From d36a988d84b35d163f98c3795fee891c41b38eb5 Mon Sep 17 00:00:00 2001 From: frank Date: Wed, 24 Aug 2011 10:37:09 -0700 Subject: [PATCH] move simulator/test to opensource --- agent-simulator/.classpath | 28 + agent-simulator/.project | 17 + .../db/create-schema-simulator.sql | 73 + agent-simulator/scripts/__old__/deletePod.sh | 13 + .../scripts/__old__/deleteServiceOffering.sh | 12 + agent-simulator/scripts/__old__/deleteVlan.sh | 13 + .../scripts/__old__/deployVirtualMachine.sh | 13 + .../scripts/__old__/listRouters.sh | 9 + .../scripts/__old__/listVirtualMachine.sh | 9 + .../scripts/__old__/queryAsyncJobResult.sh | 56 + agent-simulator/scripts/__old__/run.sh | 13 + .../scripts/__old__/setupDirectPods.sh | 18 + agent-simulator/scripts/__old__/setupHosts.sh | 25 + .../scripts/__old__/setupPodAndNetwork.sh | 41 + .../scripts/__old__/setupServiceOffering.sh | 11 + agent-simulator/scripts/__old__/setupVlan.sh | 13 + .../scripts/__old__/simulator_advanced.sh | 40 + .../scripts/__old__/simulator_basic.sh | 38 + .../scripts/__old__/startRouter.sh | 13 + agent-simulator/scripts/__old__/testQuery.sh | 9 + agent-simulator/scripts/addHostStats.py | 37 + agent-simulator/scripts/addHosts.png | Bin 0 -> 44302 bytes .../scripts/guava/__old__/1000routers.sh | 24 + .../guava/__old__/createAdminAccount.sh | 11 + .../guava/__old__/createStoragePool.sh | 7 + .../guava/__old__/createUserAccount.sh | 11 + .../scripts/guava/__old__/deleteAccount.sh | 12 + .../scripts/guava/__old__/deletePod.sh | 13 + .../guava/__old__/deleteServiceOffering.sh | 12 + .../scripts/guava/__old__/deleteVlan.sh | 13 + .../guava/__old__/deployVirtualMachine.sh | 14 + .../guava/__old__/destroyVirtualMachine.sh | 12 + .../scripts/guava/__old__/listCapacity.sh | 9 + .../scripts/guava/__old__/listEvents.sh | 9 + .../scripts/guava/__old__/listHosts.sh | 9 + .../scripts/guava/__old__/listRouters.sh | 9 + .../scripts/guava/__old__/listTemplates.sh | 9 + .../guava/__old__/listVirtualMachine.sh | 9 + agent-simulator/scripts/guava/__old__/load.sh | 15 + .../scripts/guava/__old__/networkShutDown.sh | 8 + .../scripts/guava/__old__/networkStart.sh | 8 + .../scripts/guava/__old__/reconnectStats.sh | 16 + .../scripts/guava/__old__/setup.sh | 34 + .../scripts/guava/__old__/setupDirectPods.sh | 18 + .../scripts/guava/__old__/setupHosts.sh | 10 + .../guava/__old__/setupPodAndNetwork.sh | 26 + .../guava/__old__/setupServiceOffering.sh | 11 + .../scripts/guava/__old__/setupVlan.sh | 13 + .../scripts/guava/__old__/startRouter.sh | 13 + .../guava/__old__/startVirtualMachine.sh | 13 + .../guava/__old__/stopVirtualMachine.sh | 13 + .../scripts/guava/__old__/stress.sh | 39 + .../scripts/guava/__old__/stress2.sh | 120 + agent-simulator/scripts/run.bat | 2 + .../scripts/zucchini/__old__/deletePod.sh | 13 + .../zucchini/__old__/deleteServiceOffering.sh | 12 + .../scripts/zucchini/__old__/deleteVlan.sh | 13 + .../scripts/zucchini/__old__/deployBulk-sg.sh | 194 + .../scripts/zucchini/__old__/deployBulk.sh | 147 + .../zucchini/__old__/deployVirtualMachine.sh | 13 + .../zucchini/__old__/destroySystemVm.sh | 40 + .../zucchini/__old__/destroyVirtualMachine.sh | 12 + .../scripts/zucchini/__old__/listCapacity.sh | 9 + .../scripts/zucchini/__old__/listEvents.sh | 9 + .../scripts/zucchini/__old__/listHosts.sh | 9 + .../scripts/zucchini/__old__/listRouters.sh | 9 + .../scripts/zucchini/__old__/listTemplates.sh | 9 + .../zucchini/__old__/listVirtualMachine.sh | 9 + .../scripts/zucchini/__old__/monitor.sh | 21 + .../scripts/zucchini/__old__/newsetup.sh | 224 + .../zucchini/__old__/reconnectStats.sh | 16 + .../scripts/zucchini/__old__/setup.sh | 81 + .../zucchini/__old__/setupDirectPods.sh | 18 + .../scripts/zucchini/__old__/setupHosts.sh | 10 + .../zucchini/__old__/setupPodAndNetwork.sh | 26 + .../zucchini/__old__/setupServiceOffering.sh | 11 + .../scripts/zucchini/__old__/setupVlan.sh | 13 + .../scripts/zucchini/__old__/setup_sg.sh | 248 + .../scripts/zucchini/__old__/small.sh | 151 + .../scripts/zucchini/__old__/so_setup.sh | 7 + .../scripts/zucchini/__old__/startRouter.sh | 13 + .../zucchini/__old__/startVirtualMachine.sh | 13 + .../scripts/zucchini/__old__/stopRouter.sh | 37 + .../zucchini/__old__/stopVirtualMachine.sh | 37 + .../scripts/zucchini/__old__/zucchini219.sh | 110 + agent-simulator/scripts/zucchini/setup.py | 208 + .../scripts/zucchini/tests/testProvision.py | 101 + .../zucchini/zucchini.configuration.sql | 29 + .../src/com/cloud/agent/MetricsCollector.java | 110 + .../src/com/cloud/agent/MockVmMetrics.java | 210 + .../src/com/cloud/agent/MultiCaster.java | 149 + .../com/cloud/agent/MultiCasterListener.java | 25 + .../src/com/cloud/agent/SimulatorCmd.java | 40 + .../cloud/agent/SimulatorMigrateVmCmd.java | 86 + .../cloud/agent/manager/MockAgentManager.java | 48 + .../agent/manager/MockAgentManagerImpl.java | 353 + .../agent/manager/MockStorageManager.java | 81 + .../agent/manager/MockStorageManagerImpl.java | 658 ++ .../cloud/agent/manager/MockVmManager.java | 86 + .../agent/manager/MockVmManagerImpl.java | 398 + .../cloud/agent/manager/SimulatorManager.java | 60 + .../agent/manager/SimulatorManagerImpl.java | 275 + .../api/commands/ConfigureSimulatorCmd.java | 65 + .../SimulatorComponentLibrary.java | 36 + .../com/cloud/resource/AgentResourceBase.java | 278 + .../cloud/resource/AgentRoutingResource.java | 320 + .../cloud/resource/AgentStorageResource.java | 112 + .../cloud/resource/SimulatorDiscoverer.java | 308 + .../SimulatorSecondaryDiscoverer.java | 30 + .../server/ManagementServerSimulatorImpl.java | 17 + .../cloud/simulator/MockConfigurationVO.java | 105 + .../src/com/cloud/simulator/MockHost.java | 46 + .../src/com/cloud/simulator/MockHostVO.java | 264 + .../com/cloud/simulator/MockSecStorageVO.java | 64 + .../cloud/simulator/MockSecurityRulesVO.java | 88 + .../cloud/simulator/MockStoragePoolVO.java | 90 + .../src/com/cloud/simulator/MockVMVO.java | 110 + .../src/com/cloud/simulator/MockVm.java | 33 + .../src/com/cloud/simulator/MockVolumeVO.java | 106 + .../com/cloud/simulator/SimulatorGuru.java | 61 + .../simulator/dao/MockConfigurationDao.java | 10 + .../dao/MockConfigurationDaoImpl.java | 91 + .../com/cloud/simulator/dao/MockHostDao.java | 11 + .../cloud/simulator/dao/MockHostDaoImpl.java | 42 + .../simulator/dao/MockSecStorageDao.java | 8 + .../simulator/dao/MockSecStorageDaoImpl.java | 28 + .../simulator/dao/MockSecurityRulesDao.java | 11 + .../dao/MockSecurityRulesDaoImpl.java | 47 + .../simulator/dao/MockStoragePoolDao.java | 9 + .../simulator/dao/MockStoragePoolDaoImpl.java | 41 + .../com/cloud/simulator/dao/MockVMDao.java | 13 + .../cloud/simulator/dao/MockVMDaoImpl.java | 75 + .../cloud/simulator/dao/MockVolumeDao.java | 14 + .../simulator/dao/MockVolumeDaoImpl.java | 85 + .../commands-simulator.properties.in | 1 + .../tomcatconf/components-simulator.xml.in | 35 + build/build-tests.xml | 248 + build/package.xml | 12 +- test/.classpath | 17 + test/.project | 19 + test/bindir/cloud-run-test.in | 38 + test/conf/README | 8 + test/conf/config.xml | 86 + test/conf/deploy.properties | 14 + test/conf/deploy.xml | 166 + test/conf/log4j-stdout.properties | 6 + test/conf/log4j.properties | 14 + test/conf/templates.sql | 1 + test/conf/tool.properties | 6 + test/metadata/adapter.xml | 318 + .../delegated_admin_cleanup.xml | 108 + .../delegated_admin_createusers.xml | 294 + .../delegated_admin_verify_part1.xml | 402 + .../delegated_admin_verify_part2.xml | 934 ++ .../pickuser_domainlevel1_domainlevel2.xml | 104 + ...er_domainlevel1admin_domainlevel1admin.xml | 104 + .../pickuser_domainlevel1admin_rootadmin.xml | 104 + ...ckuser_domainlevel2_child_domainlevel1.xml | 104 + ...ser_domainlevel2_nonchild_domainlevel1.xml | 104 + .../pickuser_domainlevel2_rootadmin1.xml | 104 + .../pickuser_rootadmin1_rootadmin2.xml | 104 + ...ickuser_rootadmin_vs_domainlevel1admin.xml | 104 + test/metadata/func/commands | 174 + test/metadata/func/directnw_regression.xml | 1892 ++++ test/metadata/func/error_events.properties | 15 + test/metadata/func/expunge.xml | 1189 +++ test/metadata/func/external_firewall.xml | 371 + test/metadata/func/flatnetwork.xml | 515 + test/metadata/func/ha.xml | 349 + test/metadata/func/iso.xml | 889 ++ test/metadata/func/loadbalancers.xml | 2018 ++++ .../func/localstorage_volume_test.xml | 135 + test/metadata/func/mgmtvmsync.xml | 633 ++ test/metadata/func/portforwarding.xml | 1050 +++ test/metadata/func/private_templates.xml | 893 ++ test/metadata/func/regression.xml | 4425 +++++++++ .../func/regression_events.properties | 26 + test/metadata/func/regression_new.xml | 7654 +++++++++++++++ test/metadata/func/regression_test.xml | 3465 +++++++ test/metadata/func/regression_user.xml | 2364 +++++ test/metadata/func/regression_works.xml | 8400 +++++++++++++++++ test/metadata/func/resource_limits.xml | 1876 ++++ test/metadata/func/roughflatstress.xml | 673 ++ test/metadata/func/roughregression.xml | 5994 ++++++++++++ test/metadata/func/sanity.xml | 360 + test/metadata/func/securitygroups.xml | 752 ++ .../func/sharedstorage_volume_test.xml | 1356 +++ test/metadata/func/snapshot_iso.xml | 628 ++ test/metadata/func/snapshots.xml | 809 ++ test/metadata/func/snapshots_contd.xml | 608 ++ test/metadata/func/srxstresswithportfwd.xml | 577 ++ test/metadata/func/static_nat.xml | 898 ++ test/metadata/func/templatedwnldstress.xml | 739 ++ test/metadata/func/templates_sync.xml | 1371 +++ test/metadata/func/userapi.xml | 1275 +++ test/metadata/func/vmapi.xml | 873 ++ test/metadata/func/vmsync.xml | 389 + test/scripts/bootstrap-regression.sh | 40 + test/scripts/build-env.sh | 33 + test/scripts/certDeleteEC2.sh | 28 + test/scripts/certSubmitEC2.sh | 28 + test/scripts/checkLog.sh | 71 + test/scripts/checkOutOfMemory.sh | 39 + test/scripts/cleanparallel.sh | 117 + test/scripts/deploy-and-run-regression.sh | 53 + test/scripts/deploy.sh | 174 + test/scripts/deploycluster.sh | 79 + test/scripts/executeUserAPI.sh | 36 + test/scripts/invoke.sh | 30 + test/scripts/regression.sh | 27 + test/scripts/run.bat | 1 + test/scripts/run.sh | 36 + test/scripts/sign.sh | 28 + test/scripts/signEC2.sh | 29 + test/scripts/usage/allocated.sh | 88 + test/scripts/usage/network.sh | 73 + test/scripts/usage/running.sh | 89 + test/scripts/usage/volume_usage.sh | 163 + test/scripts/usercloud.properties | 4 + test/scripts/wget.exe | Bin 0 -> 162816 bytes test/scripts/xen/corrupttemplate.sh | 53 + test/scripts/xen/createfaketemplate.sh | 55 + test/scripts/xen/killvm.sh | 54 + test/scripts/xen/listtemplate.sh | 49 + test/scripts/xen/listvdi.sh | 60 + test/scripts/xen/listvm.sh | 60 + test/scripts/xen/ms.sh | 42 + test/scripts/xen/removetemplate.sh | 53 + test/scripts/xen/shutdown.sh | 54 + test/scripts/xen/sleep.sh | 35 + test/scripts/xen/ssh.sh | 49 + test/src/com/cloud/sample/Base64.java | 1759 ++++ .../cloud/sample/UserCloudAPIExecutor.java | 194 + .../cloud/test/longrun/BuildGuestNetwork.java | 131 + .../test/longrun/PerformanceWithAPI.java | 212 + test/src/com/cloud/test/longrun/User.java | 241 + .../cloud/test/longrun/VirtualMachine.java | 119 + .../com/cloud/test/longrun/guestNetwork.java | 110 + .../com/cloud/test/regression/ApiCommand.java | 865 ++ .../com/cloud/test/regression/ConfigTest.java | 134 + .../test/regression/DelegatedAdminTest.java | 135 + .../src/com/cloud/test/regression/Deploy.java | 117 + .../cloud/test/regression/EventsApiTest.java | 181 + test/src/com/cloud/test/regression/HA.java | 81 + .../test/regression/LoadBalancingTest.java | 150 + .../test/regression/PortForwardingTest.java | 149 + .../com/cloud/test/regression/SanityTest.java | 90 + test/src/com/cloud/test/regression/Test.java | 89 + .../com/cloud/test/regression/TestCase.java | 143 + .../cloud/test/regression/TestCaseEngine.java | 291 + .../com/cloud/test/regression/VMApiTest.java | 98 + test/src/com/cloud/test/stress/SshTest.java | 93 + .../test/stress/StressTestDirectAttach.java | 1531 +++ .../cloud/test/stress/TestClientWithAPI.java | 2265 +++++ test/src/com/cloud/test/stress/WgetTest.java | 164 + .../test/ui/AbstractSeleniumTestCase.java | 63 + .../com/cloud/test/ui/AddAndDeleteAISO.java | 120 + .../cloud/test/ui/AddAndDeleteATemplate.java | 118 + .../src/com/cloud/test/ui/UIScenarioTest.java | 87 + .../com/cloud/test/utils/ConsoleProxy.java | 117 + .../com/cloud/test/utils/IpSqlGenerator.java | 91 + .../com/cloud/test/utils/ProxyLoadTemp.java | 125 + test/src/com/cloud/test/utils/SignEC2.java | 151 + .../src/com/cloud/test/utils/SignRequest.java | 117 + .../cloud/test/utils/SqlDataGenerator.java | 51 + test/src/com/cloud/test/utils/SubmitCert.java | 206 + test/src/com/cloud/test/utils/TestClient.java | 384 + .../com/cloud/test/utils/UtilsForTest.java | 240 + 268 files changed, 80347 insertions(+), 1 deletion(-) create mode 100644 agent-simulator/.classpath create mode 100644 agent-simulator/.project create mode 100644 agent-simulator/db/create-schema-simulator.sql create mode 100755 agent-simulator/scripts/__old__/deletePod.sh create mode 100755 agent-simulator/scripts/__old__/deleteServiceOffering.sh create mode 100755 agent-simulator/scripts/__old__/deleteVlan.sh create mode 100755 agent-simulator/scripts/__old__/deployVirtualMachine.sh create mode 100755 agent-simulator/scripts/__old__/listRouters.sh create mode 100755 agent-simulator/scripts/__old__/listVirtualMachine.sh create mode 100755 agent-simulator/scripts/__old__/queryAsyncJobResult.sh create mode 100644 agent-simulator/scripts/__old__/run.sh create mode 100755 agent-simulator/scripts/__old__/setupDirectPods.sh create mode 100755 agent-simulator/scripts/__old__/setupHosts.sh create mode 100755 agent-simulator/scripts/__old__/setupPodAndNetwork.sh create mode 100755 agent-simulator/scripts/__old__/setupServiceOffering.sh create mode 100755 agent-simulator/scripts/__old__/setupVlan.sh create mode 100755 agent-simulator/scripts/__old__/simulator_advanced.sh create mode 100755 agent-simulator/scripts/__old__/simulator_basic.sh create mode 100755 agent-simulator/scripts/__old__/startRouter.sh create mode 100755 agent-simulator/scripts/__old__/testQuery.sh create mode 100644 agent-simulator/scripts/addHostStats.py create mode 100644 agent-simulator/scripts/addHosts.png create mode 100755 agent-simulator/scripts/guava/__old__/1000routers.sh create mode 100755 agent-simulator/scripts/guava/__old__/createAdminAccount.sh create mode 100755 agent-simulator/scripts/guava/__old__/createStoragePool.sh create mode 100755 agent-simulator/scripts/guava/__old__/createUserAccount.sh create mode 100755 agent-simulator/scripts/guava/__old__/deleteAccount.sh create mode 100755 agent-simulator/scripts/guava/__old__/deletePod.sh create mode 100755 agent-simulator/scripts/guava/__old__/deleteServiceOffering.sh create mode 100755 agent-simulator/scripts/guava/__old__/deleteVlan.sh create mode 100755 agent-simulator/scripts/guava/__old__/deployVirtualMachine.sh create mode 100755 agent-simulator/scripts/guava/__old__/destroyVirtualMachine.sh create mode 100755 agent-simulator/scripts/guava/__old__/listCapacity.sh create mode 100755 agent-simulator/scripts/guava/__old__/listEvents.sh create mode 100755 agent-simulator/scripts/guava/__old__/listHosts.sh create mode 100755 agent-simulator/scripts/guava/__old__/listRouters.sh create mode 100755 agent-simulator/scripts/guava/__old__/listTemplates.sh create mode 100755 agent-simulator/scripts/guava/__old__/listVirtualMachine.sh create mode 100755 agent-simulator/scripts/guava/__old__/load.sh create mode 100755 agent-simulator/scripts/guava/__old__/networkShutDown.sh create mode 100755 agent-simulator/scripts/guava/__old__/networkStart.sh create mode 100755 agent-simulator/scripts/guava/__old__/reconnectStats.sh create mode 100755 agent-simulator/scripts/guava/__old__/setup.sh create mode 100755 agent-simulator/scripts/guava/__old__/setupDirectPods.sh create mode 100755 agent-simulator/scripts/guava/__old__/setupHosts.sh create mode 100755 agent-simulator/scripts/guava/__old__/setupPodAndNetwork.sh create mode 100755 agent-simulator/scripts/guava/__old__/setupServiceOffering.sh create mode 100755 agent-simulator/scripts/guava/__old__/setupVlan.sh create mode 100755 agent-simulator/scripts/guava/__old__/startRouter.sh create mode 100755 agent-simulator/scripts/guava/__old__/startVirtualMachine.sh create mode 100755 agent-simulator/scripts/guava/__old__/stopVirtualMachine.sh create mode 100755 agent-simulator/scripts/guava/__old__/stress.sh create mode 100755 agent-simulator/scripts/guava/__old__/stress2.sh create mode 100644 agent-simulator/scripts/run.bat create mode 100755 agent-simulator/scripts/zucchini/__old__/deletePod.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/deleteServiceOffering.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/deleteVlan.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/deployBulk-sg.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/deployBulk.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/deployVirtualMachine.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/destroySystemVm.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/destroyVirtualMachine.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/listCapacity.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/listEvents.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/listHosts.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/listRouters.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/listTemplates.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/listVirtualMachine.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/monitor.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/newsetup.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/reconnectStats.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/setup.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/setupDirectPods.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/setupHosts.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/setupPodAndNetwork.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/setupServiceOffering.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/setupVlan.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/setup_sg.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/small.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/so_setup.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/startRouter.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/startVirtualMachine.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/stopRouter.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/stopVirtualMachine.sh create mode 100755 agent-simulator/scripts/zucchini/__old__/zucchini219.sh create mode 100644 agent-simulator/scripts/zucchini/setup.py create mode 100644 agent-simulator/scripts/zucchini/tests/testProvision.py create mode 100644 agent-simulator/scripts/zucchini/zucchini.configuration.sql create mode 100644 agent-simulator/src/com/cloud/agent/MetricsCollector.java create mode 100644 agent-simulator/src/com/cloud/agent/MockVmMetrics.java create mode 100644 agent-simulator/src/com/cloud/agent/MultiCaster.java create mode 100644 agent-simulator/src/com/cloud/agent/MultiCasterListener.java create mode 100644 agent-simulator/src/com/cloud/agent/SimulatorCmd.java create mode 100644 agent-simulator/src/com/cloud/agent/SimulatorMigrateVmCmd.java create mode 100644 agent-simulator/src/com/cloud/agent/manager/MockAgentManager.java create mode 100644 agent-simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java create mode 100644 agent-simulator/src/com/cloud/agent/manager/MockStorageManager.java create mode 100644 agent-simulator/src/com/cloud/agent/manager/MockStorageManagerImpl.java create mode 100644 agent-simulator/src/com/cloud/agent/manager/MockVmManager.java create mode 100644 agent-simulator/src/com/cloud/agent/manager/MockVmManagerImpl.java create mode 100644 agent-simulator/src/com/cloud/agent/manager/SimulatorManager.java create mode 100644 agent-simulator/src/com/cloud/agent/manager/SimulatorManagerImpl.java create mode 100644 agent-simulator/src/com/cloud/api/commands/ConfigureSimulatorCmd.java create mode 100644 agent-simulator/src/com/cloud/configuration/SimulatorComponentLibrary.java create mode 100644 agent-simulator/src/com/cloud/resource/AgentResourceBase.java create mode 100644 agent-simulator/src/com/cloud/resource/AgentRoutingResource.java create mode 100644 agent-simulator/src/com/cloud/resource/AgentStorageResource.java create mode 100755 agent-simulator/src/com/cloud/resource/SimulatorDiscoverer.java create mode 100644 agent-simulator/src/com/cloud/resource/SimulatorSecondaryDiscoverer.java create mode 100644 agent-simulator/src/com/cloud/server/ManagementServerSimulatorImpl.java create mode 100644 agent-simulator/src/com/cloud/simulator/MockConfigurationVO.java create mode 100644 agent-simulator/src/com/cloud/simulator/MockHost.java create mode 100644 agent-simulator/src/com/cloud/simulator/MockHostVO.java create mode 100644 agent-simulator/src/com/cloud/simulator/MockSecStorageVO.java create mode 100644 agent-simulator/src/com/cloud/simulator/MockSecurityRulesVO.java create mode 100644 agent-simulator/src/com/cloud/simulator/MockStoragePoolVO.java create mode 100644 agent-simulator/src/com/cloud/simulator/MockVMVO.java create mode 100644 agent-simulator/src/com/cloud/simulator/MockVm.java create mode 100644 agent-simulator/src/com/cloud/simulator/MockVolumeVO.java create mode 100644 agent-simulator/src/com/cloud/simulator/SimulatorGuru.java create mode 100644 agent-simulator/src/com/cloud/simulator/dao/MockConfigurationDao.java create mode 100644 agent-simulator/src/com/cloud/simulator/dao/MockConfigurationDaoImpl.java create mode 100644 agent-simulator/src/com/cloud/simulator/dao/MockHostDao.java create mode 100644 agent-simulator/src/com/cloud/simulator/dao/MockHostDaoImpl.java create mode 100644 agent-simulator/src/com/cloud/simulator/dao/MockSecStorageDao.java create mode 100644 agent-simulator/src/com/cloud/simulator/dao/MockSecStorageDaoImpl.java create mode 100644 agent-simulator/src/com/cloud/simulator/dao/MockSecurityRulesDao.java create mode 100644 agent-simulator/src/com/cloud/simulator/dao/MockSecurityRulesDaoImpl.java create mode 100644 agent-simulator/src/com/cloud/simulator/dao/MockStoragePoolDao.java create mode 100644 agent-simulator/src/com/cloud/simulator/dao/MockStoragePoolDaoImpl.java create mode 100644 agent-simulator/src/com/cloud/simulator/dao/MockVMDao.java create mode 100644 agent-simulator/src/com/cloud/simulator/dao/MockVMDaoImpl.java create mode 100644 agent-simulator/src/com/cloud/simulator/dao/MockVolumeDao.java create mode 100644 agent-simulator/src/com/cloud/simulator/dao/MockVolumeDaoImpl.java create mode 100644 agent-simulator/tomcatconf/commands-simulator.properties.in create mode 100755 agent-simulator/tomcatconf/components-simulator.xml.in create mode 100755 build/build-tests.xml create mode 100644 test/.classpath create mode 100644 test/.project create mode 100755 test/bindir/cloud-run-test.in create mode 100644 test/conf/README create mode 100644 test/conf/config.xml create mode 100644 test/conf/deploy.properties create mode 100644 test/conf/deploy.xml create mode 100644 test/conf/log4j-stdout.properties create mode 100644 test/conf/log4j.properties create mode 100644 test/conf/templates.sql create mode 100644 test/conf/tool.properties create mode 100644 test/metadata/adapter.xml create mode 100644 test/metadata/delegatedAdmin/delegated_admin_cleanup.xml create mode 100644 test/metadata/delegatedAdmin/delegated_admin_createusers.xml create mode 100644 test/metadata/delegatedAdmin/delegated_admin_verify_part1.xml create mode 100644 test/metadata/delegatedAdmin/delegated_admin_verify_part2.xml create mode 100644 test/metadata/delegatedAdmin/pickuser_domainlevel1_domainlevel2.xml create mode 100644 test/metadata/delegatedAdmin/pickuser_domainlevel1admin_domainlevel1admin.xml create mode 100644 test/metadata/delegatedAdmin/pickuser_domainlevel1admin_rootadmin.xml create mode 100644 test/metadata/delegatedAdmin/pickuser_domainlevel2_child_domainlevel1.xml create mode 100644 test/metadata/delegatedAdmin/pickuser_domainlevel2_nonchild_domainlevel1.xml create mode 100644 test/metadata/delegatedAdmin/pickuser_domainlevel2_rootadmin1.xml create mode 100644 test/metadata/delegatedAdmin/pickuser_rootadmin1_rootadmin2.xml create mode 100644 test/metadata/delegatedAdmin/pickuser_rootadmin_vs_domainlevel1admin.xml create mode 100644 test/metadata/func/commands create mode 100644 test/metadata/func/directnw_regression.xml create mode 100644 test/metadata/func/error_events.properties create mode 100644 test/metadata/func/expunge.xml create mode 100644 test/metadata/func/external_firewall.xml create mode 100644 test/metadata/func/flatnetwork.xml create mode 100644 test/metadata/func/ha.xml create mode 100644 test/metadata/func/iso.xml create mode 100644 test/metadata/func/loadbalancers.xml create mode 100644 test/metadata/func/localstorage_volume_test.xml create mode 100644 test/metadata/func/mgmtvmsync.xml create mode 100644 test/metadata/func/portforwarding.xml create mode 100644 test/metadata/func/private_templates.xml create mode 100644 test/metadata/func/regression.xml create mode 100644 test/metadata/func/regression_events.properties create mode 100644 test/metadata/func/regression_new.xml create mode 100644 test/metadata/func/regression_test.xml create mode 100644 test/metadata/func/regression_user.xml create mode 100644 test/metadata/func/regression_works.xml create mode 100644 test/metadata/func/resource_limits.xml create mode 100644 test/metadata/func/roughflatstress.xml create mode 100644 test/metadata/func/roughregression.xml create mode 100644 test/metadata/func/sanity.xml create mode 100644 test/metadata/func/securitygroups.xml create mode 100644 test/metadata/func/sharedstorage_volume_test.xml create mode 100644 test/metadata/func/snapshot_iso.xml create mode 100644 test/metadata/func/snapshots.xml create mode 100644 test/metadata/func/snapshots_contd.xml create mode 100644 test/metadata/func/srxstresswithportfwd.xml create mode 100644 test/metadata/func/static_nat.xml create mode 100644 test/metadata/func/templatedwnldstress.xml create mode 100644 test/metadata/func/templates_sync.xml create mode 100644 test/metadata/func/userapi.xml create mode 100644 test/metadata/func/vmapi.xml create mode 100644 test/metadata/func/vmsync.xml create mode 100755 test/scripts/bootstrap-regression.sh create mode 100755 test/scripts/build-env.sh create mode 100755 test/scripts/certDeleteEC2.sh create mode 100755 test/scripts/certSubmitEC2.sh create mode 100755 test/scripts/checkLog.sh create mode 100755 test/scripts/checkOutOfMemory.sh create mode 100755 test/scripts/cleanparallel.sh create mode 100755 test/scripts/deploy-and-run-regression.sh create mode 100755 test/scripts/deploy.sh create mode 100755 test/scripts/deploycluster.sh create mode 100755 test/scripts/executeUserAPI.sh create mode 100755 test/scripts/invoke.sh create mode 100755 test/scripts/regression.sh create mode 100644 test/scripts/run.bat create mode 100755 test/scripts/run.sh create mode 100755 test/scripts/sign.sh create mode 100755 test/scripts/signEC2.sh create mode 100755 test/scripts/usage/allocated.sh create mode 100755 test/scripts/usage/network.sh create mode 100755 test/scripts/usage/running.sh create mode 100755 test/scripts/usage/volume_usage.sh create mode 100644 test/scripts/usercloud.properties create mode 100644 test/scripts/wget.exe create mode 100755 test/scripts/xen/corrupttemplate.sh create mode 100755 test/scripts/xen/createfaketemplate.sh create mode 100755 test/scripts/xen/killvm.sh create mode 100755 test/scripts/xen/listtemplate.sh create mode 100755 test/scripts/xen/listvdi.sh create mode 100755 test/scripts/xen/listvm.sh create mode 100755 test/scripts/xen/ms.sh create mode 100755 test/scripts/xen/removetemplate.sh create mode 100755 test/scripts/xen/shutdown.sh create mode 100755 test/scripts/xen/sleep.sh create mode 100755 test/scripts/xen/ssh.sh create mode 100644 test/src/com/cloud/sample/Base64.java create mode 100644 test/src/com/cloud/sample/UserCloudAPIExecutor.java create mode 100644 test/src/com/cloud/test/longrun/BuildGuestNetwork.java create mode 100644 test/src/com/cloud/test/longrun/PerformanceWithAPI.java create mode 100644 test/src/com/cloud/test/longrun/User.java create mode 100644 test/src/com/cloud/test/longrun/VirtualMachine.java create mode 100644 test/src/com/cloud/test/longrun/guestNetwork.java create mode 100644 test/src/com/cloud/test/regression/ApiCommand.java create mode 100644 test/src/com/cloud/test/regression/ConfigTest.java create mode 100644 test/src/com/cloud/test/regression/DelegatedAdminTest.java create mode 100644 test/src/com/cloud/test/regression/Deploy.java create mode 100644 test/src/com/cloud/test/regression/EventsApiTest.java create mode 100644 test/src/com/cloud/test/regression/HA.java create mode 100644 test/src/com/cloud/test/regression/LoadBalancingTest.java create mode 100644 test/src/com/cloud/test/regression/PortForwardingTest.java create mode 100644 test/src/com/cloud/test/regression/SanityTest.java create mode 100644 test/src/com/cloud/test/regression/Test.java create mode 100644 test/src/com/cloud/test/regression/TestCase.java create mode 100644 test/src/com/cloud/test/regression/TestCaseEngine.java create mode 100644 test/src/com/cloud/test/regression/VMApiTest.java create mode 100644 test/src/com/cloud/test/stress/SshTest.java create mode 100644 test/src/com/cloud/test/stress/StressTestDirectAttach.java create mode 100644 test/src/com/cloud/test/stress/TestClientWithAPI.java create mode 100644 test/src/com/cloud/test/stress/WgetTest.java create mode 100644 test/src/com/cloud/test/ui/AbstractSeleniumTestCase.java create mode 100644 test/src/com/cloud/test/ui/AddAndDeleteAISO.java create mode 100644 test/src/com/cloud/test/ui/AddAndDeleteATemplate.java create mode 100644 test/src/com/cloud/test/ui/UIScenarioTest.java create mode 100644 test/src/com/cloud/test/utils/ConsoleProxy.java create mode 100644 test/src/com/cloud/test/utils/IpSqlGenerator.java create mode 100644 test/src/com/cloud/test/utils/ProxyLoadTemp.java create mode 100644 test/src/com/cloud/test/utils/SignEC2.java create mode 100644 test/src/com/cloud/test/utils/SignRequest.java create mode 100644 test/src/com/cloud/test/utils/SqlDataGenerator.java create mode 100644 test/src/com/cloud/test/utils/SubmitCert.java create mode 100644 test/src/com/cloud/test/utils/TestClient.java create mode 100644 test/src/com/cloud/test/utils/UtilsForTest.java diff --git a/agent-simulator/.classpath b/agent-simulator/.classpath new file mode 100644 index 00000000000..264339135e1 --- /dev/null +++ b/agent-simulator/.classpath @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/agent-simulator/.project b/agent-simulator/.project new file mode 100644 index 00000000000..f3d551aaa5e --- /dev/null +++ b/agent-simulator/.project @@ -0,0 +1,17 @@ + + + agent-simulator + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/agent-simulator/db/create-schema-simulator.sql b/agent-simulator/db/create-schema-simulator.sql new file mode 100644 index 00000000000..7cb7ef908a1 --- /dev/null +++ b/agent-simulator/db/create-schema-simulator.sql @@ -0,0 +1,73 @@ +DROP TABLE IF EXISTS `cloud`.`mockhost`; +DROP TABLE IF EXISTS `cloud`.`mocksecstorage`; +DROP TABLE IF EXISTS `cloud`.`mockstoragepool`; +DROP TABLE IF EXISTS `cloud`.`mockvm`; +DROP TABLE IF EXISTS `cloud`.`mockvolume`; + +CREATE TABLE `cloud`.`mockhost` ( + `id` bigint unsigned NOT NULL auto_increment, + `name` varchar(255) NOT NULL, + `private_ip_address` char(40), + `private_mac_address` varchar(17), + `private_netmask` varchar(15), + `storage_ip_address` char(40), + `storage_netmask` varchar(15), + `storage_mac_address` varchar(17), + `public_ip_address` char(40), + `public_netmask` varchar(15), + `public_mac_address` varchar(17), + `guid` varchar(255) UNIQUE, + `version` varchar(40) NOT NULL, + `data_center_id` bigint unsigned NOT NULL, + `pod_id` bigint unsigned, + `cluster_id` bigint unsigned COMMENT 'foreign key to cluster', + `cpus` int(10) unsigned, + `speed` int(10) unsigned, + `ram` bigint unsigned, + `capabilities` varchar(255) COMMENT 'host capabilities in comma separated list', + `vm_id` bigint unsigned, + `resource` varchar(255) DEFAULT NULL COMMENT 'If it is a local resource, this is the class name', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `cloud`.`mocksecstorage` ( + `id` bigint unsigned NOT NULL auto_increment, + `url` varchar(255), + `capacity` bigint unsigned, + `mount_point` varchar(255), + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `cloud`.`mockstoragepool` ( + `id` bigint unsigned NOT NULL auto_increment, + `guid` varchar(255), + `mount_point` varchar(255), + `capacity` bigint, + `pool_type` varchar(40), + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + +CREATE TABLE `cloud`.`mockvm` ( + `id` bigint unsigned NOT NULL auto_increment, + `name` varchar(255), + `host_id` bigint unsigned, + `type` varchar(40), + `state` varchar(40), + `vnc_port` bigint unsigned, + `memory` bigint unsigned, + `cpu` bigint unsigned, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + +CREATE TABLE `cloud`.`mockvolume` ( + `id` bigint unsigned NOT NULL auto_increment, + `name` varchar(255), + `size` bigint unsigned, + `path` varchar(255), + `pool_id` bigint unsigned, + `type` varchar(40), + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + diff --git a/agent-simulator/scripts/__old__/deletePod.sh b/agent-simulator/scripts/__old__/deletePod.sh new file mode 100755 index 00000000000..3fa60735bbc --- /dev/null +++ b/agent-simulator/scripts/__old__/deletePod.sh @@ -0,0 +1,13 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 + +pod_query="GET http://10.91.30.226:8096/client/?command=deletePod&id=$x HTTP/1.0\n\n" + + +echo -e $pod_query | nc -v -q 20 10.91.30.226 8096 + diff --git a/agent-simulator/scripts/__old__/deleteServiceOffering.sh b/agent-simulator/scripts/__old__/deleteServiceOffering.sh new file mode 100755 index 00000000000..e3a204f44cb --- /dev/null +++ b/agent-simulator/scripts/__old__/deleteServiceOffering.sh @@ -0,0 +1,12 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 + +delete_so="GET http://10.91.30.226:8096/client/?command=deleteServiceOffering&id=$x HTTP/1.0\n\n" + +echo -e $delete_so | nc -v -q 20 10.91.30.226 8096 + diff --git a/agent-simulator/scripts/__old__/deleteVlan.sh b/agent-simulator/scripts/__old__/deleteVlan.sh new file mode 100755 index 00000000000..5cc3cd2b619 --- /dev/null +++ b/agent-simulator/scripts/__old__/deleteVlan.sh @@ -0,0 +1,13 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 + +vlan_query="GET http://10.91.30.226:8096/client/?command=deleteVlanIpRange&id=$x HTTP/1.0\n\n" + + +echo -e $vlan_query | nc -v -q 20 10.91.30.226 8096 + diff --git a/agent-simulator/scripts/__old__/deployVirtualMachine.sh b/agent-simulator/scripts/__old__/deployVirtualMachine.sh new file mode 100755 index 00000000000..4c9200cc4e3 --- /dev/null +++ b/agent-simulator/scripts/__old__/deployVirtualMachine.sh @@ -0,0 +1,13 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +zoneid=$1 +templateId=$2 +serviceOfferingId=$3 + +query="GET http://10.91.30.226:8096/client/?command=deployVirtualMachine&zoneId=$1&templateId=$2&serviceOfferingId=$3&account=admin&domainid=1 HTTP/1.0\n\n" + +echo -e $query | nc -v -q 20 10.91.30.226 8096 diff --git a/agent-simulator/scripts/__old__/listRouters.sh b/agent-simulator/scripts/__old__/listRouters.sh new file mode 100755 index 00000000000..5a4fc23dade --- /dev/null +++ b/agent-simulator/scripts/__old__/listRouters.sh @@ -0,0 +1,9 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +query="GET http://10.91.30.226:8096/client/?command=listRouters&zoneId=$1&account=admin&domainid=1 HTTP/1.0\n\n" + +echo -e $query | nc -v 10.91.30.226 8096 diff --git a/agent-simulator/scripts/__old__/listVirtualMachine.sh b/agent-simulator/scripts/__old__/listVirtualMachine.sh new file mode 100755 index 00000000000..bd810f5a395 --- /dev/null +++ b/agent-simulator/scripts/__old__/listVirtualMachine.sh @@ -0,0 +1,9 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +query="GET http://10.91.28.33:8096/client/?command=listVirtualMachines&zoneId=$1&account=admin&domainid=1 HTTP/1.0\n\n" + +echo -e $query | nc -v -q 20 10.91.28.33 8096 diff --git a/agent-simulator/scripts/__old__/queryAsyncJobResult.sh b/agent-simulator/scripts/__old__/queryAsyncJobResult.sh new file mode 100755 index 00000000000..f74ec9a1bd7 --- /dev/null +++ b/agent-simulator/scripts/__old__/queryAsyncJobResult.sh @@ -0,0 +1,56 @@ +#!/bin/bash + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + +usage() { + printf "Query job result Usage: %s: -h management-server -j jobid\n" $(basename $0) >&2 +} + +#options +jflag= +hflag= + +jobid= +host="127.0.0.1" #defaults to localhost + +while getopts 'h:j:' OPTION +do + case $OPTION in + h) hflag=1 + host="$OPTARG" + ;; + j) jflag=1 + jobid="$OPTARG" + ;; + ?) usage + exit 2 + ;; + esac +done + +if [ $jflag != "1" ] +then + usage + exit 2 +fi + + +job_query="GET http://$host:8096/client/?command=queryAsyncJobResult&jobid=$jobid HTTP/1.0\n\n" +echo -e $job_query | nc -v -w 60 $host 8096 diff --git a/agent-simulator/scripts/__old__/run.sh b/agent-simulator/scripts/__old__/run.sh new file mode 100644 index 00000000000..a1e54c7b062 --- /dev/null +++ b/agent-simulator/scripts/__old__/run.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + + + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +#run.sh runs the agent simulator client. +java -cp cloud-utils.jar:agent-simulator.jar:log4j-1.2.15.jar:apache-log4j-extras-1.0.jar:ws-commons-util-1.0.2.jar:xmlrpc-client-3.1.3.jar:cloud-agent.jar:cloud-core.jar:xmlrpc-common-3.1.3.jar:javaee-api-5.0-1.jar:gson-1.3.jar:commons-httpclient-3.1.jar:commons-logging-1.1.1.jar:commons-codec-1.4.jar:commons-collections-3.2.1.jar:commons-pool-1.4.jar:.:./conf com.cloud.agent.AgentSimulator $@ + + diff --git a/agent-simulator/scripts/__old__/setupDirectPods.sh b/agent-simulator/scripts/__old__/setupDirectPods.sh new file mode 100755 index 00000000000..fd1b8c2db5c --- /dev/null +++ b/agent-simulator/scripts/__old__/setupDirectPods.sh @@ -0,0 +1,18 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 +y=$2 +name=$3 + +pod_query="GET http://10.91.30.226:8096/client/?command=createPod&zoneId=1&name=SSP$name&cidr=182.$x.$y.0%2F24&startIp=182.$x.$y.2&endIp=182.$x.$y.252&gateway=182.$x.$y.1 +HTTP/1.0\n\n" + +echo -e $pod_query | nc -v -q 20 10.91.30.226 8096 + +#vlan_query="GET http://10.91.30.226/client/?command=createVlanIpRange&vlan=untagged&zoneid=1&podId=$name&forVirtualNetwork=false&gateway=172.$y.$x.1&netmask=255.255.255.0&startip=172.$y.$x.2&endip=172.$y.$x.252 HTTP/1.0\n\n" + +#echo -e $vlan_query | nc -v -q 20 10.91.30.226 8096 diff --git a/agent-simulator/scripts/__old__/setupHosts.sh b/agent-simulator/scripts/__old__/setupHosts.sh new file mode 100755 index 00000000000..def8b0aafbc --- /dev/null +++ b/agent-simulator/scripts/__old__/setupHosts.sh @@ -0,0 +1,25 @@ + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + +name=$1 + +host_query="GET http://10.91.30.226:8096/client/?command=addHost&zoneId=1&podId=$((name+250))&username=sim&password=sim&clustername=simulator-$name&hosttags=RP$name&url=http%3A%2F%2Fsim HTTP/1.0\n\n" +echo -e $host_query | nc -v -w 60 10.91.30.226 8096 diff --git a/agent-simulator/scripts/__old__/setupPodAndNetwork.sh b/agent-simulator/scripts/__old__/setupPodAndNetwork.sh new file mode 100755 index 00000000000..5f62c39d9ea --- /dev/null +++ b/agent-simulator/scripts/__old__/setupPodAndNetwork.sh @@ -0,0 +1,41 @@ + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + +workers=$1 +x=$2 #CIDR - 16bytes +y=$3 #CIDR - 8 bytes + +for name in `seq 1 $workers` +do + pod_query="GET http://10.91.30.226:8096/client/?command=createPod&zoneId=1&name=RP$name&cidr=182.$x.$y.0%2F24&startIp=182.$x.$y.2&endIp=182.$x.$y.252&gateway=182.$x.$y.1 HTTP/1.0\n\n" + vlan_query="GET http://10.91.30.226:8096/client/?command=createVlanIpRange&vlan=untagged&zoneid=1&podId=$((name+250))&forVirtualNetwork=false&gateway=182.$y.$x.1&netmask=255.255.255.0&startip=182.$y.$x.2&endip=182.$y.$x.252 HTTP/1.0\n\n" + so_query="GET http://10.91.30.226:8096/client/?command=createServiceOffering&name=RP$name&displayText=RP$name&storageType=local&cpuNumber=1&cpuSpeed=1000&memory=512&offerha=false&usevirtualnetwork=false&hosttags=RP$name HTTP/1.0\n\n" + + echo -e $pod_query | nc -v -w 20 10.91.30.226 8096 + echo -e $vlan_query | nc -v -w 20 10.91.30.226 8096 + echo -e $so_query | nc -v -w 20 10.91.30.226 8096 + + let x+=1 + let y+=1 +done + + + diff --git a/agent-simulator/scripts/__old__/setupServiceOffering.sh b/agent-simulator/scripts/__old__/setupServiceOffering.sh new file mode 100755 index 00000000000..7e995144335 --- /dev/null +++ b/agent-simulator/scripts/__old__/setupServiceOffering.sh @@ -0,0 +1,11 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 + +so_query="GET http://10.91.30.226:8096/client/?command=createServiceOffering&name=SO$x&displayText=SO$x&storageType=local&cpuNumber=1&cpuSpeed=1000&memory=512&offerha=false&usevirtualnetwork=false&hosttags=SP$x HTTP/1.0\n\n" + +echo -e $so_query | nc -v -q 20 10.91.30.226 8096 diff --git a/agent-simulator/scripts/__old__/setupVlan.sh b/agent-simulator/scripts/__old__/setupVlan.sh new file mode 100755 index 00000000000..2f1190f2889 --- /dev/null +++ b/agent-simulator/scripts/__old__/setupVlan.sh @@ -0,0 +1,13 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 +y=$2 +name=$3 + +vlan_query="GET http://10.91.30.226/client/?command=createVlanIpRange&vlan=untagged&zoneid=1&podId=$name&forVirtualNetwork=false&gateway=172.$x.$y.1&netmask=255.255.255.0&startip=172.$x.$y.2&endip=172.$x.$y.252 HTTP/1.0\n\n" + +echo -e $vlan_query | nc -v -q 20 10.91.30.226 8096 diff --git a/agent-simulator/scripts/__old__/simulator_advanced.sh b/agent-simulator/scripts/__old__/simulator_advanced.sh new file mode 100755 index 00000000000..0f1462d2ecd --- /dev/null +++ b/agent-simulator/scripts/__old__/simulator_advanced.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +a=$1 #CIDR - 16bytes +b=$2 #CIDR - 8 bytes +host=$3 +zoneid=$4 + +zone_query="GET http://$host/client/?command=createZone&networktype=Advanced&securitygroupenabled=false&name=SimulatorAdvanced&dns1=4.2.2.2&internaldns1=4.2.2.2&vlan=10-4000&guestcidraddress=10.1.1.0%2F24 HTTP/1.0\n\n" +echo -e $zone_query | nc -v -w 120 $host 8096 + +let x=a +let y=b +for name in `seq 1 1` +do + pod_query="GET http://$host/client/?command=createPod&zoneid=$zoneid&name=POD$name&netmask=255.255.0.0&startIp=172.$x.$y.2&endIp=172.$x.$y.252&gateway=172.$x.$y.1 HTTP/1.0\n\n" + vlan_query="GET http://$host/client/?command=createVlanIpRange&forVirtualNetwork=true&vlan=untagged&zoneid=$zoneid&podId=$name&gateway=172.$y.$x.1&netmask=255.255.255.0&startip=172.$y.$x.2&endip=172.$y.$x.252 HTTP/1.0\n\n" + echo -e $pod_query | nc -v -w 20 $host 8096 + echo -e $vlan_query | nc -v -w 20 $host 8096 +done +let x+=1 +let y+=1 + +name=1 + +clusterid=1 +for cluster in `seq 1 1` +do + cluster_query="GET http://$host/client/?command=addCluster&hypervisor=Simulator&clustertype=CloudManaged&zoneid=$zoneid&podId=1&clustername=POD$name-CLUSTER$cluster HTTP/1.0\n\n" + echo -e $cluster_query | nc -v -w 120 $host 8096 + + host_query="GET http://$host/client/?command=addHost&zoneid=$zoneid&podId=1&username=sim&password=sim&clusterid=$cluster&hypervisor=Simulator&clustertype=CloudManaged&url=http%3A%2F%2Fsim HTTP/1.0\n\n" + echo -e $host_query | nc -v -w 6000 $host 8096 + + spool_query="GET http://$host/client/?command=createStoragePool&zoneid=$zoneid&podId=1&clusterid=$cluster&name=SPOOL$cluster&url=nfs://172.1.25.$((cluster+1))/export/share/$cluster HTTP/1.0\n\n" + echo -e $spool_query | nc -v -w 6000 $host 8096 + let clusterid+=1 +done + +sstorquery="GET http://$host/client/?command=addSecondaryStorage&zoneid=$zoneid&url=nfs://172.1.25.32/export/share/ HTTP/1.0\n\n" +echo -e $sstorquery | nc -v -w 6000 $host 8096 diff --git a/agent-simulator/scripts/__old__/simulator_basic.sh b/agent-simulator/scripts/__old__/simulator_basic.sh new file mode 100755 index 00000000000..17815005f38 --- /dev/null +++ b/agent-simulator/scripts/__old__/simulator_basic.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +a=$1 #CIDR - 16bytes +b=$2 #CIDR - 8 bytes +host=$3 #MSHOST +zoneid=$4 + +zone_query="GET http://$host/client/?command=createZone&networktype=Basic&securitygroupenabled=false&name=SimulatorBasic&dns1=4.2.2.2&internaldns1=4.2.2.2&vlan=10-4000 HTTP/1.0\n\n" +echo -e $zone_query | nc -v -w 120 $host 8096 + +let x=a +let y=b + +for name in `seq $zoneid 1` +do + pod_query="GET http://$host/client/?command=createPod&zoneId=$zoneid&name=POD$name&netmask=255.255.255.0&startIp=172.$x.$y.2&endIp=172.$x.$y.252&gateway=172.$x.$y.1 HTTP/1.0\n\n" + vlan_query="GET http://$host/client/?command=createVlanIpRange&vlan=untagged&zoneid=$zoneid&podId=$name&forVirtualNetwork=false&gateway=172.$y.$x.1&netmask=255.255.255.0&startip=172.$y.$x.2&endip=172.$y.$x.252 HTTP/1.0\n\n" + echo -e $pod_query | nc -v -w 20 $host 8096 + echo -e $vlan_query | nc -v -w 20 $host 8096 + + let x+=1 + let y+=1 +done + +clusterid=1 + +for podid in `seq $zoneid 1` +do + cluster_query="GET http://$host/client/?command=addCluster&hypervisor=Simulator&clustertype=CloudManaged&zoneid=$zoneid&podId=$podid&clustername=POD$name-CLUSTER$cluster HTTP/1.0\n\n" + echo -e $cluster_query | nc -v -w 120 $host 8096 + + host_query="GET http://$host/client/?command=addHost&zoneId=$zoneid&podId=$podid&username=sim&password=sim&clusterid=$clusterid&url=http%3A%2F%2Fsim&hypervisor=Simulator&clustertype=CloudManaged HTTP/1.0\n\n" + echo -e $host_query | nc -v -w 6000 $host 8096 + let clusterid+=1 +done + +sstorquery="GET http://$host/client/?command=addSecondaryStorage&zoneid=$zoneid&url=nfs://172.1.25.32/export/share/ HTTP/1.0\n\n" +echo -e $sstorquery | nc -v -w 6000 $host 8096 diff --git a/agent-simulator/scripts/__old__/startRouter.sh b/agent-simulator/scripts/__old__/startRouter.sh new file mode 100755 index 00000000000..8667d263790 --- /dev/null +++ b/agent-simulator/scripts/__old__/startRouter.sh @@ -0,0 +1,13 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 + +start_router="GET http://10.91.30.226:8096/client/?command=startRouter&id=$x HTTP/1.0\n\n" + + +echo -e $start_router | nc -v -q 60 10.91.30.226 8096 + diff --git a/agent-simulator/scripts/__old__/testQuery.sh b/agent-simulator/scripts/__old__/testQuery.sh new file mode 100755 index 00000000000..21a7a1094b1 --- /dev/null +++ b/agent-simulator/scripts/__old__/testQuery.sh @@ -0,0 +1,9 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +test="GET http://10.91.30.226:8096/?command=listEvents&page=1 HTTP/1.0\n\n" +echo -e $test | nc -v -q 20 10.91.30.226 8096 + diff --git a/agent-simulator/scripts/addHostStats.py b/agent-simulator/scripts/addHostStats.py new file mode 100644 index 00000000000..98910fbd4d8 --- /dev/null +++ b/agent-simulator/scripts/addHostStats.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +from datetime import datetime +import sys +import matplotlib.cbook as cbook +import matplotlib.image as image +import matplotlib.pyplot as plt + +def formGraph(list_timedelta): + """ Draw a graph of the performance of host add response """ + plt.plot(list(map(lambda x:x.seconds, list_timedelta))) + plt.ylabel("time(s) to add host") + plt.xlabel("number of hosts") + plt.title("Add Host Performance") + plt.grid(True) + plt.show() + + +if __name__=='__main__': + time_file=open(sys.argv[1], 'r') + timelist=[] + diffs=[] + for line in time_file.readlines(): + try: + timelist.append(datetime.strptime(line.strip(), "%d %b %Y %H:%M:%S")) + except ValueError: + print "Unable to parse:",line + + stime=timelist[:-1] + btime=timelist[1:] + + diffs=list(map(lambda x,y: y - x,stime,btime)) + + formGraph(diffs) + + + diff --git a/agent-simulator/scripts/addHosts.png b/agent-simulator/scripts/addHosts.png new file mode 100644 index 0000000000000000000000000000000000000000..ae40e5022ed276dd79617fc21592f17756c87c34 GIT binary patch literal 44302 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 literal 0 HcmV?d00001 diff --git a/agent-simulator/scripts/guava/__old__/1000routers.sh b/agent-simulator/scripts/guava/__old__/1000routers.sh new file mode 100755 index 00000000000..ee0f6b6a7e7 --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/1000routers.sh @@ -0,0 +1,24 @@ +# +# Copyright (C) 2011 Cloud.com, Inc. All rights reserved. +# + + + + +zoneid=$1 +templateId=$2 +serviceOfferingId=$3 + +for j in `seq 1 100` +do + let add=0 + for i in `seq 1 10` + do + let account=$(($i+$add)) + echo Account Name: , $account + query="GET http://127.0.0.1/client/?command=deployVirtualMachine&zoneId=$1&hypervisor=Simulator&templateId=$2&serviceOfferingId=$3&account=DummyAccount$account&domainid=1 HTTP/1.0\n\n" + echo -e $query | nc -v -q 20 127.0.0.1 8096 + done + let add=add+10 + sleep 60s +done diff --git a/agent-simulator/scripts/guava/__old__/createAdminAccount.sh b/agent-simulator/scripts/guava/__old__/createAdminAccount.sh new file mode 100755 index 00000000000..0f9ac86b138 --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/createAdminAccount.sh @@ -0,0 +1,11 @@ +# +# Copyright (C) 2011 Cloud.com, Inc. All rights reserved. +# + + + +name=$1 + +account_query="GET http://127.0.0.1/client/?command=createAccount&accounttype=1&email=simulator%40simulator.com&username=$name&firstname=first$name&lastname=last$name&password=5f4dcc3b5aa765d61d8327deb882cf99&account=$name&domainid=1 HTTP/1.1\n\n" + +echo -e $account_query | nc -v -q 120 127.0.0.1 8096 diff --git a/agent-simulator/scripts/guava/__old__/createStoragePool.sh b/agent-simulator/scripts/guava/__old__/createStoragePool.sh new file mode 100755 index 00000000000..fde068c51f5 --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/createStoragePool.sh @@ -0,0 +1,7 @@ +# +# Copyright (C) 2011 Cloud.com, Inc. All rights reserved. +# + + +spool_query="GET http://127.0.0.1/client/?command=createStoragePool&zoneId=1&podId=1&clusterid=1&name=SPOOL&url=nfs://10.91.25.6/export/share/1 HTTP/1.0\n\n" +echo -e $spool_query | nc -v -q 60 127.0.0.1 8096 diff --git a/agent-simulator/scripts/guava/__old__/createUserAccount.sh b/agent-simulator/scripts/guava/__old__/createUserAccount.sh new file mode 100755 index 00000000000..ae99d26b74f --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/createUserAccount.sh @@ -0,0 +1,11 @@ +# +# Copyright (C) 2011 Cloud.com, Inc. All rights reserved. +# + + + +name=$1 + +account_query="GET http://127.0.0.1/client/?command=createAccount&accounttype=0&email=simulator%40simulator.com&username=$name&firstname=first$name&lastname=last$name&password=5f4dcc3b5aa765d61d8327deb882cf99&account=$name&domainid=1 HTTP/1.1\n\n" + +echo -e $account_query | nc -v -q 120 127.0.0.1 8096 diff --git a/agent-simulator/scripts/guava/__old__/deleteAccount.sh b/agent-simulator/scripts/guava/__old__/deleteAccount.sh new file mode 100755 index 00000000000..360117168cd --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/deleteAccount.sh @@ -0,0 +1,12 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 + +delete="GET http://127.0.0.1/client/?command=deleteAccount&id=$x HTTP/1.0\n\n" + +echo -e $delete | nc -v -q 60 127.0.0.1 8096 + diff --git a/agent-simulator/scripts/guava/__old__/deletePod.sh b/agent-simulator/scripts/guava/__old__/deletePod.sh new file mode 100755 index 00000000000..3156fd7b912 --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/deletePod.sh @@ -0,0 +1,13 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 + +pod_query="GET http://10.91.30.219:8096/client/?command=deletePod&id=$x HTTP/1.0\n\n" + + +echo -e $pod_query | nc -v -q 20 10.91.30.219 8096 + diff --git a/agent-simulator/scripts/guava/__old__/deleteServiceOffering.sh b/agent-simulator/scripts/guava/__old__/deleteServiceOffering.sh new file mode 100755 index 00000000000..d4b864c6b54 --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/deleteServiceOffering.sh @@ -0,0 +1,12 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 + +delete_so="GET http://10.91.30.219:8096/client/?command=deleteServiceOffering&id=$x HTTP/1.0\n\n" + +echo -e $delete_so | nc -v -q 20 10.91.30.219 8096 + diff --git a/agent-simulator/scripts/guava/__old__/deleteVlan.sh b/agent-simulator/scripts/guava/__old__/deleteVlan.sh new file mode 100755 index 00000000000..70e865c8d6e --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/deleteVlan.sh @@ -0,0 +1,13 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 + +vlan_query="GET http://10.91.30.219:8096/client/?command=deleteVlanIpRange&id=$x HTTP/1.0\n\n" + + +echo -e $vlan_query | nc -v -q 20 10.91.30.219 8096 + diff --git a/agent-simulator/scripts/guava/__old__/deployVirtualMachine.sh b/agent-simulator/scripts/guava/__old__/deployVirtualMachine.sh new file mode 100755 index 00000000000..ddc1f35f4ea --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/deployVirtualMachine.sh @@ -0,0 +1,14 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +zoneid=$1 +templateId=$2 +serviceOfferingId=$3 +networkIds=$4 + +query="GET http://10.91.30.219/client/?command=deployVirtualMachine&zoneId=$1&hypervisor=Simulator&templateId=$2&serviceOfferingId=$3&networkIds=$4&account=admin&domainid=1 HTTP/1.0\n\n" + +echo -e $query | nc -v -q 20 10.91.30.219 8096 diff --git a/agent-simulator/scripts/guava/__old__/destroyVirtualMachine.sh b/agent-simulator/scripts/guava/__old__/destroyVirtualMachine.sh new file mode 100755 index 00000000000..46bffffe6c4 --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/destroyVirtualMachine.sh @@ -0,0 +1,12 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 + +destroy="GET http://10.91.30.219:8096/client/?command=destroyVirtualMachine&id=$x HTTP/1.0\n\n" + +echo -e $destroy | nc -v -q 60 10.91.30.219 8096 + diff --git a/agent-simulator/scripts/guava/__old__/listCapacity.sh b/agent-simulator/scripts/guava/__old__/listCapacity.sh new file mode 100755 index 00000000000..b30da8c0c87 --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/listCapacity.sh @@ -0,0 +1,9 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +query="GET http://10.91.30.219:8096/client/?command=listCapacity&zoneId=$1&podid=$2&response=json HTTP/1.0\n\n" + +echo -e $query | nc -v -q 120 10.91.30.219 8096 diff --git a/agent-simulator/scripts/guava/__old__/listEvents.sh b/agent-simulator/scripts/guava/__old__/listEvents.sh new file mode 100755 index 00000000000..aad3b5f5bbe --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/listEvents.sh @@ -0,0 +1,9 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +test="GET http://10.91.30.219:8096/?command=listEvents HTTP/1.0\n\n" +echo -e $test | nc -v -q 120 10.91.30.219 8096 + diff --git a/agent-simulator/scripts/guava/__old__/listHosts.sh b/agent-simulator/scripts/guava/__old__/listHosts.sh new file mode 100755 index 00000000000..2e29e64fe64 --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/listHosts.sh @@ -0,0 +1,9 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +query="GET http://10.91.30.219:8096/client/?command=listHosts&zoneId=$1&account=admin&domainid=1&page=$2 HTTP/1.0\n\n" + +echo -e $query | nc -v -q 120 10.91.30.219 8096 diff --git a/agent-simulator/scripts/guava/__old__/listRouters.sh b/agent-simulator/scripts/guava/__old__/listRouters.sh new file mode 100755 index 00000000000..f7293fd363e --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/listRouters.sh @@ -0,0 +1,9 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +query="GET http://10.91.30.219:8096/client/?command=listRouters&zoneId=$1&account=admin&domainid=1 HTTP/1.0\n\n" + +echo -e $query | nc -v -q 120 10.91.30.219 8096 diff --git a/agent-simulator/scripts/guava/__old__/listTemplates.sh b/agent-simulator/scripts/guava/__old__/listTemplates.sh new file mode 100755 index 00000000000..1b5c8520e46 --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/listTemplates.sh @@ -0,0 +1,9 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +query="GET http://10.91.30.219:8096/client/?command=listTemplates&templatefilter=featured&zoneid=$1 HTTP/1.0\n\n" + +echo -e $query | nc -v -q 120 10.91.30.219 8096 diff --git a/agent-simulator/scripts/guava/__old__/listVirtualMachine.sh b/agent-simulator/scripts/guava/__old__/listVirtualMachine.sh new file mode 100755 index 00000000000..9559d4754df --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/listVirtualMachine.sh @@ -0,0 +1,9 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +query="GET http://10.91.30.219:8096/client/?command=listVirtualMachines&zoneId=$1&account=admin&domainid=1 HTTP/1.0\n\n" + +echo -e $query | nc -v -q 120 10.91.30.219 8096 diff --git a/agent-simulator/scripts/guava/__old__/load.sh b/agent-simulator/scripts/guava/__old__/load.sh new file mode 100755 index 00000000000..98f54c82697 --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/load.sh @@ -0,0 +1,15 @@ +for x in `seq 3 2082` +do + start_vm="GET http://127.0.0.1:8096/client/?command=startVirtualMachine&id=$x HTTP/1.0\n\n" + echo -e $start_vm | nc -v -q 60 127.0.0.1 8096 +done + +sleep 60s + +for x in `seq 3 1102` +do + stop_vm="GET http://127.0.0.1/client/?command=stopVirtualMachine&id=$x HTTP/1.0\n\n" + echo -e $stop_vm | nc -v -q 60 127.0.0.1 8096 +done + +sleep 60s diff --git a/agent-simulator/scripts/guava/__old__/networkShutDown.sh b/agent-simulator/scripts/guava/__old__/networkShutDown.sh new file mode 100755 index 00000000000..21d434dcc26 --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/networkShutDown.sh @@ -0,0 +1,8 @@ +x=$1 +y=$2 + +for i in `seq $x $y` +do + stop_vm="GET http://127.0.0.1/client/?command=stopVirtualMachine&id=$i HTTP/1.0\n\n" + echo -e $stop_vm | nc -v -q 60 127.0.0.1 8096 +done diff --git a/agent-simulator/scripts/guava/__old__/networkStart.sh b/agent-simulator/scripts/guava/__old__/networkStart.sh new file mode 100755 index 00000000000..cfee671bb0e --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/networkStart.sh @@ -0,0 +1,8 @@ +x=$1 +y=$2 + +for i in `seq $x $y` +do + start_vm="GET http://127.0.0.1:8096/client/?command=startVirtualMachine&id=$i HTTP/1.0\n\n" + echo -e $start_vm | nc -v -q 60 127.0.0.1 8096 +done diff --git a/agent-simulator/scripts/guava/__old__/reconnectStats.sh b/agent-simulator/scripts/guava/__old__/reconnectStats.sh new file mode 100755 index 00000000000..d08ceb97bf2 --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/reconnectStats.sh @@ -0,0 +1,16 @@ +#/bin/bash + + + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +name=$1 +while [ 1 ] +do + mysql -s -r -uroot -Dcloud -h10.1.1.215 -e"select count(id),now(),max(disconnected),mgmt_server_id,status from host group by mgmt_server_id,status;" >> $1 + sleep 5 + echo --------------------------------------------------------------------------------------------------------------------- >> $1 +done diff --git a/agent-simulator/scripts/guava/__old__/setup.sh b/agent-simulator/scripts/guava/__old__/setup.sh new file mode 100755 index 00000000000..274b1009d37 --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/setup.sh @@ -0,0 +1,34 @@ +#!/bin/bash + + + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +#setup for Guava hosts in the simulator + +#1. 1 host per cluster +#2. 100 clusters in a pod + +zone_query="GET http://10.91.30.219/client/?command=createZone&networktype=Advanced&securitygroupenabled=false&name=Go&dns1=4.2.2.2&internaldns1=4.2.2.2&vlan=500-1000&guestcidraddress=10.1.1.0%2F24 HTTP/1.0\n\n" +echo -e $zone_query | nc -v -q 120 10.91.30.219 8096 + +pod_query="GET http://10.91.30.219/client/?command=createPod&zoneId=1&name=Guava&netmask=255.255.0.0&startIp=172.1.2.2&endIp=172.1.255.252&gateway=172.1.2.1 HTTP/1.0\n\n" +echo -e $pod_query | nc -v -q 120 10.91.30.219 8096 + +vlan_query="GET http://10.91.30.219/client/?command=createVlanIpRange&forVirtualNetwork=true&zoneId=1&vlan=untagged&gateway=172.2.1.1&netmask=255.255.0.0&startip=172.2.1.2&endip=172.2.255.254 HTTP/1.0\n\n" +echo -e $vlan_query | nc -v -q 120 10.91.30.219 8096 + +for name in `seq 1 100` +do + cluster_query="GET http://10.91.30.219/client/?command=addCluster&hypervisor=Simulator&clustertype=CloudManaged&zoneId=1&podId=1&clustername=CS$name HTTP/1.0\n\n" + echo -e $cluster_query | nc -v -q 120 10.91.30.219 8096 + + host_query="GET http://10.91.30.219/client/api?_=1302625706202&command=addHost&zoneId=1&podId=1&clusterid=$name&hypervisor=Simulator&clustertype=CloudManaged&hosttags=&username=sim&password=sim&url=http%3A%2F%2Fsim HTTP/1.0\n\n" + echo -e $host_query | nc -v -q 60 10.91.30.219 8096 + + spool_query="GET http://10.91.30.219/client/?command=createStoragePool&zoneId=1&podId=1&clusterid=$name&name=SPOOL$name&url=nfs://172.1.25.$name/export/share/$name HTTP/1.0\n\n" + echo -e $spool_query | nc -v -q 60 10.91.30.219 8096 +done diff --git a/agent-simulator/scripts/guava/__old__/setupDirectPods.sh b/agent-simulator/scripts/guava/__old__/setupDirectPods.sh new file mode 100755 index 00000000000..3834845a2b1 --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/setupDirectPods.sh @@ -0,0 +1,18 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 +y=$2 +name=$3 + +pod_query="GET http://10.91.30.219:8096/client/?command=createPod&zoneId=1&name=SSP$name&cidr=182.$x.$y.0%2F24&startIp=182.$x.$y.2&endIp=182.$x.$y.252&gateway=182.$x.$y.1 +HTTP/1.0\n\n" + +echo -e $pod_query | nc -v -q 20 10.91.30.219 8096 + +#vlan_query="GET http://10.91.30.219/client/?command=createVlanIpRange&vlan=untagged&zoneid=1&podId=$name&forVirtualNetwork=false&gateway=172.$y.$x.1&netmask=255.255.255.0&startip=172.$y.$x.2&endip=172.$y.$x.252 HTTP/1.0\n\n" + +#echo -e $vlan_query | nc -v -q 20 10.91.30.219 8096 diff --git a/agent-simulator/scripts/guava/__old__/setupHosts.sh b/agent-simulator/scripts/guava/__old__/setupHosts.sh new file mode 100755 index 00000000000..d4e5ce1bda7 --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/setupHosts.sh @@ -0,0 +1,10 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +name=$1 + +host_query="GET http://10.91.30.219:8096/client/?command=addHost&zoneId=1&podId=$((name+250))&username=sim&password=sim&clustername=simulator-$name&hosttags=RP$name&url=http%3A%2F%2Fsim HTTP/1.0\n\n" +echo -e $host_query | nc -v -q 60 10.91.30.219 8096 diff --git a/agent-simulator/scripts/guava/__old__/setupPodAndNetwork.sh b/agent-simulator/scripts/guava/__old__/setupPodAndNetwork.sh new file mode 100755 index 00000000000..bf87f5da851 --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/setupPodAndNetwork.sh @@ -0,0 +1,26 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +workers=$1 +x=$2 #CIDR - 16bytes +y=$3 #CIDR - 8 bytes + +for name in `seq 1 $workers` +do + pod_query="GET http://10.91.30.219:8096/client/?command=createPod&zoneId=1&name=RP$name&cidr=182.$x.$y.0%2F24&startIp=182.$x.$y.2&endIp=182.$x.$y.252&gateway=182.$x.$y.1 HTTP/1.0\n\n" + vlan_query="GET http://10.91.30.219:8096/client/?command=createVlanIpRange&vlan=untagged&zoneid=1&podId=$((name+250))&forVirtualNetwork=false&gateway=182.$y.$x.1&netmask=255.255.255.0&startip=182.$y.$x.2&endip=182.$y.$x.252 HTTP/1.0\n\n" + so_query="GET http://10.91.30.219:8096/client/?command=createServiceOffering&name=RP$name&displayText=RP$name&storageType=local&cpuNumber=1&cpuSpeed=1000&memory=512&offerha=false&usevirtualnetwork=false&hosttags=RP$name HTTP/1.0\n\n" + + echo -e $pod_query | nc -v -q 20 10.91.30.219 8096 + echo -e $vlan_query | nc -v -q 20 10.91.30.219 8096 + echo -e $so_query | nc -v -q 20 10.91.30.219 8096 + + let x+=1 + let y+=1 +done + + + diff --git a/agent-simulator/scripts/guava/__old__/setupServiceOffering.sh b/agent-simulator/scripts/guava/__old__/setupServiceOffering.sh new file mode 100755 index 00000000000..12e65e5be43 --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/setupServiceOffering.sh @@ -0,0 +1,11 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 + +so_query="GET http://10.91.30.219:8096/client/?command=createServiceOffering&name=SO$x&displayText=SO$x&storageType=local&cpuNumber=1&cpuSpeed=1000&memory=512&offerha=false&usevirtualnetwork=false&hosttags=SP$x HTTP/1.0\n\n" + +echo -e $so_query | nc -v -q 20 10.91.30.219 8096 diff --git a/agent-simulator/scripts/guava/__old__/setupVlan.sh b/agent-simulator/scripts/guava/__old__/setupVlan.sh new file mode 100755 index 00000000000..ec477439638 --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/setupVlan.sh @@ -0,0 +1,13 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 +y=$2 +name=$3 + +vlan_query="GET http://10.91.30.219/client/?command=createVlanIpRange&vlan=untagged&zoneid=1&podId=$name&forVirtualNetwork=false&gateway=172.$x.$y.1&netmask=255.255.255.0&startip=172.$x.$y.2&endip=172.$x.$y.252 HTTP/1.0\n\n" + +echo -e $vlan_query | nc -v -q 20 10.91.30.219 8096 diff --git a/agent-simulator/scripts/guava/__old__/startRouter.sh b/agent-simulator/scripts/guava/__old__/startRouter.sh new file mode 100755 index 00000000000..f127735bb53 --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/startRouter.sh @@ -0,0 +1,13 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 + +start_router="GET http://10.91.30.219:8096/client/?command=startRouter&id=$x HTTP/1.0\n\n" + + +echo -e $start_router | nc -v -q 60 10.91.30.219 8096 + diff --git a/agent-simulator/scripts/guava/__old__/startVirtualMachine.sh b/agent-simulator/scripts/guava/__old__/startVirtualMachine.sh new file mode 100755 index 00000000000..84fd7c35acb --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/startVirtualMachine.sh @@ -0,0 +1,13 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 + +start_vm="GET http://10.91.30.219:8096/client/?command=startVirtualMachine&id=$x HTTP/1.0\n\n" + + +echo -e $start_vm | nc -v -q 60 10.91.30.219 8096 + diff --git a/agent-simulator/scripts/guava/__old__/stopVirtualMachine.sh b/agent-simulator/scripts/guava/__old__/stopVirtualMachine.sh new file mode 100755 index 00000000000..9884df84586 --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/stopVirtualMachine.sh @@ -0,0 +1,13 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 + +stop_vm="GET http://127.0.0.1/client/?command=stopVirtualMachine&id=$x HTTP/1.0\n\n" + + +echo -e $stop_vm | nc -v -q 60 127.0.0.1 8096 + diff --git a/agent-simulator/scripts/guava/__old__/stress.sh b/agent-simulator/scripts/guava/__old__/stress.sh new file mode 100755 index 00000000000..f88bae6aca3 --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/stress.sh @@ -0,0 +1,39 @@ +zoneid=1 +templateid=3 +account="u" +x=$1 +y=$2 +p=$3 +q=$4 + +for i in `seq 1 3` +do + serviceOfferingId=10 + query="GET http://127.0.0.1/client/?command=deployVirtualMachine&zoneId=$zoneid&hypervisor=Simulator&templateId=$templateid&serviceOfferingId=$serviceOfferingId&account=$account&domainid=1 HTTP/1.0\n\n" + echo -e $query | nc -v -q 20 127.0.0.1 8096 +done + +sleep 15s + +for x in `seq $x $y` +do + destroy="GET http://127.0.0.1:8096/client/?command=destroyVirtualMachine&id=$x HTTP/1.0\n\n" + echo -e $destroy | nc -v -q 60 127.0.0.1 8096 +done + +sleep 240s + +for i in `seq 1 30` +do + serviceOfferingId=9 + query="GET http://127.0.0.1/client/?command=deployVirtualMachine&zoneId=$zoneid&hypervisor=Simulator&templateId=$templateid&serviceOfferingId=$serviceOfferingId&account=$account&domainid=1 HTTP/1.0\n\n" + echo -e $query | nc -v -q 20 127.0.0.1 8096 +done + +sleep 150s + +for x in `seq $p $q` +do + destroy="GET http://127.0.0.1:8096/client/?command=destroyVirtualMachine&id=$x HTTP/1.0\n\n" + echo -e $destroy | nc -v -q 60 127.0.0.1 8096 +done diff --git a/agent-simulator/scripts/guava/__old__/stress2.sh b/agent-simulator/scripts/guava/__old__/stress2.sh new file mode 100755 index 00000000000..ace23a889ff --- /dev/null +++ b/agent-simulator/scripts/guava/__old__/stress2.sh @@ -0,0 +1,120 @@ +#!/bin/bash + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + +############################################################ +# +# Setup Stress. Destroy and Deploy Virtual Machines on +# Guava like environment +# +#Environment +#1. 1 host per cluster +#2. 100 clusters in a pod + +# Create 300 Accounts +# Deploy 300 VMs +# Destroy 300 VMs +# Repeat +############################################################ + + +usage() { + printf "Setup Stress\nUsage: %s: -h management-server -z zoneid [-d delay] [-t templateid] -s service-offering-id [-n number of accounts]\n" $(basename $0) >&2 +} + +create_account() { + seq=$1 + account_query="GET http://$host/client/?command=createAccount&accounttype=0&email=simulator%40simulator.com&username=$account_prefix$seq&firstname=first$seq&lastname=last$seq&password=5f4dcc3b5aa765d61d8327deb882cf99&account=$account_prefix$seq&domainid=1 HTTP/1.1\n\n" + echo -e $account_query | nc -v -q 120 $host 8096 +} + +stress() { + #Deploy 300 VMs in these accounts + for ((i=1;i<=$numberofaccounts;i++)) + do + out=$(./deployVirtualMachine.sh -h $host -z $zoneid -t $template -s $service -a $account_prefix$i) + id=$(echo $out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + echo "deployed vm with id: " $id + VmArray[$i]=$id + done + sleep $delay + + rindex=$(($RANDOM%$numberofaccounts)) + #Stop/Start 300 VMs at random + for ((i=1;i<=$numberofaccounts;i++)) + do + ./stopVirtualMachine.sh -h $host -i ${VmArray:$rindex} + rindex=$(($RANDOM%$numberofaccounts)) + echo "stopped vm with id: " ${VmArray:$rindex} + + ./startVirtualMachine.sh -h $host -i ${VmArray:$rindex} + rindex=$(($RANDOM%$numberofaccounts)) + echo "started vm with id: " ${VmArray:$rindex} + done + sleep $delay +} + +#options +hflag=1 +zflag= +dflag=1 +tflag=1 +sflag= +nflag=1 + + +declare -a VmArray +host="127.0.0.1" #default localhost +zoneid= +delay=300 #default 5 minutes +template=2 #default centos +service= +account_prefix="USER" +numberofaccounts=300 + +while getopts 'h:z:d:t:s:n:' OPTION +do + case $OPTION in + h) hflag=1 + host="$OPTARG" + ;; + z) zflag=1 + zoneid="$OPTARG" + ;; + d) dflag=1 + delay="$OPTARG" + ;; + t) tflag=1 + template="$OPTARG" + ;; + s) sflag=1 + service="$OPTARG" + ;; + n) nflag=1 + numberofaccounts="$OPTARG" + ;; + ?) usage + exit 2 + ;; + esac +done + +if [ $hflag$zflag$dflag$tflag$sflag$nflag != "111111" ] +then + usage + exit 2 +fi + +#Create 300 Accounts +#for ((i=1;i<=$numberofaccounts;i++)) +#do +# create_account $i +#done + +for i in {1..5} +do + #Do the stress test + stress +done diff --git a/agent-simulator/scripts/run.bat b/agent-simulator/scripts/run.bat new file mode 100644 index 00000000000..b28bbc0b824 --- /dev/null +++ b/agent-simulator/scripts/run.bat @@ -0,0 +1,2 @@ +java -cp cloud-utils.jar;agent-simulator.jar;log4j-1.2.15.jar;apache-log4j-extras-1.0.jar;ws-commons-util-1.0.2.jar;xmlrpc-client-3.1.3.jar;cloud-agent.jar;cloud-core.jar;xmlrpc-common-3.1.3.jar;javaee-api-5.0-1.jar;gson-1.3.jar;commons-httpclient-3.1.jar;commons-logging-1.1.1.jar;commons-codec-1.3.jar;commons-collections-3.2.1.jar;commons-pool-1.4.jar;.\;.\conf com.cloud.agent.AgentSimulator %* + diff --git a/agent-simulator/scripts/zucchini/__old__/deletePod.sh b/agent-simulator/scripts/zucchini/__old__/deletePod.sh new file mode 100755 index 00000000000..3fa60735bbc --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/deletePod.sh @@ -0,0 +1,13 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 + +pod_query="GET http://10.91.30.226:8096/client/?command=deletePod&id=$x HTTP/1.0\n\n" + + +echo -e $pod_query | nc -v -q 20 10.91.30.226 8096 + diff --git a/agent-simulator/scripts/zucchini/__old__/deleteServiceOffering.sh b/agent-simulator/scripts/zucchini/__old__/deleteServiceOffering.sh new file mode 100755 index 00000000000..e3a204f44cb --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/deleteServiceOffering.sh @@ -0,0 +1,12 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 + +delete_so="GET http://10.91.30.226:8096/client/?command=deleteServiceOffering&id=$x HTTP/1.0\n\n" + +echo -e $delete_so | nc -v -q 20 10.91.30.226 8096 + diff --git a/agent-simulator/scripts/zucchini/__old__/deleteVlan.sh b/agent-simulator/scripts/zucchini/__old__/deleteVlan.sh new file mode 100755 index 00000000000..5cc3cd2b619 --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/deleteVlan.sh @@ -0,0 +1,13 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 + +vlan_query="GET http://10.91.30.226:8096/client/?command=deleteVlanIpRange&id=$x HTTP/1.0\n\n" + + +echo -e $vlan_query | nc -v -q 20 10.91.30.226 8096 + diff --git a/agent-simulator/scripts/zucchini/__old__/deployBulk-sg.sh b/agent-simulator/scripts/zucchini/__old__/deployBulk-sg.sh new file mode 100755 index 00000000000..73b09d6fbfd --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/deployBulk-sg.sh @@ -0,0 +1,194 @@ +#!/bin/bash + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + +usage() { + printf "Deploy many VMs: %s: -h management-server -n numberofvms [[-b batchsize] [-w wait for success] [-d db-node]]\n" $(basename $0) >&2 + printf "-w option when specifed waits for successful deployment of batchsize (specifed by -b option) number of VMs. default batchsize =100\n" +} + +getSgListRandom() { + num_groups=$((RANDOM%groups_per_vm)) + if [[ $num_groups -eq 0 ]]; then + num_groups=1 #set back to default + fi + + #form sg list string + local sg_list="" + for ((i=0;i<$num_groups;i++)) + do + sgid=$((RANDOM%numberofgroups)) + if [[ $sgid -eq 0 || $sgid -eq 1 ]]; then + sgid=1 #set back to default security group + sg_list=$sgid","$sg_list + continue + fi + + sg_exists="GET http://$host/client/?command=listSecurityGroups&id=$sgid HTTP/1.0\n\n" + sg_out=$(echo -e $sg_exists | nc -v -q 60 $host 8096) + count=$(echo $sg_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + if [[ $count != "1" ]]; then #FAIL: Invalid security group was randomly selected + continue + fi + sg_list=$sgid","$sg_list + done + echo "$sg_list" +} + + +waitDeploy() { + local dbnode=$1 + local batchsize=$2 + while [ 1 ] + do + donecount=$(mysql -uroot -Dcloud -h$dbnode -s -r --skip-column-names -e"select count(*) from async_job where job_cmd like '%DeployVM%' and last_updated is null") + echo "[DEBUG] " $(date) " " $donecount " VMs still deploying" + if [[ $donecount == "0" || $donecount -eq 0 ]] + then + break + fi + sleep $(($donecount*2))s #2 seconds per VM + done +} + +hflag= +nflag=1 +wflag= +bflag= +dflag= +iterator=0 + +declare -a sg_array=('79' '79' '79' '79' '79' '79' '79' '79' '79') +#declare -a sg_array=('72' '73' '74' '75' '76' '77' '78' '79' '80') + +host="127.0.0.1" #defaults to locahost +numberofvms=1040 #defaults +batchsize=100 #default +dbnode= +waitSuccess=false + +while getopts 'h:n:b:d:w' OPTION +do + case $OPTION in + h) hflag=1 + host="$OPTARG" + ;; + n) nflag=1 + numberofvms="$OPTARG" + ;; + w) wflag=1 + waitSuccess=true + ;; + b) bflag=1 + batchsize="$OPTARG" + ;; + d) dflag=1 + dbnode="$OPTARG" + ;; + ?) usage + exit 2 + ;; + esac +done + +if [ $hflag$nflag != "11" ] +then + usage + exit 2 +fi + +if [[ $wflag == "1" && $dflag != "1" ]] +then + echo "please specify dbnode -d option" + usage + exit 2 +fi + + +if [[ $bflag == "1" && $wflag != "1" ]] +then + echo "-w option mandatory when -b is given" + usage + exit 2 +fi + +tag1=$(($numberofvms*5/13)) +tag2=$(($numberofvms*2/13)) +tag3=$(($numberofvms*6/13)) + +tag1_so=9 #defaults from a regular installation +tag2_so=10 +tag3_so=11 +vmcount=0 + +echo -n "Service Offering ID with TAG1 hosttag: " +read tag1_so + +echo -n "Service Offering ID with TAG2 hosttag: " +read tag2_so + +echo -n "Service Offering ID with TAG3 hosttag: " +read tag3_so + +echo "Deploying TAG1 VMs with Service Offering: " $tag1_so +for ((c=1;c<$tag1;c++)) +do + if [[ $vmcount -eq $batchsize && waitSuccess ]] + then + waitDeploy $dbnode $batchsize + vmcount=0 + fi + sglist=${sg_array[$((iterator % 9))]} + iterator=$((iterator+1)) + + job_out=$(./deployVirtualMachine.sh -h $host -z 1 -t 2 -s $tag1_so -u -g $sglist) + job_id=$(echo $job_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + vmid=$(echo $job_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + echo "[DEBUG] $(date) deployed vm: " $vmid " in job: " $job_id + + vmcount=$((vmcount+1)) +done + +sleep 60s + +echo "Deploying TAG2 VMs with Service Offering: " $tag2_so +for ((c=1;c<$tag2;c++)) +do + if [[ $vmcount -eq $batchsize && wflag == "1" ]] + then + waitDeploy $dbnode $batchsize + vmcount=0 + fi + sglist=${sg_array[$((iterator % 9))]} + iterator=$((iterator+1)) + + job_out=$(./deployVirtualMachine.sh -h $host -z 1 -t 2 -s $tag2_so -u -g $sglist) + job_id=$(echo $job_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + vmid=$(echo $job_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + echo "[DEBUG] $(date) deployed vm: " $vmid " in job: " $job_id + + vmcount=$((vmcount+1)) +done + +sleep 60s + +echo "Deploying TAG3 VMs with Service Offering: " $tag3_so +for ((c=1;c<$tag3;c++)) +do + if [[ $vmcount -eq $batchsize && wflag == "1" ]] + then + waitDeploy $dbnode $batchsize + vmcount=0 + fi + sglist=${sg_array[$((iterator % 9))]} + iterator=$((iterator+1)) + + job_out=$(./deployVirtualMachine.sh -h $host -z 1 -t 2 -s $tag3_so -u -g $sglist) + job_id=$(echo $job_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + vmid=$(echo $job_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + echo "[DEBUG] $(date) deployed vm: " $vmid " in job: " $job_id + + vmcount=$((vmcount+1)) +done diff --git a/agent-simulator/scripts/zucchini/__old__/deployBulk.sh b/agent-simulator/scripts/zucchini/__old__/deployBulk.sh new file mode 100755 index 00000000000..076892131d1 --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/deployBulk.sh @@ -0,0 +1,147 @@ +#!/bin/bash + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + +usage() { + printf "Deploy many VMs: %s: -h management-server -n numberofvms [[-b batchsize] [-w wait for success] [-d db-node]]\n" $(basename $0) >&2 +} + +waitDeploy() { + local dbnode=$1 + local batchsize=$2 + while [ 1 ] + do + donecount=$(mysql -uroot -Dcloud -h$dbnode -s -r --skip-column-names -e"select count(*) from async_job where job_cmd like '%DeployVM%' and last_updated is null") + echo "[DEBUG] " $(date) " " $donecount " VMs still deploying" + if [[ $donecount == "0" || $donecount -eq 0 ]] + then + break + fi + sleep $(($donecount*2))s #2 seconds per VM + done +} + +hflag= +nflag=1 +wflag= +bflag= +dflag= +iterator=0 + +host="127.0.0.1" #defaults to locahost +numberofvms=1040 #defaults +numberofgroups= +groups_per_vm=1 #default one group per vm +batchsize=100 +waitSuccess=false + +while getopts 'h:n:b:d:w' OPTION +do + case $OPTION in + h) hflag=1 + host="$OPTARG" + ;; + n) nflag=1 + numberofvms="$OPTARG" + ;; + w) wflag=1 + waitSuccess=true + ;; + b) bflag=1 + batchsize="$OPTARG" + ;; + d) dflag=1 + dbnode="$OPTARG" + ;; + ?) usage + exit 2 + ;; + esac +done + +if [ $hflag$nflag != "11" ] +then + usage + exit 2 +fi + +if [[ $wflag == "1" && $dflag != "1" ]] +then + echo "please specify dbnode -d option" + usage + exit 2 +fi + + +if [[ $bflag == "1" && $wflag != "1" ]] +then + echo "-w option mandatory when -b is given" + usage + exit 2 +fi + +tag1=$(($numberofvms*5/13)) +tag2=$(($numberofvms*2/13)) +tag3=$(($numberofvms*6/13)) + +tag1_so=9 #defaults from a regular installation +tag2_so=10 +tag3_so=11 +vmcount=0 + +echo -n "Service Offering ID with TAG1 hosttag: " +read tag1_so + +echo -n "Service Offering ID with TAG2 hosttag: " +read tag2_so + +echo -n "Service Offering ID with TAG3 hosttag: " +read tag3_so + +echo "Deploying TAG1 VMs with Service Offering: " $tag1_so +for ((c=1;c<$tag1;c++)) +do + if [[ $vmcount -eq $batchsize && waitSuccess ]] + then + waitDeploy $dbnode $batchsize + vmcount=0 + fi + job_out=$(./deployVirtualMachine.sh -h $host -z 1 -t 2 -s $tag1_so -u) + job_id=$(echo $job_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + vmid=$(echo $job_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + echo "[DEBUG] $(date) deployed vm: " $vmid " in job: " $job_id + vmcount=$((vmcount+1)) +done + +echo "Deploying TAG2 VMs with Service Offering: " $tag2_so +for ((c=1;c<$tag2;c++)) +do + if [[ $vmcount -eq $batchsize && waitSuccess ]] + then + waitDeploy $dbnode $batchsize + vmcount=0 + fi + job_out=$(./deployVirtualMachine.sh -h $host -z 1 -t 2 -s $tag2_so -u) + job_id=$(echo $job_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + vmid=$(echo $job_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + echo "[DEBUG] $(date) deployed vm: " $vmid " in job: " $job_id + vmcount=$((vmcount+1)) +done + + +echo "Deploying TAG3 VMs with Service Offering: " $tag3_so +for ((c=1;c<$tag3;c++)) +do + if [[ $vmcount -eq $batchsize && waitSuccess ]] + then + waitDeploy $dbnode $batchsize + vmcount=0 + fi + job_out=$(./deployVirtualMachine.sh -h $host -z 1 -t 2 -s $tag3_so -u) + job_id=$(echo $job_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + vmid=$(echo $job_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + echo "[DEBUG] $(date) deployed vm: " $vmid " in job: " $job_id + vmcount=$((vmcount+1)) +done diff --git a/agent-simulator/scripts/zucchini/__old__/deployVirtualMachine.sh b/agent-simulator/scripts/zucchini/__old__/deployVirtualMachine.sh new file mode 100755 index 00000000000..4c9200cc4e3 --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/deployVirtualMachine.sh @@ -0,0 +1,13 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +zoneid=$1 +templateId=$2 +serviceOfferingId=$3 + +query="GET http://10.91.30.226:8096/client/?command=deployVirtualMachine&zoneId=$1&templateId=$2&serviceOfferingId=$3&account=admin&domainid=1 HTTP/1.0\n\n" + +echo -e $query | nc -v -q 20 10.91.30.226 8096 diff --git a/agent-simulator/scripts/zucchini/__old__/destroySystemVm.sh b/agent-simulator/scripts/zucchini/__old__/destroySystemVm.sh new file mode 100755 index 00000000000..3a164eca85d --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/destroySystemVm.sh @@ -0,0 +1,40 @@ +#!/bin/bash + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + +usage() { + printf "Destroy System Virtual Machine\nUsage: %s: -h management-server-ip -i vmid\n" $(basename $0) >&2 +} + + +hflag= +iflag= + +vmid= +host="127.0.0.1" #defaults to localhost + +while getopts 'h:i:' OPTION +do + case $OPTION in + h) hflag=1 + host="$OPTARG" + ;; + i) iflag=1 + vmid="$OPTARG" + ;; + ?) usage + exit 2 + ;; + esac +done + +if [[ $iflag != "1" ]] +then + usage + exit 2 +fi + +destroy="GET http://$host:8096/client/?command=destroySystemVm&id=$vmid HTTP/1.0\n\n" +echo -e $destroy | nc -v -w 60 $host 8096 + diff --git a/agent-simulator/scripts/zucchini/__old__/destroyVirtualMachine.sh b/agent-simulator/scripts/zucchini/__old__/destroyVirtualMachine.sh new file mode 100755 index 00000000000..a0abf6911a1 --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/destroyVirtualMachine.sh @@ -0,0 +1,12 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 + +destroy="GET http://10.91.30.226:8096/client/?command=destroyVirtualMachine&id=$x HTTP/1.0\n\n" + +echo -e $destroy | nc -v -q 60 10.91.30.226 8096 + diff --git a/agent-simulator/scripts/zucchini/__old__/listCapacity.sh b/agent-simulator/scripts/zucchini/__old__/listCapacity.sh new file mode 100755 index 00000000000..c6cf457f9a4 --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/listCapacity.sh @@ -0,0 +1,9 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +query="GET http://10.91.30.226:8096/client/?command=listCapacity&zoneId=$1&podid=$2&response=json HTTP/1.0\n\n" + +echo -e $query | nc -v -q 120 10.91.30.226 8096 diff --git a/agent-simulator/scripts/zucchini/__old__/listEvents.sh b/agent-simulator/scripts/zucchini/__old__/listEvents.sh new file mode 100755 index 00000000000..2e8b837d33d --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/listEvents.sh @@ -0,0 +1,9 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +test="GET http://10.91.30.226:8096/?command=listEvents&page=1 HTTP/1.0\n\n" +echo -e $test | nc -v -q 120 10.91.30.226 8096 + diff --git a/agent-simulator/scripts/zucchini/__old__/listHosts.sh b/agent-simulator/scripts/zucchini/__old__/listHosts.sh new file mode 100755 index 00000000000..3d92be0cdbe --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/listHosts.sh @@ -0,0 +1,9 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +query="GET http://10.91.30.226:8096/client/?command=listHosts&zoneId=$1&account=admin&domainid=1&page=$2 HTTP/1.0\n\n" + +echo -e $query | nc -v -q 120 10.91.30.226 8096 diff --git a/agent-simulator/scripts/zucchini/__old__/listRouters.sh b/agent-simulator/scripts/zucchini/__old__/listRouters.sh new file mode 100755 index 00000000000..c7cea4c9f21 --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/listRouters.sh @@ -0,0 +1,9 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +query="GET http://10.91.30.226:8096/client/?command=listRouters&zoneId=$1&account=admin&domainid=1 HTTP/1.0\n\n" + +echo -e $query | nc -v -q 120 10.91.30.226 8096 diff --git a/agent-simulator/scripts/zucchini/__old__/listTemplates.sh b/agent-simulator/scripts/zucchini/__old__/listTemplates.sh new file mode 100755 index 00000000000..ec7a17cf6f1 --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/listTemplates.sh @@ -0,0 +1,9 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +query="GET http://10.91.30.212:8096/client/?command=listTemplates&templatefilter=featured&zoneid=$1 HTTP/1.0\n\n" + +echo -e $query | nc -v -w 120 10.91.30.212 8096 diff --git a/agent-simulator/scripts/zucchini/__old__/listVirtualMachine.sh b/agent-simulator/scripts/zucchini/__old__/listVirtualMachine.sh new file mode 100755 index 00000000000..6d9e30f6f49 --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/listVirtualMachine.sh @@ -0,0 +1,9 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +query="GET http://10.91.30.226:8096/client/?command=listVirtualMachines&zoneId=$1&account=admin&domainid=1 HTTP/1.0\n\n" + +echo -e $query | nc -v -q 120 10.91.30.226 8096 diff --git a/agent-simulator/scripts/zucchini/__old__/monitor.sh b/agent-simulator/scripts/zucchini/__old__/monitor.sh new file mode 100755 index 00000000000..140a20348b9 --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/monitor.sh @@ -0,0 +1,21 @@ +#!/bin/bash +host=$1 + +while [ 1 ] +do + echo ==== $(date) ==== +# mysql -uroot -Dcloud -h$host -e"select count(*), status, mgmt_server_id from host group by status, mgmt_server_id;" + mysql -uroot -Dcloud -h$host -e"select count(*), state, type from vm_instance group by state, type;" + mysql -uroot -Dcloud -h$host -e"select avg(timestampdiff(second,created,last_updated)),count(id),job_cmd,job_status,job_result_code from async_job where last_updated is not null group by job_cmd,job_status,job_result_code;" + mysql -uroot -Dcloud -h$host -e "select count(*) as locks from op_lock;" + echo === last 5 successful DeployVM === + mysql -uroot -Dcloud -h$host -e"select created,last_updated,id, timestampdiff(second,created,last_updated) from async_job where job_cmd like '%DeployVM%' and job_result_code=0 and last_updated is not null order by id desc limit 5;" + echo === nwgroup status === + mysql -uroot -Dcloud -h$host -e"select step, count(*) from op_nwgrp_work group by step;" + mysql -uroot -Dcloud -h$host -e"select avg(timestampdiff(second,created,taken)), count(id),mgmt_server_id from op_nwgrp_work where step='Done' and taken is not null and created < taken group by mgmt_server_id;" + mysql -uroot -Dcloud -h$host -e"select id,mgmt_server_id,instance_id,created,taken,timestampdiff(second,created,taken) from op_nwgrp_work where taken is not null and created!=taken order by id desc limit 5;" + echo + echo + echo + sleep 30s +done diff --git a/agent-simulator/scripts/zucchini/__old__/newsetup.sh b/agent-simulator/scripts/zucchini/__old__/newsetup.sh new file mode 100755 index 00000000000..67029fdf1f5 --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/newsetup.sh @@ -0,0 +1,224 @@ +#!/bin/bash + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + +############################################################ +# +# zucchini uses local storage, before setting up make sure +# * xen.public.network.device is set +# * use.local.storage and systemvm.use.local.storage are true +# * optionally turn off stats collectors +# * expunge.delay and expunge.interval are 60s +# * ping.interval is around 3m +# * turn off dns updates to entire zone, network.dns.basiczone.update=pod +# * capacity.skipcounting.hours=0 +# * direct.agent.load.size=1000 + +# +# This script will only setup an approximate number of hosts. To achieve the ratio +# of 5:2:6 hosts the total number of hosts is brought close to a number divisible +# by 13. So if 4000 hosts are added, you might see only 3900 come up +# +# 10 hosts per pod @ 1 host per cluster in a single zone +# +# Each pod has a /25, so 128 addresses. I think we reserved 5 IP addresses for system VMs in each pod. +# Then we had something like 60 addresses for hosts and 60 addresses for VMs. + +#Environment +#1. Approximately 10 hosts per pod. +#2. Only 3 host tags. +#3. With in each pod, the host tags are the same. Homogenous Pods +#4. The ratio of hosts for the three tags should be 5/2/6 +#5. In simulator.properties, workers=1 +############################################################ + +usage() { + printf "Setup Zucchini Like Environment\nUsage: %s: -h management-server -z zoneid [-d delay] -n numberofhosts\n" $(basename $0) >&2 +} + +a=1 #CIDR - 16bytes +b=2 #CIDR - 8 bytes + +#options +hflag=1 +zflag= +dflag=1 +nflag=1 + +host="127.0.0.1" #default localhost +zoneid= +delay=300 #default 5 minutes +numberofhosts=1300 #default 1300 hosts +tag1="TAG1" +tag2="TAG2" +tag3="TAG3" + +while getopts 'h:z:d:n:' OPTION +do + case $OPTION in + h) hflag=1 + host="$OPTARG" + ;; + z) zflag=1 + zoneid="$OPTARG" + ;; + d) dflag=1 + delay="$OPTARG" + ;; + n) nflag=1 + numberofhosts="$OPTARG" + ;; + ?) usage + exit 2 + ;; + esac +done + +if [ $zflag$nflag != "11" ] +then + usage + exit 2 +fi + +numberofpods=$(($numberofhosts/10)) #10 hosts per pod +tag_one_range=$(($numberofpods*5/13)) +tag_two_range=$(($numberofpods*2/13)) +tag_three_range=$(($numberofpods-$tag_one_range-$tag_two_range)) + +clusters_per_pod=10 #each cluster has one host +hosts_per_pod=10 + + +declare -a pod_array +declare -a cluster_array + +echo "Split Ratio :: " $tag_one_range":"$tag_two_range":"$tag_three_range + +#create the zone +zone_query="GET http://$host/client/?command=createZone&networktype=Basic&securitygroupenabled=false&name=Zucchini&dns1=4.2.2.2&internaldns1=4.2.2.2 HTTP/1.0\n\n" +echo -e $zone_query | nc -v -w $delay $host 8096 + +#Add Secondary Storage +sstor_query="GET http://$host/client/?command=addSecondaryStorage&zoneid=$zoneid&url=nfs://172.16.15.32/export/share/secondary HTTP/1.0\n\n" +echo -e $sstor_query | nc -v -w $delay $host 8096 + +let x=a +let y=b + +echo "[DEBUG] $(date) Starting Creation of $numberofpods Pods" +for ((name=1;name<=$numberofpods;name++)) +do + echo "[DEBUG] $(date) Creating pod[POD$name]" + pod_query="GET http://$host/client/?command=createPod&zoneId=$zoneid&name=POD$name&netmask=255.255.255.128&startIp=172.$x.$y.130&endIp=172.$x.$y.189&gateway=172.$x.$y.129 HTTP/1.0\n\n" + pod_out=$(echo -e $pod_query | nc -v -w $delay $host 8096) + pod_id=$(echo $pod_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + if ! [[ "$pod_id" =~ ^[0-9]+$ ]] ; then + exec >&2; echo "[ERROR] $(date) pod [POD$name] creation failed"; continue + fi + echo "[DEBUG] $(date) Created pod["$pod_id":POD"$name"]" + pod_array[$name]=$pod_id + + echo "[DEBUG] $(date) Creating vlan for pod[POD$name]" + vlan_query="GET http://$host/client/?command=createVlanIpRange&vlan=untagged&zoneid=$zoneid&podId=$pod_id&forVirtualNetwork=false&gateway=172.$x.$y.129&netmask=255.255.255.128&startip=172.$x.$y.190&endip=172.$x.$y.249 HTTP/1.0\n\n" + vlan_out=$(echo -e $vlan_query | nc -v -w $delay $host 8096) + vlan_id=$(echo $vlan_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + if ! [[ "$vlan_id" =~ ^[0-9]+$ ]] ; then + let y+=1 + if [ "$y" -eq 256 ] + then + let x+=1 + y=1 + fi + exec >&2; echo "[ERROR] $(date) vlan creation for pod[POD$name] failed"; continue + fi + echo "[DEBUG] $(date) Created vlan for pod[POD$name]" + + #add clusters + echo "[DEBUG] $(date) Starting Creation of $clusters_per_pod clusters for pod[POD$name]" + for ((cluster=1;cluster<=$clusters_per_pod;cluster++)) + do + echo "[DEBUG] $(date) Creating cluster[POD$name-CLUSTER$cluster] for pod[POD$name]" + cluster_query="GET http://$host/client/?command=addCluster&hypervisor=Simulator&clustertype=CloudManaged&zoneId=$zoneid&podId=$pod_id&clustername=POD$name-CLUSTER$cluster HTTP/1.0\n\n" + cluster_out=$(echo -e $cluster_query | nc -v -w $delay $host 8096) + cluster_id=$(echo $cluster_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + if ! [[ "$cluster_id" =~ ^[0-9]+$ ]] ; then + exec >&2; echo "[ERROR] $(date) cluster[POD$name-CLUSTER$cluster] creation for pod[POD$name] failed"; continue + fi + echo "[DEBUG] $(date) Created cluster["$cluster_id":POD"$name"-CLUSTER"$cluster"]" + cluster_array[$(($name*$clusters_per_pod + $cluster))]=$cluster_id + done + echo "[DEBUG] $(date) Finished Creating clusters for pod[POD$name]" + let y+=1 + if [ "$y" -eq 256 ] + then + let x+=1 + y=1 + fi +done +echo "[DEBUG] $(date) Finished Creating $numberofpods Pods" + +#echo "DEBUG:Pods and Clusters" +#echo "PODS:("${#pod_array[@]}")" ${pod_array[@]} +#echo "CLUSTERS:("${#cluster_array[@]}")" ${cluster_array[@]} +echo +echo + +#Add hosts +#TAG1 +for ((i=1;i<=$tag_one_range;i++)) +do + podid=${pod_array[$i]} + for ((j=1;j<=$hosts_per_pod;j++)) + do + clusterid=${cluster_array[$(($i*$clusters_per_pod + $j))]} + host_query="GET http://$host/client/?command=addHost&zoneId=$zoneid&podId=$podid&username=sim&password=sim&clusterid=$clusterid&url=http%3A%2F%2Fsim&hypervisor=Simulator&clustertype=CloudManaged&hosttags=$tag1 HTTP/1.0\n\n" + host_out=$(echo -e $host_query | nc -v -w $delay $host 8096) + host_id=$(echo $host_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + if ! [[ "$host_id" =~ ^[0-9]+$ ]] ; then + exec >&2; echo "[ERROR] $(date) host addition failed in [pod:$podid,cluster:$clusterid]"; continue + fi + host_name=$(echo $host_out | sed 's/\(.*\)\(SimulatedAgent.[-0-9a-zA-Z]*\)\(.*\)/\2/g') + echo "[DEBUG] $date added host [$host_id:$host_name] to [pod:$podid,cluster:$clusterid] for TAG1" + done +done + +#TAG2 +for ((i=$(($tag_one_range + 1));i<=$(($tag_one_range + $tag_two_range));i++)) +do + podid=${pod_array[$i]} + for ((j=1;j<=$hosts_per_pod;j++)) + do + clusterid=${cluster_array[$(($i*$clusters_per_pod + $j))]} + host_query="GET http://$host/client/?command=addHost&zoneId=$zoneid&podId=$podid&username=sim&password=sim&clusterid=$clusterid&url=http%3A%2F%2Fsim&hypervisor=Simulator&clustertype=CloudManaged&hosttags=$tag2 HTTP/1.0\n\n" + host_out=$(echo -e $host_query | nc -v -w $delay $host 8096) + host_id=$(echo $host_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + if ! [[ "$host_id" =~ ^[0-9]+$ ]] ; then + exec >&2; echo "[ERROR] $(date) host addition failed in [pod:$podid,cluster:$clusterid]"; continue + fi + host_name=$(echo $host_out | sed 's/\(.*\)\(SimulatedAgent.[-0-9a-zA-Z]*\)\(.*\)/\2/g') + echo "[DEBUG] $date added host [$host_id:$host_name] to [pod:$podid,cluster:$clusterid] for TAG2" + done +done + +#TAG3 +for ((i=$(($tag_two_range + $tag_one_range + 1));i<=$(($tag_three_range + $tag_two_range + $tag_one_range));i++)) +do + podid=${pod_array[$i]} + for ((j=1;j<=$hosts_per_pod;j++)) + do + clusterid=${cluster_array[$(($i*$clusters_per_pod + $j))]} + host_query="GET http://$host/client/?command=addHost&zoneId=$zoneid&podId=$podid&username=sim&password=sim&clusterid=$clusterid&url=http%3A%2F%2Fsim&hypervisor=Simulator&clustertype=CloudManaged&hosttags=$tag3 HTTP/1.0\n\n" + host_out=$(echo -e $host_query | nc -v -w $delay $host 8096) + host_id=$(echo $host_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + if ! [[ "$host_id" =~ ^[0-9]+$ ]] ; then + exec >&2; echo "[ERROR] $(date) host addition failed in [pod:$podid,cluster:$clusterid]"; continue + fi + host_name=$(echo $host_out | sed 's/\(.*\)\(SimulatedAgent.[-0-9a-zA-Z]*\)\(.*\)/\2/g') + echo "[DEBUG] $date added host [$host_id:$host_name] to [pod:$podid,cluster:$clusterid] for TAG3" + done +done + +echo "Setup complete" +exit 0 diff --git a/agent-simulator/scripts/zucchini/__old__/reconnectStats.sh b/agent-simulator/scripts/zucchini/__old__/reconnectStats.sh new file mode 100755 index 00000000000..d08ceb97bf2 --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/reconnectStats.sh @@ -0,0 +1,16 @@ +#/bin/bash + + + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +name=$1 +while [ 1 ] +do + mysql -s -r -uroot -Dcloud -h10.1.1.215 -e"select count(id),now(),max(disconnected),mgmt_server_id,status from host group by mgmt_server_id,status;" >> $1 + sleep 5 + echo --------------------------------------------------------------------------------------------------------------------- >> $1 +done diff --git a/agent-simulator/scripts/zucchini/__old__/setup.sh b/agent-simulator/scripts/zucchini/__old__/setup.sh new file mode 100755 index 00000000000..5100c6f7974 --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/setup.sh @@ -0,0 +1,81 @@ +#!/bin/bash + + + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +#setup for zucchini hosts in the simulator + +#1. Approximately 10 hosts per pod. +#2. Only 3 host tags. +#3. With in each pod, the host tags are the same. +#4. The ratio of hosts for the three tags should be 5/2/6 + +a=$1 #CIDR - 16bytes +b=$2 #CIDR - 8 bytes + +zone_query="GET http://10.91.30.219/client/?command=createZone&name=Zucchini&dns1=4.2.2.2&internaldns1=4.2.2.2&vlan=10-4000&guestcidraddress=10.1.1.0%2F24 HTTP/1.0\n\n" +echo -e $zone_query | nc -v -q 120 10.91.30.219 8096 + +# Pod Ratio: 38:15:47 @ 10 hosts per pod +let x=a +let y=b +for name in `seq 1 152` +do + pod_query="GET http://10.91.30.219:8096/client/?command=createPod&zoneId=1&name=POD$name&cidr=172.$x.$y.0%2F24&startIp=172.$x.$y.2&endIp=172.$x.$y.252&gateway=172.$x.$y.1 HTTP/1.0\n\n" + vlan_query="GET http://10.91.30.219:8096/client/?command=createVlanIpRange&vlan=untagged&zoneid=1&podId=$name&forVirtualNetwork=false&gateway=172.$y.$x.1&netmask=255.255.255.0&startip=172.$y.$x.2&endip=172.$y.$x.252 HTTP/1.0\n\n" + echo -e $pod_query | nc -v -q 20 10.91.30.219 8096 + echo -e $vlan_query | nc -v -q 20 10.91.30.219 8096 + + for cluster in `seq 1 10` + do + host_query="GET http://10.91.30.219:8096/client/?command=addHost&zoneId=1&podId=$name&username=sim&password=sim&clustername=simulator-POD$name-CLUSTER$cluster&hosttags=TAG1&url=http%3A%2F%2Fsim HTTP/1.0\n\n" + echo -e $host_query | nc -v -q 6000 10.91.30.219 8096 + done + + let x+=1 + let y+=1 +done + +#reset for tag2 +let x=a +let y=b +for name in `seq 153 212` +do + pod_query="GET http://10.91.30.219:8096/client/?command=createPod&zoneId=1&name=POD$name&cidr=182.$x.$y.0%2F24&startIp=182.$x.$y.2&endIp=182.$x.$y.252&gateway=182.$x.$y.1 HTTP/1.0\n\n" + vlan_query="GET http://10.91.30.219:8096/client/?command=createVlanIpRange&vlan=untagged&zoneid=1&podId=$name&forVirtualNetwork=false&gateway=182.$y.$x.1&netmask=255.255.255.0&startip=182.$y.$x.2&endip=182.$y.$x.252 HTTP/1.0\n\n" + echo -e $pod_query | nc -v -q 20 10.91.30.219 8096 + echo -e $vlan_query | nc -v -q 20 10.91.30.219 8096 + + for cluster in `seq 1 10` + do + host_query="GET http://10.91.30.219:8096/client/?command=addHost&zoneId=1&podId=$name&username=sim&password=sim&clustername=simulator-POD$name-CLUSTER$cluster&hosttags=TAG2&url=http%3A%2F%2Fsim HTTP/1.0\n\n" + echo -e $host_query | nc -v -q 6000 10.91.30.219 8096 + done + + let x+=1 + let y+=1 +done + +#reset for TAG3 +let x=a +let y=b +for name in `seq 213 400` +do + pod_query="GET http://10.91.30.219:8096/client/?command=createPod&zoneId=1&name=POD$name&cidr=192.$x.$y.0%2F24&startIp=192.$x.$y.2&endIp=192.$x.$y.252&gateway=192.$x.$y.1 HTTP/1.0\n\n" + vlan_query="GET http://10.91.30.219:8096/client/?command=createVlanIpRange&vlan=untagged&zoneid=1&podId=$name&forVirtualNetwork=false&gateway=192.$y.$x.1&netmask=255.255.255.0&startip=192.$y.$x.2&endip=192.$y.$x.252 HTTP/1.0\n\n" + echo -e $pod_query | nc -v -q 20 10.91.30.219 8096 + echo -e $vlan_query | nc -v -q 20 10.91.30.219 8096 + + for cluster in `seq 1 10` + do + host_query="GET http://10.91.30.219:8096/client/?command=addHost&zoneId=1&podId=$name&username=sim&password=sim&clustername=simulator-POD$name-CLUSTER$cluster&hosttags=TAG3&url=http%3A%2F%2Fsim HTTP/1.0\n\n" + echo -e $host_query | nc -v -q 6000 10.91.30.219 8096 + done + + let x+=1 + let y+=1 +done diff --git a/agent-simulator/scripts/zucchini/__old__/setupDirectPods.sh b/agent-simulator/scripts/zucchini/__old__/setupDirectPods.sh new file mode 100755 index 00000000000..5d1d28c236d --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/setupDirectPods.sh @@ -0,0 +1,18 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 +y=$2 +name=$3 + +pod_query="GET http://10.91.30.212:8096/client/?command=createPod&zoneId=1&name=SSP$name&cidr=182.$x.$y.0%2F24&startIp=182.$x.$y.2&endIp=182.$x.$y.252&gateway=182.$x.$y.1 +HTTP/1.0\n\n" + +echo -e $pod_query | nc -v -w 20 10.91.30.212 8096 + +#vlan_query="GET http://10.91.30.212/client/?command=createVlanIpRange&vlan=untagged&zoneid=1&podId=$name&forVirtualNetwork=false&gateway=172.$y.$x.1&netmask=255.255.255.0&startip=172.$y.$x.2&endip=172.$y.$x.252 HTTP/1.0\n\n" + +#echo -e $vlan_query | nc -v -w 20 10.91.30.212 8096 diff --git a/agent-simulator/scripts/zucchini/__old__/setupHosts.sh b/agent-simulator/scripts/zucchini/__old__/setupHosts.sh new file mode 100755 index 00000000000..6cef7d5b83f --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/setupHosts.sh @@ -0,0 +1,10 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +name=$1 + +host_query="GET http://10.91.30.226:8096/client/?command=addHost&zoneId=1&podId=$((name+250))&username=sim&password=sim&clustername=simulator-$name&hosttags=RP$name&url=http%3A%2F%2Fsim HTTP/1.0\n\n" +echo -e $host_query | nc -v -q 60 10.91.30.226 8096 diff --git a/agent-simulator/scripts/zucchini/__old__/setupPodAndNetwork.sh b/agent-simulator/scripts/zucchini/__old__/setupPodAndNetwork.sh new file mode 100755 index 00000000000..4ab4a577963 --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/setupPodAndNetwork.sh @@ -0,0 +1,26 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +workers=$1 +x=$2 #CIDR - 16bytes +y=$3 #CIDR - 8 bytes + +for name in `seq 1 $workers` +do + pod_query="GET http://10.91.30.226:8096/client/?command=createPod&zoneId=1&name=RP$name&cidr=182.$x.$y.0%2F24&startIp=182.$x.$y.2&endIp=182.$x.$y.252&gateway=182.$x.$y.1 HTTP/1.0\n\n" + vlan_query="GET http://10.91.30.226:8096/client/?command=createVlanIpRange&vlan=untagged&zoneid=1&podId=$((name+250))&forVirtualNetwork=false&gateway=182.$y.$x.1&netmask=255.255.255.0&startip=182.$y.$x.2&endip=182.$y.$x.252 HTTP/1.0\n\n" + so_query="GET http://10.91.30.226:8096/client/?command=createServiceOffering&name=RP$name&displayText=RP$name&storageType=local&cpuNumber=1&cpuSpeed=1000&memory=512&offerha=false&usevirtualnetwork=false&hosttags=RP$name HTTP/1.0\n\n" + + echo -e $pod_query | nc -v -q 20 10.91.30.226 8096 + echo -e $vlan_query | nc -v -q 20 10.91.30.226 8096 + echo -e $so_query | nc -v -q 20 10.91.30.226 8096 + + let x+=1 + let y+=1 +done + + + diff --git a/agent-simulator/scripts/zucchini/__old__/setupServiceOffering.sh b/agent-simulator/scripts/zucchini/__old__/setupServiceOffering.sh new file mode 100755 index 00000000000..7e995144335 --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/setupServiceOffering.sh @@ -0,0 +1,11 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 + +so_query="GET http://10.91.30.226:8096/client/?command=createServiceOffering&name=SO$x&displayText=SO$x&storageType=local&cpuNumber=1&cpuSpeed=1000&memory=512&offerha=false&usevirtualnetwork=false&hosttags=SP$x HTTP/1.0\n\n" + +echo -e $so_query | nc -v -q 20 10.91.30.226 8096 diff --git a/agent-simulator/scripts/zucchini/__old__/setupVlan.sh b/agent-simulator/scripts/zucchini/__old__/setupVlan.sh new file mode 100755 index 00000000000..cd5903bfed3 --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/setupVlan.sh @@ -0,0 +1,13 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 +y=$2 +name=$3 + +vlan_query="GET http://10.91.30.212/client/?command=createVlanIpRange&vlan=untagged&zoneid=1&podId=$name&forVirtualNetwork=false&gateway=172.$x.$y.1&netmask=255.255.255.0&startip=172.$x.$y.2&endip=172.$x.$y.252 HTTP/1.0\n\n" + +echo -e $vlan_query | nc -v -w 20 10.91.30.212 8096 diff --git a/agent-simulator/scripts/zucchini/__old__/setup_sg.sh b/agent-simulator/scripts/zucchini/__old__/setup_sg.sh new file mode 100755 index 00000000000..a4d8563bb92 --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/setup_sg.sh @@ -0,0 +1,248 @@ +#!/bin/bash + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + +############################################################ +# +# zucchini uses local storage, before setting up make sure +# * xen.public.network.device is set +# * use.local.storage and systemvm.use.local.storage are true +# * optionally turn off stats collectors +# * expunge.delay and expunge.interval are 60s +# * ping.interval is around 3m +# * turn off dns updates to entire zone, network.dns.basiczone.update=pod +# * capacity.skipcounting.hours=0 +# * direct.agent.load.size=1000 +# * security groups are enabled + +# +# This script will only setup an approximate number of hosts. To achieve the ratio +# of 5:2:6 hosts the total number of hosts is brought close to a number divisible +# by 13. So if 4000 hosts are added, you might see only 3900 come up +# +# 10 hosts per pod @ 1 host per cluster in a single zone +# +# Each pod has a /25, so 128 addresses. I think we reserved 5 IP addresses for system VMs in each pod. +# Then we had something like 60 addresses for hosts and 60 addresses for VMs. + +#Environment +#1. Approximately 10 hosts per pod. +#2. Only 3 host tags. +#3. With in each pod, the host tags are the same. Homogenous Pods +#4. The ratio of hosts for the three tags should be 5/2/6 +#5. In simulator.properties, workers=1 +############################################################ + +usage() { + printf "Setup Zucchini Like Environment\nUsage: %s: -h management-server -z zoneid [-d delay] -n numberofhosts [-g numberof security groups]\n" $(basename $0) >&2 +} + +a=1 #CIDR - 16bytes +b=2 #CIDR - 8 bytes + +#options +hflag=1 +zflag= +dflag=1 +nflag=1 +gflag=1 + +host="127.0.0.1" #default localhost +zoneid= +delay=300 #default 5 minutes +numberofhosts=1300 #default 1300 hosts +numberofgroups=130 #default 130 groups +tag1="TAG1" +tag2="TAG2" +tag3="TAG3" + +while getopts 'h:z:d:n:g:' OPTION +do + case $OPTION in + h) hflag=1 + host="$OPTARG" + ;; + z) zflag=1 + zoneid="$OPTARG" + ;; + d) dflag=1 + delay="$OPTARG" + ;; + n) nflag=1 + numberofhosts="$OPTARG" + ;; + g) gflag=1 + numberofgroups="$OPTARG" + ;; + ?) usage + exit 2 + ;; + esac +done + +if [ $zflag$nflag != "11" ] +then + usage + exit 2 +fi + +numberofpods=$(($numberofhosts/10)) #10 hosts per pod +tag_one_range=$(($numberofpods*5/13)) +tag_two_range=$(($numberofpods*2/13)) +tag_three_range=$(($numberofpods-$tag_one_range-$tag_two_range)) + +clusters_per_pod=10 #each cluster has one host +hosts_per_pod=10 + + +declare -a pod_array +declare -a cluster_array + +echo "Split Ratio :: " $tag_one_range":"$tag_two_range":"$tag_three_range + +#create the zone +zone_query="GET http://$host/client/?command=createZone&networktype=Basic&securitygroupenabled=true&name=Zucchini&dns1=4.2.2.2&internaldns1=4.2.2.2 HTTP/1.0\n\n" +echo -e $zone_query | nc -v -w $delay $host 8096 + +#Add Secondary Storage +sstor_query="GET http://$host/client/?command=addSecondaryStorage&zoneid=$zoneid&url=nfs://172.16.15.32/export/share/secondary HTTP/1.0\n\n" +echo -e $sstor_query | nc -v -w $delay $host 8096 + +let x=a +let y=b + +echo "[DEBUG] $(date) Starting Creation of $numberofpods Pods" +for ((name=1;name<=$numberofpods;name++)) +do + echo "[DEBUG] $(date) Creating pod[POD$name]" + pod_query="GET http://$host/client/?command=createPod&zoneId=$zoneid&name=POD$name&netmask=255.255.255.128&startIp=172.$x.$y.130&endIp=172.$x.$y.189&gateway=172.$x.$y.129 HTTP/1.0\n\n" + pod_out=$(echo -e $pod_query | nc -v -w $delay $host 8096) + pod_id=$(echo $pod_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + if ! [[ "$pod_id" =~ ^[0-9]+$ ]] ; then + exec >&2; echo "[ERROR] $(date) pod [POD$name] creation failed"; continue + fi + echo "[DEBUG] $(date) Created pod["$pod_id":POD"$name"]" + pod_array[$name]=$pod_id + + echo "[DEBUG] $(date) Creating vlan for pod[POD$name]" + vlan_query="GET http://$host/client/?command=createVlanIpRange&vlan=untagged&zoneid=$zoneid&podId=$pod_id&forVirtualNetwork=false&gateway=172.$x.$y.129&netmask=255.255.255.128&startip=172.$x.$y.190&endip=172.$x.$y.249 HTTP/1.0\n\n" + vlan_out=$(echo -e $vlan_query | nc -v -w $delay $host 8096) + vlan_id=$(echo $vlan_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + if ! [[ "$vlan_id" =~ ^[0-9]+$ ]] ; then + let y+=1 + if [ "$y" -eq 256 ] + then + let x+=1 + y=1 + fi + exec >&2; echo "[ERROR] $(date) vlan creation for pod[POD$name] failed"; continue + fi + echo "[DEBUG] $(date) Created vlan for pod[POD$name]" + + #add clusters + echo "[DEBUG] $(date) Starting Creation of $clusters_per_pod clusters for pod[POD$name]" + for ((cluster=1;cluster<=$clusters_per_pod;cluster++)) + do + echo "[DEBUG] $(date) Creating cluster[POD$name-CLUSTER$cluster] for pod[POD$name]" + cluster_query="GET http://$host/client/?command=addCluster&hypervisor=Simulator&clustertype=CloudManaged&zoneId=$zoneid&podId=$pod_id&clustername=POD$name-CLUSTER$cluster HTTP/1.0\n\n" + cluster_out=$(echo -e $cluster_query | nc -v -w $delay $host 8096) + cluster_id=$(echo $cluster_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + if ! [[ "$cluster_id" =~ ^[0-9]+$ ]] ; then + exec >&2; echo "[ERROR] $(date) cluster[POD$name-CLUSTER$cluster] creation for pod[POD$name] failed"; continue + fi + echo "[DEBUG] $(date) Created cluster["$cluster_id":POD"$name"-CLUSTER"$cluster"]" + cluster_array[$(($name*$clusters_per_pod + $cluster))]=$cluster_id + done + echo "[DEBUG] $(date) Finished Creating clusters for pod[POD$name]" + let y+=1 + if [ "$y" -eq 256 ] + then + let x+=1 + y=1 + fi +done +echo "[DEBUG] $(date) Finished Creating $numberofpods Pods" + +#echo "DEBUG:Pods and Clusters" +#echo "PODS:("${#pod_array[@]}")" ${pod_array[@]} +#echo "CLUSTERS:("${#cluster_array[@]}")" ${cluster_array[@]} +echo +echo + + +echo "[DEBUG] $(date) Creating $numberofgroups security groups" +for ((sg=1;sg<=$numberofgroups;sg++)) +do + sg_create_query="GET http://$host/client/?command=createSecurityGroup&name=zGroup$sg&description=zGroup$sg&domainid=1&account=admin HTTP/1.0\n\n" + sg_create_out=$(echo -e $sg_create_query | nc -v -w $delay $host 8096) + sg_id=$(echo $sg_create_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + if ! [[ "$sg_id" =~ ^[0-9]+$ ]] ; then + exec >&2; echo "[ERROR] $(date) security group[zGroup$sg] creation failed"; continue + fi + echo "[DEBUG] $(date) Created security group[$sg_id:zGroup$sg]" + + echo "[DEBUG] $(date) Adding ingress rule start,end=$((2000 + $sg)), $((2000 + $sg)) to security group[$sg_id:zGroup$sg]" + sg_auth_query="GET http://$host/client/?command=authorizeSecurityGroupIngress&domainid=1&account=admin&securitygroupid=$sg_id&protocol=TCP&startport=$((2000 + $sg))&endport=$((2000 + $sg))&usersecuritygrouplist[0].account=admin&usersecuritygrouplist[0].group=zGroup$sg HTTP/1.0\n\n" + sg_auth_out=$(echo -e $sg_auth_query | nc -v -w $delay $host 8096) +done +echo "[DEBUG] $(date) Finished Creating security groups" + +#Add hosts +#TAG1 +for ((i=1;i<=$tag_one_range;i++)) +do + podid=${pod_array[$i]} + for ((j=1;j<=$hosts_per_pod;j++)) + do + clusterid=${cluster_array[$(($i*$clusters_per_pod + $j))]} + host_query="GET http://$host/client/?command=addHost&zoneId=$zoneid&podId=$podid&username=sim&password=sim&clusterid=$clusterid&url=http%3A%2F%2Fsim&hypervisor=Simulator&clustertype=CloudManaged&hosttags=$tag1 HTTP/1.0\n\n" + host_out=$(echo -e $host_query | nc -v -w $delay $host 8096) + host_id=$(echo $host_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + if ! [[ "$host_id" =~ ^[0-9]+$ ]] ; then + exec >&2; echo "[ERROR] $(date) host addition failed in [pod:$podid,cluster:$clusterid]"; continue + fi + host_name=$(echo $host_out | sed 's/\(.*\)\(SimulatedAgent.[-0-9a-zA-Z]*\)\(.*\)/\2/g') + echo "[DEBUG] $date added host [$host_id:$host_name] to [pod:$podid,cluster:$clusterid] for TAG1" + done +done + +#TAG2 +for ((i=$(($tag_one_range + 1));i<=$(($tag_one_range + $tag_two_range));i++)) +do + podid=${pod_array[$i]} + for ((j=1;j<=$hosts_per_pod;j++)) + do + clusterid=${cluster_array[$(($i*$clusters_per_pod + $j))]} + host_query="GET http://$host/client/?command=addHost&zoneId=$zoneid&podId=$podid&username=sim&password=sim&clusterid=$clusterid&url=http%3A%2F%2Fsim&hypervisor=Simulator&clustertype=CloudManaged&hosttags=$tag2 HTTP/1.0\n\n" + host_out=$(echo -e $host_query | nc -v -w $delay $host 8096) + host_id=$(echo $host_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + if ! [[ "$host_id" =~ ^[0-9]+$ ]] ; then + exec >&2; echo "[ERROR] $(date) host addition failed in [pod:$podid,cluster:$clusterid]"; continue + fi + host_name=$(echo $host_out | sed 's/\(.*\)\(SimulatedAgent.[-0-9a-zA-Z]*\)\(.*\)/\2/g') + echo "[DEBUG] $date added host [$host_id:$host_name] to [pod:$podid,cluster:$clusterid] for TAG2" + done +done + +#TAG3 +for ((i=$(($tag_two_range + $tag_one_range + 1));i<=$(($tag_three_range + $tag_two_range + $tag_one_range));i++)) +do + podid=${pod_array[$i]} + for ((j=1;j<=$hosts_per_pod;j++)) + do + clusterid=${cluster_array[$(($i*$clusters_per_pod + $j))]} + host_query="GET http://$host/client/?command=addHost&zoneId=$zoneid&podId=$podid&username=sim&password=sim&clusterid=$clusterid&url=http%3A%2F%2Fsim&hypervisor=Simulator&clustertype=CloudManaged&hosttags=$tag3 HTTP/1.0\n\n" + host_out=$(echo -e $host_query | nc -v -w $delay $host 8096) + host_id=$(echo $host_out | sed 's/\(.*\)\([0-9]*\)\(.*\)/\2/g') + if ! [[ "$host_id" =~ ^[0-9]+$ ]] ; then + exec >&2; echo "[ERROR] $(date) host addition failed in [pod:$podid,cluster:$clusterid]"; continue + fi + host_name=$(echo $host_out | sed 's/\(.*\)\(SimulatedAgent.[-0-9a-zA-Z]*\)\(.*\)/\2/g') + echo "[DEBUG] $date added host [$host_id:$host_name] to [pod:$podid,cluster:$clusterid] for TAG3" + done +done + +echo "Setup complete" +exit 0 diff --git a/agent-simulator/scripts/zucchini/__old__/small.sh b/agent-simulator/scripts/zucchini/__old__/small.sh new file mode 100755 index 00000000000..9ffed2322b8 --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/small.sh @@ -0,0 +1,151 @@ +#!/bin/bash + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + +############################################################ +# +# zucchini uses local storage, before setting up make sure +# * xen.public.network.device is set +# * use.local.storage and systemvm.use.local.storage are true +# * optionally turn off stats collector +# * expunge.delay and expunge.interval are 60s +# * capacity.skipcounting.hours=0 + +#Environment +#1. Small setup for zucchini : 13, 26, 39, 52 hosts only +#2. Only 3 host tags. +#3. With in each pod, the host tags are the same. +#4. The ratio of hosts for the three tags should be 5/2/6 +#5. simulator.properties, workers=1 +############################################################ + +usage() { + printf "Setup Zucchini Like Environment\nUsage: %s: -h management-server -z zoneid [-d delay] -n numberofhosts\n" $(basename $0) >&2 +} + +a=1 #CIDR - 16bytes +b=2 #CIDR - 8 bytes + +#options +hflag=1 +zflag=1 +dflag=1 +nflag=1 + +host="127.0.0.1" #default localhost +zoneid= +delay=300 #default 5 minutes +numberofhosts=13 #default 13 hosts +tag1="TAG1" +tag2="TAG2" +tag3="TAG3" + +while getopts 'h:z:d:n:' OPTION +do + case $OPTION in + h) hflag=1 + host="$OPTARG" + ;; + z) zflag=1 + zoneid="$OPTARG" + ;; + d) dflag=1 + delay="$OPTARG" + ;; + n) nflag=1 + numberofhosts="$OPTARG" + ;; + ?) usage + exit 2 + ;; + esac +done + +if [ $hflag$zflag$dflag$nflag != "1111" ] +then + usage + exit 2 +fi + +if [ $numberofhosts -gt 52 ] +then + echo "Can't exceed 52 hosts" + exit 130 +fi + +numberofpods=3 #130 hosts per pod. So need only 3. each pod is homogenous +tag_one_range=$(($numberofhosts*5/13)) +tag_two_range=$(($numberofhosts*2/13)) +tag_three_range=$(($numberofhosts-$tag_one_range-$tag_two_range)) + +#create the zone +zone_query="GET http://$host/client/?command=createZone&networktype=Basic&securitygroupenabled=true&name=Zucchini&dns1=4.2.2.2&internaldns1=4.2.2.2 HTTP/1.0\n\n" +echo -e $zone_query | nc -v -w $delay $host 8096 + +sstor_query="GET http://$host/client/?command=addSecondaryStorage&zoneid=$zoneid&url=nfs://172.16.15.32/export/share/secondary HTTP/1.0\n\n" +echo -e $sstor_query | nc -v -w $delay $host 8096 + +let x=a +let y=b +for name in `seq 1 $numberofpods` +do + pod_query="GET http://$host/client/?command=createPod&zoneId=$zoneid&name=POD$name&netmask=255.255.255.0&startIp=172.$x.$y.2&endIp=172.$x.$y.131&gateway=172.$x.$y.1 HTTP/1.0\n\n" + vlan_query="GET http://$host/client/?command=createVlanIpRange&vlan=untagged&zoneid=$zoneid&podId=$name&forVirtualNetwork=false&gateway=172.$y.$x.1&netmask=255.255.255.0&startip=172.$y.$x.2&endip=172.$y.$x.131 HTTP/1.0\n\n" + echo -e $pod_query | nc -v -w $delay $host 8096 + echo -e $vlan_query | nc -v -w $delay $host 8096 + + let x+=1 + let y+=1 +done + +#add clusters - +#for i in `seq 1 10` +# cluster_query="GET http://$host/client/?command=addCluster&hypervisor=Simulator&clustertype=CloudManaged&zoneId=$zoneid&podId=$podid&clustername=POD$podid-CLUSTER$cluster HTTP/1.0\n\n" +# echo -e $cluster_query | nc -v -w $delay $host 8096 +#do + +clusterid=1 +#TAG1 +for cluster in `seq 1 $tag_one_range` +do + cluster_query="GET http://$host/client/?command=addCluster&hypervisor=Simulator&clustertype=CloudManaged&zoneId=$zoneid&podId=1&clustername=POD1-CLUSTER$cluster HTTP/1.0\n\n" + echo -e $cluster_query | nc -v -w $delay $host 8096 + host_query="GET http://$host/client/?command=addHost&zoneId=$zoneid&podId=1&username=sim&password=sim&clusterid=$clusterid&url=http%3A%2F%2Fsim&hypervisor=Simulator&clustertype=CloudManaged&hosttags=$tag1 HTTP/1.0\n\n" + echo -e $host_query | nc -v -w $delay $host 8096 + let clusterid+=1 +done + +#TAG2 +for cluster in `seq $(($tag_one_range + 1)) $(($tag_one_range + $tag_two_range))` +do + cluster_query="GET http://$host/client/?command=addCluster&hypervisor=Simulator&clustertype=CloudManaged&zoneId=$zoneid&podId=2&clustername=POD2-CLUSTER$cluster HTTP/1.0\n\n" + echo -e $cluster_query | nc -v -w $delay $host 8096 + host_query="GET http://$host/client/?command=addHost&zoneId=$zoneid&podId=2&username=sim&password=sim&clusterid=$clusterid&url=http%3A%2F%2Fsim&hypervisor=Simulator&clustertype=CloudManaged&hosttags=$tag2 HTTP/1.0\n\n" + echo -e $host_query | nc -v -w $delay $host 8096 + let clusterid+=1 +done + +#TAG3 +for cluster in `seq $(($tag_two_range + $tag_one_range + 1)) $(($tag_three_range + $tag_two_range + $tag_one_range))` +do + cluster_query="GET http://$host/client/?command=addCluster&hypervisor=Simulator&clustertype=CloudManaged&zoneId=$zoneid&podId=3&clustername=POD3-CLUSTER$cluster HTTP/1.0\n\n" + echo -e $cluster_query | nc -v -w $delay $host 8096 + host_query="GET http://$host/client/?command=addHost&zoneId=$zoneid&podId=3&username=sim&password=sim&clusterid=$clusterid&url=http%3A%2F%2Fsim&hypervisor=Simulator&clustertype=CloudManaged&hosttags=$tag3 HTTP/1.0\n\n" + echo -e $host_query | nc -v -w $delay $host 8096 + let clusterid+=1 + +done + +for i in {1..60} +do + sg_create_query="GET http://$host/client/?command=createSecurityGroup&name=TestGroup1&description=Test HTTP/1.0\n\n" + echo -e $sg_create_query | nc -v -w $delay $host 8096 + + sg_auth_query="GET http://$host/client/?command=authorizeSecurityGroupIngress&domainid=1&account=admin&securitygroupid=$((i+2))&protocol=TCP&startport=2002&endport=2002&usersecuritygrouplist[0].account=admin&usersecuritygrouplist[0].group=TestGroup1 HTTP/1.0\n\n" + echo -e $sg_create_query | nc -v -w $delay $host 8096 +done + +echo "Setup complete" +exit 0 diff --git a/agent-simulator/scripts/zucchini/__old__/so_setup.sh b/agent-simulator/scripts/zucchini/__old__/so_setup.sh new file mode 100755 index 00000000000..97bee1b5339 --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/so_setup.sh @@ -0,0 +1,7 @@ +#setup service offerings with hosttags - TAG1, TAG2, TAG3 +#offering sizes are such that only one VM sits on each host +host=$1 + +./setupServiceOffering.sh -h $host -i T1 -l -m 7168 -c 1024 -n 1 -g TAG1 +./setupServiceOffering.sh -h $host -i T2 -l -m 7168 -c 1024 -n 1 -g TAG2 +./setupServiceOffering.sh -h $host -i T3 -l -m 7168 -c 1024 -n 1 -g TAG3 diff --git a/agent-simulator/scripts/zucchini/__old__/startRouter.sh b/agent-simulator/scripts/zucchini/__old__/startRouter.sh new file mode 100755 index 00000000000..8667d263790 --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/startRouter.sh @@ -0,0 +1,13 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 + +start_router="GET http://10.91.30.226:8096/client/?command=startRouter&id=$x HTTP/1.0\n\n" + + +echo -e $start_router | nc -v -q 60 10.91.30.226 8096 + diff --git a/agent-simulator/scripts/zucchini/__old__/startVirtualMachine.sh b/agent-simulator/scripts/zucchini/__old__/startVirtualMachine.sh new file mode 100755 index 00000000000..84fa055ff87 --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/startVirtualMachine.sh @@ -0,0 +1,13 @@ + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +x=$1 + +start_vm="GET http://10.91.30.226:8096/client/?command=startVirtualMachine&id=$x HTTP/1.0\n\n" + + +echo -e $start_vm | nc -v -q 60 10.91.30.226 8096 + diff --git a/agent-simulator/scripts/zucchini/__old__/stopRouter.sh b/agent-simulator/scripts/zucchini/__old__/stopRouter.sh new file mode 100755 index 00000000000..51d101cec79 --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/stopRouter.sh @@ -0,0 +1,37 @@ +#!/bin/bash + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + +usage() { + printf "Stop Router: %s: -h management-server -i vmid\n" $(basename $0) >&2 +} + +iflag= +hflag= + +host="127.0.0.1" #defaults to localhost +vmid= + +while getopts 'h:i:' OPTION +do + case $OPTION in + h) hflag=1 + host="$OPTARG" + ;; + i) iflag=1 + vmid="$OPTARG" + ;; + ?) usage + exit 2 + ;; + esac +done + +if [[ $iflag != "1" ]] +then + usage + exit 2 +fi +stop_vm="GET http://$host:8096/client/?command=stopRouter&id=$vmid HTTP/1.0\n\n" +echo -e $stop_vm | nc -v -w 60 $host 8096 diff --git a/agent-simulator/scripts/zucchini/__old__/stopVirtualMachine.sh b/agent-simulator/scripts/zucchini/__old__/stopVirtualMachine.sh new file mode 100755 index 00000000000..a0d26c0c62a --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/stopVirtualMachine.sh @@ -0,0 +1,37 @@ +#!/bin/bash + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + +usage() { + printf "Stop Virtual Machine: %s: -h management-server -i vmid\n" $(basename $0) >&2 +} + +iflag= +hflag= + +host="127.0.0.1" #defaults to localhost +vmid= + +while getopts 'h:i:' OPTION +do + case $OPTION in + h) hflag=1 + host="$OPTARG" + ;; + i) iflag=1 + vmid="$OPTARG" + ;; + ?) usage + exit 2 + ;; + esac +done + +if [[ $iflag != "1" ]] +then + usage + exit 2 +fi +stop_vm="GET http://$host:8096/client/?command=stopVirtualMachine&id=$vmid HTTP/1.0\n\n" +echo -e $stop_vm | nc -v -w 60 $host 8096 diff --git a/agent-simulator/scripts/zucchini/__old__/zucchini219.sh b/agent-simulator/scripts/zucchini/__old__/zucchini219.sh new file mode 100755 index 00000000000..424e9fca127 --- /dev/null +++ b/agent-simulator/scripts/zucchini/__old__/zucchini219.sh @@ -0,0 +1,110 @@ +#!/bin/bash + + + + # + # Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + # + + +#setup for zucchini hosts in the simulator + +#1. Approximately 10 hosts per pod. +#2. Only 3 host tags. +#3. With in each pod, the host tags are the same. +#4. The ratio of hosts for the three tags should be 5/2/6 + +a=$1 #CIDR - 16bytes +b=$2 #CIDR - 8 bytes +host=$3 #MSHOST +zone=$4 + +zone_query="GET http://$host/client/?command=createZone&name=Zucchini&dns1=4.2.2.2&internaldns1=4.2.2.2&vlan=10-4000&guestcidraddress=10.1.1.0%2F24 HTTP/1.0\n\n" +echo -e $zone_query | nc -v -w 120 $host 8096 + +# Pod Ratio: 38:15:47 +let x=a +let y=b +for name in `seq 1 152` +do + pod_query="GET http://$host/client/?command=createPod&zoneId=$zone&name=POD$name&cidr=172.$x.$y.0%2F24&startIp=172.$x.$y.2&endIp=172.$x.$y.252&gateway=172.$x.$y.1 HTTP/1.0\n\n" + vlan_query="GET http://$host/client/?command=createVlanIpRange&vlan=untagged&zoneid=$zone&podId=$name&forVirtualNetwork=false&gateway=172.$y.$x.1&netmask=255.255.255.0&startip=172.$y.$x.2&endip=172.$y.$x.252 HTTP/1.0\n\n" + echo -e $pod_query | nc -v -w 20 $host 8096 + echo -e $vlan_query | nc -v -w 20 $host 8096 + + let x+=1 + let y+=1 +done + + +let x=a +let y=b +for name in `seq 153 212` +do + pod_query="GET http://$host/client/?command=createPod&zoneId=$zone&name=POD$name&cidr=182.$x.$y.0%2F24&startIp=182.$x.$y.2&endIp=182.$x.$y.252&gateway=182.$x.$y.1 HTTP/1.0\n\n" + vlan_query="GET http://$host/client/?command=createVlanIpRange&vlan=untagged&zoneid=$zone&podId=$name&forVirtualNetwork=false&gateway=182.$y.$x.1&netmask=255.255.255.0&startip=182.$y.$x.2&endip=182.$y.$x.252 HTTP/1.0\n\n" + echo -e $pod_query | nc -v -w 20 $host 8096 + echo -e $vlan_query | nc -v -w 20 $host 8096 + + let x+=1 + let y+=1 +done + +let x=a +let y=b +for name in `seq 213 400` +do + + pod_query="GET http://$host/client/?command=createPod&zoneId=$zone&name=POD$name&cidr=192.$x.$y.0%2F24&startIp=192.$x.$y.2&endIp=192.$x.$y.252&gateway=192.$x.$y.1 HTTP/1.0\n\n" + vlan_query="GET http://$host/client/?command=createVlanIpRange&vlan=untagged&zoneid=$zone&podId=$name&forVirtualNetwork=false&gateway=192.$y.$x.1&netmask=255.255.255.0&startip=192.$y.$x.2&endip=192.$y.$x.252 HTTP/1.0\n\n" + echo -e $pod_query | nc -v -w 20 $host 8096 + echo -e $vlan_query | nc -v -w 20 $host 8096 + + let x+=1 + let y+=1 +done + +#add clusters +#for name in `seq 1 400` +#do +# for cluster in `seq 1 10` +# do +# cluster_query="GET http://$host/client/?command=addCluster&hypervisor=Simulator&clustertype=CloudManaged&zoneId=$zone&podId=$name&clustername=POD$name-CLUSTER$cluster HTTP/1.0\n\n" +# echo -e $cluster_query | nc -v -w 120 $host 8096 +# done +#done + +# @ 10 hosts per pod @ 10 clusters per pod +clusterid=1 +#TAG1 +for podid in `seq 58 152` +do + for i in `seq 1 10` + do + host_query="GET http://$host/client/?command=addHost&zoneId=$zone&podId=$podid&username=sim&password=sim&clustername=CLUSTER$clusterid&hosttags=TAG1&url=http%3A%2F%2Fsim HTTP/1.0\n\n" + echo -e $host_query | nc -v -w 6000 $host 8096 + done + let clusterid+=1 +done + +#TAG2 +for podid in `seq 153 212` +do + for i in `seq 1 10` + do + host_query="GET http://$host/client/?command=addHost&zoneId=$zone&podId=$podid&username=sim&password=sim&clustername=CLUSTER$clusterid&hosttags=TAG2&url=http%3A%2F%2Fsim HTTP/1.0\n\n" + echo -e $host_query | nc -v -w 6000 $host 8096 + done + let clusterid+=1 +done + +#TAG3 +for podid in `seq 213 400` +do + for i in `seq 1 10` + do + host_query="GET http://$host/client/?command=addHost&zoneId=$zone&podId=$podid&username=sim&password=sim&cluster=CLUSTER$clusterid&hosttags=TAG3&url=http%3A%2F%2Fsim HTTP/1.0\n\n" + echo -e $host_query | nc -v -w 6000 $host 8096 + done + let clusterid+=1 +done diff --git a/agent-simulator/scripts/zucchini/setup.py b/agent-simulator/scripts/zucchini/setup.py new file mode 100644 index 00000000000..e3fa849e9bd --- /dev/null +++ b/agent-simulator/scripts/zucchini/setup.py @@ -0,0 +1,208 @@ +#!/usr/bin/env python + +''' +############################################################ +# zucchini uses local storage, before setting up make sure +# * xen.public.network.device is set +# * use.local.storage and systemvm.use.local.storage are true +# * optionally turn off stats collectors +# * expunge.delay and expunge.interval are 60s +# * ping.interval is around 3m +# * turn off dns updates to entire zone, network.dns.basiczone.update=pod +# * capacity.skipcounting.hours=0 +# * direct.agent.load.size=1000 +# * security groups are enabled +# +# This script will only setup an approximate number of hosts. To achieve the ratio +# of 5:2:6 hosts the total number of hosts is brought close to a number divisible +# by 13. So if 4000 hosts are added, you might see only 3900 come up +# +# 10 hosts per pod @ 1 host per cluster in a single zone +# +# Each pod has a /25, so 128 addresses. I think we reserved 5 IP addresses for system VMs in each pod. +# Then we had something like 60 addresses for hosts and 60 addresses for VMs. + +#Environment +#1. Approximately 10 hosts per pod. +#2. Only 3 host tags. +#3. With in each pod, the host tags are the same. Homogenous Pods +#4. The ratio of hosts for the three tags should be 5/2/6 +#5. In simulator.properties, workers=1 +############################################################ +''' + +from optparse import OptionParser +from configGenerator import * +import random + +def getGlobalSettings(): + global_settings = {'expunge.delay': '60', + 'expunge.interval': '60', + 'expunge.workers': '3', + 'workers': '10', + 'network.dns.basiczone.updates':'pod', + 'use.user.concentrated.pod.allocation':'false', + 'vm.allocation.algorithm':'firstfit', + 'capacity.check.period':'0', + 'host.stats.interval':'-1', + 'vm.stats.interval':'-1', + 'storage.stats.interval':'-1', + 'router.stats.interval':'-1', + 'vm.op.wait.interval':'5', + 'xen.public.network.device':'10.10.10.10', #only a dummy for the simulator + 'guest.domain.suffix':'zcloud.simulator', + 'instance.name':'ZIM', + 'direct.agent.load.size':'1000', + 'default.page.size':'10000', + 'linkLocalIp.nums':'4', + 'systemvm.use.local.storage':'true', + 'use.local.storage':'true', + 'check.pod.cidrs':'false', + } + for k,v in global_settings.iteritems(): + cfg=configuration() + cfg.name=k + cfg.value=v + yield cfg + +def podIpRangeGenerator(): + x=1 + y=2 + while 1: + if y == 256: + x=x+1 + if x == 256: + break + y=1 + y=y+1 + #pod mangement network + yield ('172.'+str(x)+'.'+str(y)+'.129', + '172.'+str(x)+'.'+str(y)+'.130', + '172.'+str(x)+'.'+str(y)+'.189') + + +def vlanIpRangeGenerator(): + x=1 + y=2 + while 1: + if y == 256: + x=x+1 + if x==256: + break + y=1 + y=y+1 + #vlan ip range + yield ('172.'+str(x)+'.'+str(y)+'.129', + '172.'+str(x)+'.'+str(y)+'.190', + '172.'+str(x)+'.'+str(y)+'.249') + + +def describeZucchiniResources(numberOfAgents=1300, dbnode='localhost', mshost='localhost', randomize=False): + zs=cloudstackConfiguration() + numberofpods=numberOfAgents/10 + tagOneHosts = numberOfAgents*5/13 + tagTwoHosts = numberOfAgents*2/13 + tagThreeHosts = numberOfAgents-tagOneHosts-tagTwoHosts + + clustersPerPod=10 + hostsPerPod=10 + + z = zone() + z.dns1 = '4.2.2.2' + z.dns2 = '192.168.110.254' + z.internaldns1 = '10.91.28.6' + z.internaldns2 = '192.168.110.254' + z.name = 'Zucchini' + z.networktype = 'Basic' + + hosttags=['TAG1' for x in range(tagOneHosts)] + ['TAG2' for x in range(tagTwoHosts)] + ['TAG3' for x in range(tagThreeHosts)] + if randomize: + random.shuffle(hosttags) #randomize the host distribution + curhost=0 + curpod=0 + for podRange,vlanRange in zip(podIpRangeGenerator(), vlanIpRangeGenerator()): + p = pod() + curpod=curpod+1 + p.name = 'POD'+str(curpod) + p.gateway=podRange[0] + p.startip=podRange[1] + p.endip=podRange[2] + p.netmask='255.255.255.128' + + v = iprange() + v.gateway=vlanRange[0] + v.startip=vlanRange[1] + v.endip=vlanRange[2] + v.netmask="255.255.255.128" + p.guestIpRanges.append(v) + + for i in range(1,clustersPerPod+1): + c = cluster() + c.clustername = 'POD'+str(curpod)+'-CLUSTER'+str(i) + c.hypervisor = 'Simulator' + c.clustertype = 'CloudManaged' + + try: + h = host() + h.username = 'root' + h.password = 'password' + h.url = "http://sim/%d/cpucore=4&cpuspeed=8000&memory=%d&localstorage=%d"%(i,8*1024*1024*1024,1*1024*1024*1024*1024) + h.hosttags = hosttags.pop() + c.hosts.append(h) + curhost=curhost+1 + p.clusters.append(c) + except IndexError: + break + #end clusters + z.pods.append(p) + if curpod == numberofpods or curhost == numberOfAgents: + break + #end pods + secondary = secondaryStorage() + secondary.url = 'nfs://172.16.25.32/secondary/path' + z.secondaryStorages.append(secondary) + zs.zones.append(z) + + '''Add mgt server''' + mgt = managementServer() + mgt.mgtSvrIp = mshost #could be the LB balancing the cluster of management server as well + zs.mgtSvr.append(mgt) + + '''Add a database''' + db = dbServer() + db.dbSvr = opts.dbnode + zs.dbSvr = db + + '''Add some configuration''' + [zs.globalConfig.append(cfg) for cfg in getGlobalSettings()] + + ''''add loggers''' + testClientLogger = logger() + testClientLogger.name = "TestClient" + testClientLogger.file = "/var/log/testclient.log" + + testCaseLogger = logger() + testCaseLogger.name = "TestCase" + testCaseLogger.file = "/var/log/testcase.log" + + zs.logger.append(testClientLogger) + zs.logger.append(testCaseLogger) + return zs + +if __name__=="__main__": + parser = OptionParser() +# parser.add_option('-h','--host',dest='host',help='location of management server(s) or load-balancer') + parser.add_option('-n', '--number-of-agents', action='store', dest='agents', help='number of agents in the deployment') + parser.add_option('-g', '--enable-security-groups', dest='sgenabled', help='specify if security groups are to be enabled', default=False, action='store_true') + parser.add_option('-o', '--output', action='store', default='./zucchiniCfg', dest='output', help='the path where the json config file generated') + parser.add_option('-d', '--dbnode', dest='dbnode', help='hostname/ip of the database node', action='store') + parser.add_option('-m', '--mshost', dest='mshost', help='hostname/ip of management server', action='store') + parser.add_option('-r', '--randomize', dest='randomize', help='randomize the distribution of tags (hetergenous clusters)', action='store_true', default=False) + + (opts, args) = parser.parse_args() + mandatories = ['mshost', 'dbnode', 'agents'] + for m in mandatories: + if not opts.__dict__[m]: + print "mandatory option missing" + cfg = describeZucchiniResources(int(opts.agents), opts.dbnode, opts.mshost, opts.randomize) + generate_setup_config(cfg, opts.output) diff --git a/agent-simulator/scripts/zucchini/tests/testProvision.py b/agent-simulator/scripts/zucchini/tests/testProvision.py new file mode 100644 index 00000000000..21acb6e33df --- /dev/null +++ b/agent-simulator/scripts/zucchini/tests/testProvision.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python +''' +Deploy Virtual Machine tests +''' +import unittest +import random +from cloudstackAPI import * + +class Provision(unittest.case.TestCase): + ''' + This should test basic provisioning of virtual machines + 1. Deploy a no-frills VM + 2. Deploy with tags - hosttags + 3. Deploy with/without security groups + ''' + + api = self.testClient.getApiClient() + solist = {} + + def setUp(self): + '''setup service offerings with tags''' + for tag in ['TAG1', 'TAG2', 'TAG3']: + csocmd = createServiceOffering.createServiceOfferingCmd() + csocmd.cpunumber = 1 + csocmd.cpuspeed = 2048 + csocmd.displayText = tag + csocmd.memory = 7168 + csocmd.name = tag + csocmd.hosttags = tag + csocmd.storagetype = 'local' + csoresponse = self.api.createServiceOffering(csocmd) + self.debug("Created Service Offering: %s", tag) + solist[tag]=csoresponse.id + + + def tearDown(self): + ''' Any cleanup post tests ''' + + def test_DeployVMWithHostTags(self): + ''' + Deploy 3 virtual machines one with each hosttag + ''' + for k,v in solist: + deployVmCmd = deployVirtualMachine.deployVirtualMachineCmd() + deployVmCmd.zoneid = 1 + deployVmCmd.hypervisor='Simulator' + deployVmCmd.serviceofferingid=v + deployVmCmd.account='admin' + deployVmCmd.domainid=1 + deployVmCmd.templateid=2 + deployVmResponse = self.api.deployVirtualMachine(deployVmCmd) + self.debug("Deployed VM :%d in job: %d",deployVmResponse.id, deployVmResponse.jobid) + + + def deployCmd(self, tag): + deployVmCmd = deployVirtualMachine.deployVirtualMachineCmd() + deployVmCmd.zoneid = 1 + deployVmCmd.hypervisor='Simulator' + deployVmCmd.serviceofferingid=solist[tag] + deployVmCmd.account='admin' + deployVmCmd.domainid=1 + deployVmCmd.templateid=2 + return deployVmCmd + + def deployN(self,nargs=300,batchsize=0): + ''' + Deploy Nargs number of VMs concurrently in batches of size {batchsize}. + When batchsize is 0 all Vms are deployed in one batch + VMs will be deployed in 5:2:6 ratio + ''' + tag1=nargs*5/13 + tag2=nargs*2/13 + tag3=nargs-tag1-tag2 + + cmds = [] + [cmds.append(deployCmd('TAG1')) for i in range(tag1)] + [cmds.append(deployCmd('TAG2')) for i in range(tag2)] + [cmds.append(deployCmd('TAG3')) for i in range(tag3)] + random.shuffle(cmds) #with mix-and-match of Tags + + if batchsize == 0: + self.testClient.submitCmdsAndWait(cmds) + else: + while len(z) > 0: + try: + newbatch = [cmds.pop() for b in range(batchsize)] #pop batchsize items + self.testClient.submitCmdsAndWait(newbatch) + except IndexError: + break + + def test_bulkDeploy(self): + deployN(130,0) + deployN(nargs=3000,batchsize=100) + + + + + + + + diff --git a/agent-simulator/scripts/zucchini/zucchini.configuration.sql b/agent-simulator/scripts/zucchini/zucchini.configuration.sql new file mode 100644 index 00000000000..3f81b64d259 --- /dev/null +++ b/agent-simulator/scripts/zucchini/zucchini.configuration.sql @@ -0,0 +1,29 @@ +update configuration set value='pod' where name='network.dns.basiczone.updates'; + +update configuration set value='false' where name='use.user.concentrated.pod.allocation'; +update configuration set value='firstfit' where name='vm.allocation.algorithm'; + +update configuration set value='60' where name='expunge.delay'; +update configuration set value='60' where name='expunge.interval'; +update configuration set value='3' where name='expunge.workers'; +update configuration set value='10' where name='workers'; + +update configuration set value='0' where name='capacity.check.period'; +update configuration set value='-1' where name='host.stats.interval'; +update configuration set value='-1' where name='vm.stats.interval'; +update configuration set value='-1' where name='storage.stats.interval'; +update configuration set value='-1' where name='router.stats.interval'; +update configuration set value='5' where name like 'vm.op.wait.interval'; + +update configuration set value='10.10.10.10' where name='xen.public.network.device'; +update configuration set value='zcloud.simulator' where name='guest.domain.suffix'; +update configuration set value='ZIM' where name='instance.name'; + +update configuration set value='1000' where name='direct.agent.load.size'; +update configuration set value='10000' where name='default.page.size'; +update configuration set value='4' where name='linkLocalIp.nums'; +update configuration set value='true' where name like '%local.storage%'; +update configuration set value='false' where name like '%check.pod.cidr%'; + +update configuration set value='100' where name like '%network.security%pool%'; +update configuration set value='120' where name like 'network.securitygroups.work.cleanup.interval'; diff --git a/agent-simulator/src/com/cloud/agent/MetricsCollector.java b/agent-simulator/src/com/cloud/agent/MetricsCollector.java new file mode 100644 index 00000000000..2bb258e0aca --- /dev/null +++ b/agent-simulator/src/com/cloud/agent/MetricsCollector.java @@ -0,0 +1,110 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.agent; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import org.apache.log4j.Logger; + +import com.cloud.utils.concurrency.NamedThreadFactory; + +public class MetricsCollector { + private static final Logger s_logger = Logger.getLogger(MetricsCollector.class); + + private final Set vmNames = new HashSet(); + private final Set newVMnames = new HashSet(); + private final Map metricsMap = new HashMap(); + + private final transient ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1, new NamedThreadFactory("Metrics")); + + private Set _currentVms; + + public MetricsCollector(Set currentVms) { + _currentVms = currentVms; + getAllVMNames(); + } + + public MetricsCollector() { + + } + + public synchronized void getAllVMNames() { + Set currentVMs = _currentVms; + + newVMnames.clear(); + newVMnames.addAll(currentVMs); + newVMnames.removeAll(vmNames); //leave only new vms + + vmNames.removeAll(currentVMs); //old vms - current vms --> leave non-running vms; + for (String vm: vmNames) { + removeVM(vm); + } + + vmNames.clear(); + vmNames.addAll(currentVMs); + } + + public synchronized void submitMetricsJobs() { + s_logger.debug("Submit Metric Jobs called"); + + for (String vm : newVMnames) { + MockVmMetrics task = new MockVmMetrics(vm); + if (!metricsMap.containsKey(vm)) { + metricsMap.put(vm, task); + ScheduledFuture sf = executor.scheduleWithFixedDelay(task, 2, 600, TimeUnit.SECONDS); + task.setFuture(sf); + } + } + newVMnames.clear(); + } + + public synchronized void addVM(String vmName) { + newVMnames.add(vmName); + s_logger.debug("Added vm name= " + vmName); + } + + public synchronized void removeVM(String vmName) { + newVMnames.remove(vmName); + vmNames.remove(vmName); + MockVmMetrics task = metricsMap.get(vmName); + if (task != null) { + task.stop(); + boolean r1= task.getFuture().cancel(false); + metricsMap.remove(vmName); + s_logger.debug("removeVM: cancel returned " + r1 + " for VM " + vmName); + } else { + s_logger.warn("removeVM called for nonexistent VM " + vmName); + } + } + + public synchronized Set getVMNames() { + return vmNames; + } + + public synchronized Map getMetricsMap() { + return metricsMap; + } +} diff --git a/agent-simulator/src/com/cloud/agent/MockVmMetrics.java b/agent-simulator/src/com/cloud/agent/MockVmMetrics.java new file mode 100644 index 00000000000..49184ea2a0f --- /dev/null +++ b/agent-simulator/src/com/cloud/agent/MockVmMetrics.java @@ -0,0 +1,210 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.agent; + +import java.util.HashMap; +import java.util.Map; +import java.util.Random; +import java.util.concurrent.ScheduledFuture; + +import org.apache.log4j.Logger; + +public class MockVmMetrics implements Runnable { + private static final Logger s_logger = Logger.getLogger(MockVmMetrics.class); + + private String vmName; + + //the maximum number of network interfaces to a VM (should be 1) + public final int MAX_INTERFACES=1; + + //the maximum number of disks to a VM + public final int MAX_DISKS=8; + + //the last calculated traffic speed (transmit) per interface + private Map netTxKBps = new HashMap(); + + //the last calculated traffic speed (receive) per interface + private Map netRxKBps = new HashMap(); + + //the last calculated disk write speed per disk (Bytes Per Second) + private Map diskWriteKBytesPerSec = new HashMap(); + + //the last calculated disk read speed per disk (Bytes Per Second) + private Map diskReadKBytesPerSec = new HashMap(); + + //Total Bytes Transmitted on network interfaces + private Map netTxTotalBytes = new HashMap(); + + //Total Bytes Received on network interfaces + private Map netRxTotalBytes = new HashMap(); + + //Total Bytes read per disk + private Map diskReadTotalBytes = new HashMap(); + + //Total Bytes written per disk + private Map diskWriteTotalBytes = new HashMap(); + + //CPU time in seconds + private Double cpuSeconds = new Double(0.0); + + //CPU percentage + private Float cpuPercent = new Float(0.0); + + private Map diskMap = new HashMap(); + + private Map vifMap = new HashMap(); + + private Map diskStatTimestamp = new HashMap(); + private Map netStatTimestamp = new HashMap(); + + private long cpuStatTimestamp = 0L; + + private ScheduledFuture future; + private boolean stopped = false; + private Random randSeed = new Random(); + + public MockVmMetrics(String vmName) { + this.vmName = vmName; + vifMap.put("eth0", "eth0"); + vifMap.put("eth1", "eth1"); + vifMap.put("eth2", "eth2"); + + Long networkStart = 0L; + netTxTotalBytes.put("eth0", networkStart); + netRxTotalBytes.put("eth0", networkStart); + + netTxTotalBytes.put("eth1", networkStart); + netRxTotalBytes.put("eth1", networkStart); + + netTxTotalBytes.put("eth2", networkStart); + netRxTotalBytes.put("eth2", networkStart); + } + + private int getIncrementor() { + return randSeed.nextInt(100); + } + + @Override + public void run() { + if(s_logger.isDebugEnabled()) { + s_logger.debug("Generating MockVM metrics"); + } + for (Map.Entry entry : netRxTotalBytes.entrySet()) { + entry.setValue(entry.getValue() + getIncrementor()); + } + + for (Map.Entry entry : netTxTotalBytes.entrySet()) { + entry.setValue(entry.getValue() + getIncrementor()); + } + } + + public String getVmName() { + return vmName; + } + + public Map getNetTxKBps() { + return netTxKBps; + } + + public Map getNetRxKBps() { + return netRxKBps; + } + + public Map getDiskWriteBytesPerSec() { + return diskWriteKBytesPerSec; + } + + public Map getDiskReadBytesPerSec() { + return diskReadKBytesPerSec; + } + + public Map getNetTxTotalBytes() { + return netTxTotalBytes; + } + + public Map getNetRxTotalBytes() { + return netRxTotalBytes; + } + + public Map getDiskReadTotalBytes() { + return diskReadTotalBytes; + } + + public Map getDiskWriteTotalBytes() { + return diskWriteTotalBytes; + } + + public Double getNetTxKBps(String intf) { + return netTxKBps.get(intf); + } + + public Double getNetRxKBps(String intf) { + return netRxKBps.get(intf); + } + + public Double getDiskWriteKBytesPerSec(String disk) { + return diskWriteKBytesPerSec.get(disk); + } + + public Double getDiskReadKBytesPerSec(String disk) { + return diskReadKBytesPerSec.get(disk); + } + + public Long getNetTxTotalBytes(String intf) { + return netTxTotalBytes.get(intf); + } + + public Long getNetRxTotalBytes(String intf) { + return netRxTotalBytes.get(intf); + } + + public Long getDiskReadTotalBytes(String disk) { + return diskReadTotalBytes.get(disk); + } + + public Long getDiskWriteTotalBytes(String disk) { + return diskWriteTotalBytes.get(disk); + } + + public Double getCpuSeconds() { + return cpuSeconds; + } + + public Map getDiskMap() { + return diskMap; + } + + public Float getCpuPercent() { + return cpuPercent; + } + + public void setFuture(ScheduledFuture sf) { + this.future = sf; + } + + public ScheduledFuture getFuture() { + return future; + } + + public void stop() { + this.stopped = true; + } +} + diff --git a/agent-simulator/src/com/cloud/agent/MultiCaster.java b/agent-simulator/src/com/cloud/agent/MultiCaster.java new file mode 100644 index 00000000000..f282a2f401e --- /dev/null +++ b/agent-simulator/src/com/cloud/agent/MultiCaster.java @@ -0,0 +1,149 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.agent; + +import java.util.*; +import java.net.*; +import java.io.*; + +import org.apache.log4j.Logger; + +public class MultiCaster implements Runnable { + private static final Logger s_logger = Logger.getLogger(MultiCaster.class); + + public final int MAX_PACKET_SIZE = 8096; + + private List listeners; + private DatagramSocket socket; + private byte[] recvBuffer; + + private Thread driver; + private volatile boolean stopRequested = false; + + public MultiCaster() { + listeners = new ArrayList(); + recvBuffer = new byte[MAX_PACKET_SIZE]; + } + + public void addListener(MultiCasterListener listener) { + synchronized(listeners) { + listeners.add(listener); + } + } + + public void removeListener(MultiCasterListener listener) { + synchronized(listeners) { + listeners.remove(listener); + } + } + + public void cast(byte[] buf, int off, int len, + InetAddress toAddress, int nToPort) throws IOException { + + if(socket == null) + throw new IOException("multi caster is not started"); + + if(len >= MAX_PACKET_SIZE) + throw new IOException("packet size exceeds limit of " + MAX_PACKET_SIZE); + + DatagramPacket packet = new DatagramPacket(buf, off, + len, toAddress, nToPort); + + socket.send(packet); + } + + public void start(String strOutboundAddress, + String strClusterAddress, int nPort) throws SocketException { + assert(socket == null); + + InetAddress addr = null; + try { + addr = InetAddress.getByName(strClusterAddress); + } catch(IOException e) { + s_logger.error("Unexpected exception " , e); + } + + if(addr != null && addr.isMulticastAddress()) { + try { + socket = new MulticastSocket(nPort); + socket.setReuseAddress(true); + + if(s_logger.isInfoEnabled()) + s_logger.info("Join multicast group : " + addr); + + ((MulticastSocket)socket).joinGroup(addr); + ((MulticastSocket)socket).setTimeToLive(1); + + if(strOutboundAddress != null) { + if(s_logger.isInfoEnabled()) + s_logger.info("set outgoing interface to : " + strOutboundAddress); + + InetAddress ia = InetAddress.getByName(strOutboundAddress); + NetworkInterface ni = NetworkInterface.getByInetAddress(ia); + ((MulticastSocket)socket).setNetworkInterface(ni); + } + } catch(IOException e) { + s_logger.error("Unexpected exception " , e); + } + } else { + socket = new DatagramSocket(nPort); + socket.setReuseAddress(true); + } + + driver = new Thread(this, "Multi-caster"); + driver.setDaemon(true); + driver.start(); + } + + public void stop() { + if(socket != null) { + stopRequested = true; + + socket.close(); + if(driver != null) { + try { + driver.join(); + } catch(InterruptedException e) { + } + driver = null; + } + } + + socket = null; + stopRequested = false; + } + + public void run() { + while(!stopRequested) { + try { + DatagramPacket packet = new DatagramPacket(recvBuffer, recvBuffer.length); + socket.receive(packet); + + for(Object listener : listeners.toArray()) { + ((MultiCasterListener)listener).onMultiCasting(packet.getData(), + packet.getOffset(), packet.getLength(), packet.getAddress()); + } + } catch(IOException e) { + } catch(Throwable e) { + s_logger.error("Unhandled exception : ", e); + } + } + } +} diff --git a/agent-simulator/src/com/cloud/agent/MultiCasterListener.java b/agent-simulator/src/com/cloud/agent/MultiCasterListener.java new file mode 100644 index 00000000000..b42978d8bc9 --- /dev/null +++ b/agent-simulator/src/com/cloud/agent/MultiCasterListener.java @@ -0,0 +1,25 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.agent; +import java.net.*; + +public interface MultiCasterListener { + public void onMultiCasting(byte[] data, int off, int len, InetAddress addrFrom); +} diff --git a/agent-simulator/src/com/cloud/agent/SimulatorCmd.java b/agent-simulator/src/com/cloud/agent/SimulatorCmd.java new file mode 100644 index 00000000000..61d86ba7818 --- /dev/null +++ b/agent-simulator/src/com/cloud/agent/SimulatorCmd.java @@ -0,0 +1,40 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.agent; + +import java.io.Serializable; + +public class SimulatorCmd implements Serializable { + private static final long serialVersionUID = 1L; + + private String testCase = "DEFAULT"; + + public SimulatorCmd(String testCase) { + this.testCase = testCase; + } + + public String getTestCase() { + return testCase; + } + + public void setTestCase(String testCase) { + this.testCase = testCase; + } +} diff --git a/agent-simulator/src/com/cloud/agent/SimulatorMigrateVmCmd.java b/agent-simulator/src/com/cloud/agent/SimulatorMigrateVmCmd.java new file mode 100644 index 00000000000..0b1357a1350 --- /dev/null +++ b/agent-simulator/src/com/cloud/agent/SimulatorMigrateVmCmd.java @@ -0,0 +1,86 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.agent; + +public class SimulatorMigrateVmCmd extends SimulatorCmd { + + private static final long serialVersionUID = 1L; + + private String destIp; + + private String vmName; + private long ramSize; + private int cpuCount; + private int utilization; + + public SimulatorMigrateVmCmd(String testCase) { + super(testCase); + } + + public String getDestIp() { + return destIp; + } + + public void setDestIp(String destIp) { + this.destIp = destIp; + } + + public String getVmName() { + return vmName; + } + + public void setVmName(String vmName) { + this.vmName = vmName; + } + + public long getRamSize() { + return ramSize; + } + + public void setRamSize(long ramSize) { + this.ramSize = ramSize; + } + + public int getCpuCount() { + return cpuCount; + } + + public void setCpuCount(int cpuCount) { + this.cpuCount = cpuCount; + } + + public int getUtilization() { + return utilization; + } + + public void setUtilization(int utilization) { + this.utilization = utilization; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("SimulatorMigrateVmCmd {").append("vm: ").append(getVmName()); + sb.append(", destIp: ").append(getDestIp()).append(", ramSize: ").append(getRamSize()); + sb.append(", cpuCount: ").append(getCpuCount()).append(", utilization: ").append(getUtilization()); + sb.append("}"); + + return sb.toString(); + } +} diff --git a/agent-simulator/src/com/cloud/agent/manager/MockAgentManager.java b/agent-simulator/src/com/cloud/agent/manager/MockAgentManager.java new file mode 100644 index 00000000000..ce2cf58a6c9 --- /dev/null +++ b/agent-simulator/src/com/cloud/agent/manager/MockAgentManager.java @@ -0,0 +1,48 @@ +package com.cloud.agent.manager; + +import java.util.Map; + +import javax.naming.ConfigurationException; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CheckHealthAnswer; +import com.cloud.agent.api.CheckHealthCommand; +import com.cloud.agent.api.GetHostStatsAnswer; +import com.cloud.agent.api.GetHostStatsCommand; +import com.cloud.agent.api.HostStatsEntry; +import com.cloud.agent.api.MaintainCommand; +import com.cloud.agent.api.PingTestCommand; +import com.cloud.agent.api.PrepareForMigrationAnswer; +import com.cloud.agent.api.PrepareForMigrationCommand; +import com.cloud.agent.api.ReadyAnswer; +import com.cloud.agent.api.ReadyCommand; +import com.cloud.agent.api.SecurityIngressRulesCmd; +import com.cloud.agent.api.ShutdownCommand; +import com.cloud.resource.AgentResourceBase; +import com.cloud.simulator.MockHost; +import com.cloud.utils.component.Manager; + +public interface MockAgentManager extends Manager { + public static final long DEFAULT_HOST_MEM_SIZE = 8 * 1024 * 1024 * 1024L; // 8G, unit of + // Mbytes + public static final int DEFAULT_HOST_CPU_CORES = 4; // 2 dual core CPUs (2 x + // 2) + public static final int DEFAULT_HOST_SPEED_MHZ = 8000; // 1 GHz CPUs + boolean configure(String name, Map params) throws ConfigurationException; + + Map> createServerResources(Map params); + + boolean handleSystemVMStart(long vmId, String privateIpAddress, String privateMacAddress, String privateNetMask, long dcId, long podId, String name, String vmType, String url); + + boolean handleSystemVMStop(long vmId); + + GetHostStatsAnswer getHostStatistic(GetHostStatsCommand cmd); + Answer checkHealth(CheckHealthCommand cmd); + Answer pingTest(PingTestCommand cmd); + + Answer PrepareForMigration(PrepareForMigrationCommand cmd); + + MockHost getHost(String guid); + + Answer MaintainCommand(MaintainCommand cmd); +} diff --git a/agent-simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java b/agent-simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java new file mode 100644 index 00000000000..5fcdff62648 --- /dev/null +++ b/agent-simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java @@ -0,0 +1,353 @@ +package com.cloud.agent.manager; + +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.regex.PatternSyntaxException; + +import javax.ejb.Local; +import javax.naming.ConfigurationException; + +import org.apache.log4j.Logger; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CheckHealthCommand; +import com.cloud.agent.api.GetHostStatsAnswer; +import com.cloud.agent.api.GetHostStatsCommand; +import com.cloud.agent.api.HostStatsEntry; +import com.cloud.agent.api.PingTestCommand; +import com.cloud.agent.api.PrepareForMigrationAnswer; +import com.cloud.agent.api.PrepareForMigrationCommand; +import com.cloud.agent.api.SecurityIngressRulesCmd; +import com.cloud.agent.api.ShutdownCommand; +import com.cloud.dc.dao.HostPodDao; +import com.cloud.host.Host.Type; +import com.cloud.resource.AgentResourceBase; +import com.cloud.resource.AgentRoutingResource; +import com.cloud.resource.AgentStorageResource; +import com.cloud.simulator.MockHost; +import com.cloud.simulator.MockHostVO; +import com.cloud.simulator.MockVMVO; +import com.cloud.simulator.dao.MockHostDao; +import com.cloud.simulator.dao.MockVMDao; + +import com.cloud.utils.Pair; + +import com.cloud.utils.component.Inject; +import com.cloud.utils.concurrency.NamedThreadFactory; +import com.cloud.utils.db.DB; +import com.cloud.utils.net.NetUtils; + +@Local(value = { MockAgentManager.class }) +public class MockAgentManagerImpl implements MockAgentManager { + private static final Logger s_logger = Logger.getLogger(MockAgentManagerImpl.class); + @Inject HostPodDao _podDao = null; + @Inject MockHostDao _mockHostDao = null; + @Inject MockVMDao _mockVmDao = null; + @Inject SimulatorManager _simulatorMgr = null; + @Inject AgentManager _agentMgr = null; + @Inject MockStorageManager _storageMgr = null; + private SecureRandom random; + private Map _resources = new ConcurrentHashMap(); + private ThreadPoolExecutor _executor; + + private Pair getPodCidr(long podId, long dcId) { + try { + + HashMap> podMap = _podDao + .getCurrentPodCidrSubnets(dcId, 0); + List cidrPair = podMap.get(podId); + String cidrAddress = (String) cidrPair.get(0); + Long cidrSize = (Long)cidrPair.get(1); + return new Pair(cidrAddress, cidrSize); + } catch (PatternSyntaxException e) { + s_logger.error("Exception while splitting pod cidr"); + return null; + } catch(IndexOutOfBoundsException e) { + s_logger.error("Invalid pod cidr. Please check"); + return null; + } + } + + + private String getIpAddress(long instanceId, long dcId, long podId) { + Pair cidr = this.getPodCidr(podId, dcId); + return NetUtils.long2Ip(NetUtils.ip2Long(cidr.first()) + instanceId); + } + + private String getMacAddress(long dcId, long podId, long clusterId, int instanceId) { + return NetUtils.long2Mac((dcId << 40 + podId << 32 + clusterId << 24 + instanceId)); + } + public synchronized int getNextAgentId(long cidrSize) { + return random.nextInt((int)cidrSize); + } + + @Override + @DB + public Map> createServerResources( + Map params) { + + Map args = new HashMap(); + Map> newResources = new HashMap>(); + AgentResourceBase agentResource; + long cpuCore = Long.parseLong((String)params.get("cpucore")); + long cpuSpeed = Long.parseLong((String)params.get("cpuspeed")); + long memory = Long.parseLong((String)params.get("memory")); + long localStorageSize = Long.parseLong((String)params.get("localstorage")); + synchronized (this) { + long dataCenterId = Long.parseLong((String)params.get("zone")); + long podId = Long.parseLong((String)params.get("pod")); + long clusterId = Long.parseLong((String)params.get("cluster")); + long cidrSize = getPodCidr(podId, dataCenterId).second(); + + int agentId = getNextAgentId(cidrSize); + String ipAddress = getIpAddress(agentId, dataCenterId, podId); + String macAddress = getMacAddress(dataCenterId, podId, clusterId, agentId); + MockHostVO mockHost = new MockHostVO(); + mockHost.setDataCenterId(dataCenterId); + mockHost.setPodId(podId); + mockHost.setClusterId(clusterId); + mockHost.setCapabilities("hvm"); + mockHost.setCpuCount(cpuCore); + mockHost.setCpuSpeed(cpuSpeed); + mockHost.setMemorySize(memory); + String guid = UUID.randomUUID().toString(); + mockHost.setGuid(guid); + mockHost.setName("SimulatedAgent." + guid); + mockHost.setPrivateIpAddress(ipAddress); + mockHost.setPublicIpAddress(ipAddress); + mockHost.setStorageIpAddress(ipAddress); + mockHost.setPrivateMacAddress(macAddress); + mockHost.setPublicMacAddress(macAddress); + mockHost.setStorageMacAddress(macAddress); + mockHost.setVersion(this.getClass().getPackage().getImplementationVersion()); + mockHost.setResource("com.cloud.agent.AgentRoutingResource"); + mockHost = _mockHostDao.persist(mockHost); + + _storageMgr.getLocalStorage(guid, localStorageSize); + + agentResource = new AgentRoutingResource(); + if (agentResource != null) { + try { + params.put("guid", mockHost.getGuid()); + agentResource.start(); + agentResource.configure(mockHost.getName(), + params); + + newResources.put(agentResource, args); + } catch (ConfigurationException e) { + s_logger + .error("error while configuring server resource" + + e.getMessage()); + } + } + } + return newResources; + } + + + @Override + public boolean configure(String name, Map params) + throws ConfigurationException { + try { + random = SecureRandom.getInstance("SHA1PRNG"); + _executor = new ThreadPoolExecutor(1, 5, 1, TimeUnit.DAYS, new LinkedBlockingQueue(), new NamedThreadFactory("Simulator-Agent-Mgr")); + //ComponentLocator locator = ComponentLocator.getCurrentLocator(); + //_simulatorMgr = (SimulatorManager) locator.getComponent(SimulatorManager.Name); + } catch (NoSuchAlgorithmException e) { + s_logger.debug("Failed to initialize random:" + e.toString()); + return false; + } + return true; + } + + @Override + public boolean handleSystemVMStart(long vmId, String privateIpAddress, String privateMacAddress, String privateNetMask, long dcId, long podId, String name, String vmType, String url) { + _executor.execute(new SystemVMHandler(vmId, privateIpAddress, privateMacAddress, privateNetMask, dcId, podId, name, vmType, _simulatorMgr, url)); + return true; + } + + @Override + public boolean handleSystemVMStop(long vmId) { + _executor.execute(new SystemVMHandler(vmId)); + return true; + } + + private class SystemVMHandler implements Runnable { + private long vmId; + private String privateIpAddress; + private String privateMacAddress; + private String privateNetMask; + private long dcId; + private long podId; + private String guid; + private String name; + private String vmType; + private SimulatorManager mgr; + private String mode; + private String url; + public SystemVMHandler(long vmId, String privateIpAddress, String privateMacAddress, String privateNetMask, long dcId, long podId, String name, String vmType, + SimulatorManager mgr, String url) { + this.vmId = vmId; + this.privateIpAddress = privateIpAddress; + this.privateMacAddress = privateMacAddress; + this.privateNetMask = privateNetMask; + this.dcId = dcId; + this.guid = "SystemVM-" + UUID.randomUUID().toString(); + this.name = name; + this.vmType = vmType; + this.mgr = mgr; + this.mode = "Start"; + this.url = url; + this.podId = podId; + } + + public SystemVMHandler(long vmId) { + this.vmId = vmId; + this.mode = "Stop"; + } + + @Override + @DB + public void run() { + if (this.mode.equalsIgnoreCase("Stop")) { + MockHost host = _mockHostDao.findByVmId(this.vmId); + if (host != null) { + String guid = host.getGuid(); + if (guid != null) { + AgentResourceBase res = _resources.get(guid); + if (res != null) { + res.stop(); + _resources.remove(guid); + } + } + } + return; + } + + String resource = null; + if (vmType.equalsIgnoreCase("secstorage")) { + resource = "com.cloud.agent.AgentStorageResource"; + } + MockHostVO mockHost = new MockHostVO(); + mockHost.setDataCenterId(this.dcId); + mockHost.setPodId(this.podId); + mockHost.setCpuCount(DEFAULT_HOST_CPU_CORES); + mockHost.setCpuSpeed(DEFAULT_HOST_SPEED_MHZ); + mockHost.setMemorySize(DEFAULT_HOST_MEM_SIZE); + mockHost.setGuid(this.guid); + mockHost.setName(name); + mockHost.setPrivateIpAddress(this.privateIpAddress); + mockHost.setPublicIpAddress(this.privateIpAddress); + mockHost.setStorageIpAddress(this.privateIpAddress); + mockHost.setPrivateMacAddress(this.privateMacAddress); + mockHost.setPublicMacAddress(this.privateMacAddress); + mockHost.setStorageMacAddress(this.privateMacAddress); + mockHost.setVersion(this.getClass().getPackage().getImplementationVersion()); + mockHost.setResource(resource); + mockHost.setVmId(vmId); + mockHost = _mockHostDao.persist(mockHost); + + if (vmType.equalsIgnoreCase("secstorage")) { + AgentStorageResource storageResource = new AgentStorageResource(); + try { + Map params = new HashMap(); + params.put("guid", this.guid); + storageResource.configure("secondaryStorage", params); + storageResource.start(); + } catch (ConfigurationException e) { + s_logger.debug("Failed to load secondary storage resource: " + e.toString()); + return; + } + Map details = new HashMap(); + + _agentMgr.addHost(this.dcId, storageResource, Type.SecondaryStorageVM, details); + _resources.put(this.guid, storageResource); + } + + } + + } + + @Override + public MockHost getHost(String guid) { + return _mockHostDao.findByGuid(guid); + } + + @Override + public GetHostStatsAnswer getHostStatistic(GetHostStatsCommand cmd) { + String hostGuid = cmd.getHostGuid(); + MockHost host = _mockHostDao.findByGuid(hostGuid); + if (host == null) { + return null; + } + List vms = _mockVmDao.findByHostId(host.getId()); + double usedMem = 0.0; + double usedCpu = 0.0; + for (MockVMVO vm : vms) { + usedMem += vm.getMemory(); + usedCpu += vm.getCpu(); + } + + HostStatsEntry hostStats = new HostStatsEntry(); + hostStats.setTotalMemoryKBs(host.getMemorySize()); + hostStats.setFreeMemoryKBs(host.getMemorySize() - usedMem); + hostStats.setNetworkReadKBs(32768); + hostStats.setNetworkWriteKBs(16384); + hostStats.setCpuUtilization(usedCpu/(host.getCpuCount() * host.getCpuSpeed())); + hostStats.setEntityType("simulator-host"); + hostStats.setHostId(cmd.getHostId()); + return new GetHostStatsAnswer(cmd, hostStats); + } + + + @Override + public Answer checkHealth(CheckHealthCommand cmd) { + return new Answer(cmd); + } + + + @Override + public Answer pingTest(PingTestCommand cmd) { + return new Answer(cmd); + } + + + @Override + public PrepareForMigrationAnswer PrepareForMigration(PrepareForMigrationCommand cmd) { + return new PrepareForMigrationAnswer(cmd); + } + + + @Override + public boolean start() { + return true; + } + + + @Override + public boolean stop() { + return true; + } + + + @Override + public String getName() { + return this.getClass().getSimpleName(); + } + + + @Override + public Answer MaintainCommand(com.cloud.agent.api.MaintainCommand cmd) { + return new Answer(cmd); + } +} diff --git a/agent-simulator/src/com/cloud/agent/manager/MockStorageManager.java b/agent-simulator/src/com/cloud/agent/manager/MockStorageManager.java new file mode 100644 index 00000000000..345c51e2f51 --- /dev/null +++ b/agent-simulator/src/com/cloud/agent/manager/MockStorageManager.java @@ -0,0 +1,81 @@ +/** + * Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + */ + +package com.cloud.agent.manager; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.AttachIsoCommand; +import com.cloud.agent.api.AttachVolumeAnswer; +import com.cloud.agent.api.AttachVolumeCommand; +import com.cloud.agent.api.BackupSnapshotAnswer; +import com.cloud.agent.api.BackupSnapshotCommand; +import com.cloud.agent.api.ComputeChecksumCommand; +import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand; +import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand; +import com.cloud.agent.api.CreateStoragePoolCommand; +import com.cloud.agent.api.CreateVolumeFromSnapshotAnswer; +import com.cloud.agent.api.CreateVolumeFromSnapshotCommand; +import com.cloud.agent.api.DeleteSnapshotBackupAnswer; +import com.cloud.agent.api.DeleteSnapshotBackupCommand; +import com.cloud.agent.api.DeleteStoragePoolCommand; +import com.cloud.agent.api.GetStorageStatsAnswer; +import com.cloud.agent.api.GetStorageStatsCommand; +import com.cloud.agent.api.ManageSnapshotAnswer; +import com.cloud.agent.api.ManageSnapshotCommand; +import com.cloud.agent.api.ModifyStoragePoolCommand; +import com.cloud.agent.api.SecStorageSetupCommand; +import com.cloud.agent.api.SecStorageVMSetupCommand; +import com.cloud.agent.api.StoragePoolInfo; +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.storage.CreatePrivateTemplateCommand; +import com.cloud.agent.api.storage.DeleteTemplateCommand; +import com.cloud.agent.api.storage.DestroyCommand; +import com.cloud.agent.api.storage.DownloadCommand; +import com.cloud.agent.api.storage.DownloadProgressCommand; +import com.cloud.agent.api.storage.ListTemplateCommand; +import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer; +import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; +import com.cloud.utils.component.Manager; + +public interface MockStorageManager extends Manager { + public static final long DEFAULT_HOST_STORAGE_SIZE = 1 * 1024 * 1024 * 1024 * 1024L; //1T + public static final long DEFAULT_TEMPLATE_SIZE = 1 * 1000 * 1000 * 1000L; //1G + + public PrimaryStorageDownloadAnswer primaryStorageDownload(PrimaryStorageDownloadCommand cmd); + + public CreateAnswer createVolume(CreateCommand cmd); + public AttachVolumeAnswer AttachVolume(AttachVolumeCommand cmd); + public Answer AttachIso(AttachIsoCommand cmd); + + public Answer DeleteStoragePool(DeleteStoragePoolCommand cmd); + public Answer ModifyStoragePool(ModifyStoragePoolCommand cmd); + public Answer CreateStoragePool(CreateStoragePoolCommand cmd); + + public Answer SecStorageSetup(SecStorageSetupCommand cmd); + public Answer ListTemplates(ListTemplateCommand cmd); + public Answer Destroy(DestroyCommand cmd); + public Answer Download(DownloadCommand cmd); + public Answer DownloadProcess(DownloadProgressCommand cmd); + public GetStorageStatsAnswer GetStorageStats(GetStorageStatsCommand cmd); + public Answer ManageSnapshot(ManageSnapshotCommand cmd); + public Answer BackupSnapshot(BackupSnapshotCommand cmd); + public Answer DeleteSnapshotBackup(DeleteSnapshotBackupCommand cmd); + public Answer CreateVolumeFromSnapshot(CreateVolumeFromSnapshotCommand cmd); + public Answer DeleteTemplate(DeleteTemplateCommand cmd); + public Answer SecStorageVMSetup(SecStorageVMSetupCommand cmd); + + public void preinstallTemplates(String url, long zoneId); + + StoragePoolInfo getLocalStorage(String hostGuid); + + public Answer CreatePrivateTemplateFromSnapshot(CreatePrivateTemplateFromSnapshotCommand cmd); + + public Answer ComputeChecksum(ComputeChecksumCommand cmd); + + public Answer CreatePrivateTemplateFromVolume(CreatePrivateTemplateFromVolumeCommand cmd); + + StoragePoolInfo getLocalStorage(String hostGuid, Long storageSize); +} diff --git a/agent-simulator/src/com/cloud/agent/manager/MockStorageManagerImpl.java b/agent-simulator/src/com/cloud/agent/manager/MockStorageManagerImpl.java new file mode 100644 index 00000000000..69dc8f99790 --- /dev/null +++ b/agent-simulator/src/com/cloud/agent/manager/MockStorageManagerImpl.java @@ -0,0 +1,658 @@ +/** + * Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + */ + +package com.cloud.agent.manager; + +import java.io.File; +import java.math.BigInteger; +import java.net.URI; +import java.net.URISyntaxException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import javax.ejb.Local; +import javax.naming.ConfigurationException; + +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.AttachIsoCommand; +import com.cloud.agent.api.AttachVolumeAnswer; +import com.cloud.agent.api.AttachVolumeCommand; +import com.cloud.agent.api.BackupSnapshotAnswer; +import com.cloud.agent.api.BackupSnapshotCommand; +import com.cloud.agent.api.ComputeChecksumCommand; +import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand; +import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand; +import com.cloud.agent.api.CreateStoragePoolCommand; +import com.cloud.agent.api.CreateVolumeFromSnapshotAnswer; +import com.cloud.agent.api.CreateVolumeFromSnapshotCommand; +import com.cloud.agent.api.DeleteSnapshotBackupCommand; +import com.cloud.agent.api.DeleteStoragePoolCommand; +import com.cloud.agent.api.GetStorageStatsAnswer; +import com.cloud.agent.api.GetStorageStatsCommand; +import com.cloud.agent.api.ManageSnapshotAnswer; +import com.cloud.agent.api.ManageSnapshotCommand; +import com.cloud.agent.api.ModifyStoragePoolAnswer; +import com.cloud.agent.api.ModifyStoragePoolCommand; +import com.cloud.agent.api.SecStorageSetupAnswer; +import com.cloud.agent.api.SecStorageSetupCommand; +import com.cloud.agent.api.SecStorageVMSetupCommand; +import com.cloud.agent.api.StoragePoolInfo; +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.storage.DeleteTemplateCommand; +import com.cloud.agent.api.storage.DestroyCommand; +import com.cloud.agent.api.storage.DownloadAnswer; +import com.cloud.agent.api.storage.DownloadCommand; +import com.cloud.agent.api.storage.DownloadProgressCommand; +import com.cloud.agent.api.storage.ListTemplateAnswer; +import com.cloud.agent.api.storage.ListTemplateCommand; +import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer; +import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; +import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.agent.api.to.VolumeTO; +import com.cloud.simulator.MockHost; +import com.cloud.simulator.MockSecStorageVO; +import com.cloud.simulator.MockStoragePoolVO; +import com.cloud.simulator.MockVMVO; +import com.cloud.simulator.MockVolumeVO; +import com.cloud.simulator.MockVolumeVO.MockVolumeType; +import com.cloud.simulator.dao.MockHostDao; +import com.cloud.simulator.dao.MockSecStorageDao; +import com.cloud.simulator.dao.MockStoragePoolDao; +import com.cloud.simulator.dao.MockVMDao; +import com.cloud.simulator.dao.MockVolumeDao; +import com.cloud.storage.Storage.ImageFormat; +import com.cloud.storage.Storage.StoragePoolType; +import com.cloud.storage.VMTemplateStorageResourceAssoc; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; +import com.cloud.storage.template.TemplateInfo; +import com.cloud.utils.component.Inject; +import com.cloud.vm.DiskProfile; + + +@Local(value = { MockStorageManager.class }) +public class MockStorageManagerImpl implements MockStorageManager { + private static final Logger s_logger = Logger.getLogger(MockStorageManagerImpl.class); + @Inject MockStoragePoolDao _mockStoragePoolDao = null; + @Inject MockSecStorageDao _mockSecStorageDao = null; + @Inject MockVolumeDao _mockVolumeDao = null; + @Inject MockVMDao _mockVMDao = null; + @Inject MockHostDao _mockHostDao = null; + + private MockVolumeVO findVolumeFromSecondary(String path, String ssUrl, MockVolumeType type) { + + String volumePath = path.replaceAll(ssUrl, ""); + + MockSecStorageVO secStorage = _mockSecStorageDao.findByUrl(ssUrl); + if (secStorage == null) { + return null; + } + + volumePath = secStorage.getMountPoint() + volumePath; + volumePath = volumePath.replaceAll("//", "/"); + + MockVolumeVO volume = _mockVolumeDao.findByStoragePathAndType(volumePath); + if (volume == null) { + return null; + } + + return volume; + } + @Override + public PrimaryStorageDownloadAnswer primaryStorageDownload(PrimaryStorageDownloadCommand cmd) { + MockVolumeVO template = findVolumeFromSecondary(cmd.getUrl(),cmd.getSecondaryStorageUrl(), MockVolumeType.TEMPLATE); + if (template == null) { + return new PrimaryStorageDownloadAnswer("Can't find primary storage"); + } + + MockStoragePoolVO primaryStorage = _mockStoragePoolDao.findByUuid(cmd.getPoolUuid()); + if (primaryStorage == null) { + return new PrimaryStorageDownloadAnswer("Can't find primary storage"); + } + + String volumeName = UUID.randomUUID().toString(); + MockVolumeVO newVolume = new MockVolumeVO(); + newVolume.setName(volumeName); + newVolume.setPath(primaryStorage.getMountPoint() + volumeName); + newVolume.setPoolId(primaryStorage.getId()); + newVolume.setSize(template.getSize()); + newVolume.setType(MockVolumeType.VOLUME); + _mockVolumeDao.persist(newVolume); + + + return new PrimaryStorageDownloadAnswer(newVolume.getPath(), newVolume.getSize()); + } + + @Override + public CreateAnswer createVolume(CreateCommand cmd) { + StorageFilerTO sf = cmd.getPool(); + DiskProfile dskch = cmd.getDiskCharacteristics(); + MockStoragePoolVO storagePool = _mockStoragePoolDao.findByUuid(sf.getUuid()); + if (storagePool == null) { + return new CreateAnswer(cmd, "Failed to find storage pool: " + sf.getUuid()); + } + + String volumeName = UUID.randomUUID().toString(); + MockVolumeVO volume = new MockVolumeVO(); + volume.setPoolId(storagePool.getId()); + volume.setName(volumeName); + volume.setPath(storagePool.getMountPoint() + volumeName); + volume.setSize(dskch.getSize()); + volume.setType(MockVolumeType.VOLUME); + volume = _mockVolumeDao.persist(volume); + + VolumeTO volumeTo = new VolumeTO(cmd.getVolumeId(), dskch.getType(), sf.getType(), sf.getUuid(), + volume.getName(), storagePool.getMountPoint(), volume.getPath(), volume.getSize(), null); + + return new CreateAnswer(cmd, volumeTo); + } + + @Override + public AttachVolumeAnswer AttachVolume(AttachVolumeCommand cmd) { + String poolid = cmd.getPoolUuid(); + String volumeName = cmd.getVolumeName(); + MockVolumeVO volume = _mockVolumeDao.findByStoragePathAndType(cmd.getVolumePath()); + if (volume == null) { + return new AttachVolumeAnswer(cmd, "Can't find volume:" + volumeName + "on pool:" + poolid); + } + + String vmName = cmd.getVmName(); + MockVMVO vm = _mockVMDao.findByVmName(vmName); + if (vm == null) { + return new AttachVolumeAnswer(cmd, "can't vm :" + vmName); + } + + return new AttachVolumeAnswer(cmd, cmd.getDeviceId()); + } + + @Override + public Answer AttachIso(AttachIsoCommand cmd) { + MockVolumeVO iso = findVolumeFromSecondary(cmd.getIsoPath(), cmd.getStoreUrl(), MockVolumeType.ISO); + if (iso == null) { + return new Answer(cmd, false, "Failed to find the iso: " + cmd.getIsoPath() + "on secondary storage " + cmd.getStoreUrl()); + } + + String vmName = cmd.getVmName(); + MockVMVO vm = _mockVMDao.findByVmName(vmName); + if (vm == null) { + return new Answer(cmd, false, "can't vm :" + vmName); + } + + return new Answer(cmd); + } + + @Override + public Answer DeleteStoragePool(DeleteStoragePoolCommand cmd) { + MockStoragePoolVO storage = _mockStoragePoolDao.findByUuid(cmd.getPool().getUuid()); + if (storage == null) { + return new Answer(cmd, false, "can't find storage pool:" + cmd.getPool().getUuid()); + } + _mockStoragePoolDao.remove(storage.getId()); + return new Answer(cmd); + } + + @Override + public ModifyStoragePoolAnswer ModifyStoragePool(ModifyStoragePoolCommand cmd) { + StorageFilerTO sf = cmd.getPool(); + MockStoragePoolVO storagePool = _mockStoragePoolDao.findByUuid(sf.getUuid()); + if (storagePool == null) { + storagePool = new MockStoragePoolVO(); + storagePool.setUuid(sf.getUuid()); + storagePool.setMountPoint("/mnt/" + sf.getUuid() + File.separator); + + Long size = DEFAULT_HOST_STORAGE_SIZE; + String path = sf.getPath(); + int index = path.lastIndexOf("/"); + if (index != -1) { + path = path.substring(index+1); + if (path != null) { + String values[] = path.split("="); + if (values.length > 1 && values[0].equalsIgnoreCase("size")) { + size = Long.parseLong(values[1]); + } + } + } + + storagePool.setCapacity(size); + + storagePool.setStorageType(sf.getType()); + storagePool = _mockStoragePoolDao.persist(storagePool); + } + + return new ModifyStoragePoolAnswer(cmd, storagePool.getCapacity(), 0, new HashMap()); + } + + @Override + public Answer CreateStoragePool(CreateStoragePoolCommand cmd) { + StorageFilerTO sf = cmd.getPool(); + MockStoragePoolVO storagePool = _mockStoragePoolDao.findByUuid(sf.getUuid()); + if (storagePool == null) { + storagePool = new MockStoragePoolVO(); + storagePool.setUuid(sf.getUuid()); + storagePool.setMountPoint("/mnt/" + sf.getUuid() + File.separator); + + Long size = DEFAULT_HOST_STORAGE_SIZE; + String path = sf.getPath(); + int index = path.lastIndexOf("/"); + if (index != -1) { + path = path.substring(index+1); + if (path != null) { + String values[] = path.split("="); + if (values.length > 1 && values[0].equalsIgnoreCase("size")) { + size = Long.parseLong(values[1]); + } + } + } + storagePool.setCapacity(size); + + storagePool.setStorageType(sf.getType()); + storagePool = _mockStoragePoolDao.persist(storagePool); + } + + return new ModifyStoragePoolAnswer(cmd, storagePool.getCapacity(), 0, new HashMap()); + } + + @Override + public Answer SecStorageSetup(SecStorageSetupCommand cmd) { + MockSecStorageVO storage = _mockSecStorageDao.findByUrl(cmd.getSecUrl()); + if (storage == null) { + return new Answer(cmd, false, "can't find the storage"); + } + return new SecStorageSetupAnswer(storage.getMountPoint()); + } + + @Override + public Answer ListTemplates(ListTemplateCommand cmd) { + MockSecStorageVO storage = _mockSecStorageDao.findByUrl(cmd.getSecUrl()); + if (storage == null) { + return new Answer(cmd, false, "Failed to get secondary storage"); + } + + List templates = _mockVolumeDao.findByStorageIdAndType(storage.getId(), MockVolumeType.TEMPLATE); + Map templateInfos = new HashMap(); + for (MockVolumeVO template : templates) { + templateInfos.put(template.getName(), new TemplateInfo(template.getName(), template.getPath().replaceAll(storage.getMountPoint(), ""), template.getSize(), template.getSize(), true, false)); + } + + return new ListTemplateAnswer(cmd.getSecUrl(), templateInfos); + + } + + @Override + public Answer Destroy(DestroyCommand cmd) { + + MockVolumeVO volume = _mockVolumeDao.findByStoragePathAndType(cmd.getVolume().getPath()); + if (volume != null) { + _mockVolumeDao.remove(volume.getId()); + } + return new Answer(cmd); + } + + @Override + public DownloadAnswer Download(DownloadCommand cmd) { + MockSecStorageVO ssvo = _mockSecStorageDao.findByUrl(cmd.getSecUrl()); + if (ssvo == null) { + return new DownloadAnswer("can't find secondary storage", VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR); + } + + MockVolumeVO volume = new MockVolumeVO(); + volume.setPoolId(ssvo.getId()); + volume.setName(cmd.getName()); + volume.setPath(ssvo.getMountPoint() + cmd.getName()); + volume.setSize(0); + volume.setType(MockVolumeType.TEMPLATE); + volume.setStatus(Status.DOWNLOAD_IN_PROGRESS); + volume = _mockVolumeDao.persist(volume); + + return new DownloadAnswer(String.valueOf(volume.getId()), 0, "Downloading", Status.DOWNLOAD_IN_PROGRESS, cmd.getName(), cmd.getName(), volume.getSize(), volume.getSize()); + } + + @Override + public DownloadAnswer DownloadProcess(DownloadProgressCommand cmd) { + String volumeId = cmd.getJobId(); + MockVolumeVO volume = _mockVolumeDao.findById(Long.parseLong(volumeId)); + if (volume == null) { + return new DownloadAnswer("Can't find the downloading volume", Status.ABANDONED); + } + + long size = Math.min(volume.getSize() + DEFAULT_TEMPLATE_SIZE/5, DEFAULT_TEMPLATE_SIZE); + volume.setSize(size); + + double volumeSize = volume.getSize(); + double pct = volumeSize/DEFAULT_TEMPLATE_SIZE; + if (pct >= 1.0) { + volume.setStatus(Status.DOWNLOADED); + _mockVolumeDao.update(volume.getId(), volume); + return new DownloadAnswer(cmd.getJobId(), 100, cmd, com.cloud.storage.VMTemplateStorageResourceAssoc.Status.DOWNLOADED, volume.getPath(), volume.getName()); + } else { + _mockVolumeDao.update(volume.getId(), volume); + return new DownloadAnswer(cmd.getJobId(), (int)(pct*100.0) , cmd, com.cloud.storage.VMTemplateStorageResourceAssoc.Status.DOWNLOAD_IN_PROGRESS, volume.getPath(), volume.getName()); + } + } + + @Override + public GetStorageStatsAnswer GetStorageStats(GetStorageStatsCommand cmd) { + String uuid = cmd.getStorageId(); + if (uuid == null) { + String secUrl = cmd.getSecUrl(); + MockSecStorageVO secondary = _mockSecStorageDao.findByUrl(secUrl); + if (secondary == null) { + return new GetStorageStatsAnswer(cmd, "Can't find the secondary storage:" + secUrl); + } + Long totalUsed = _mockVolumeDao.findTotalStorageId(secondary.getId()); + return new GetStorageStatsAnswer(cmd, secondary.getCapacity(), totalUsed); + } else { + MockStoragePoolVO pool = _mockStoragePoolDao.findByUuid(uuid); + if (pool == null) { + return new GetStorageStatsAnswer(cmd, "Can't find the pool"); + } + Long totalUsed = _mockVolumeDao.findTotalStorageId(pool.getId()); + if (totalUsed == null) { + totalUsed = 0L; + } + return new GetStorageStatsAnswer(cmd, pool.getCapacity(), totalUsed); + } + } + + @Override + public ManageSnapshotAnswer ManageSnapshot(ManageSnapshotCommand cmd) { + String volPath = cmd.getVolumePath(); + + MockVolumeVO volume = _mockVolumeDao.findByStoragePathAndType(volPath); + if (volume == null) { + return new ManageSnapshotAnswer(cmd, false, "Can't find the volume"); + } + MockStoragePoolVO storagePool = _mockStoragePoolDao.findById(volume.getPoolId()); + if (storagePool == null) { + return new ManageSnapshotAnswer(cmd, false, "Can't find the storage pooll"); + } + + String mountPoint = storagePool.getMountPoint(); + MockVolumeVO snapshot = new MockVolumeVO(); + + snapshot.setName(cmd.getSnapshotName()); + snapshot.setPath(mountPoint + cmd.getSnapshotName()); + snapshot.setSize(volume.getSize()); + snapshot.setPoolId(storagePool.getId()); + snapshot.setType(MockVolumeType.SNAPSHOT); + snapshot.setStatus(Status.DOWNLOADED); + + snapshot = _mockVolumeDao.persist(snapshot); + + return new ManageSnapshotAnswer(cmd, snapshot.getId(), snapshot.getPath(), true, ""); + } + + @Override + public BackupSnapshotAnswer BackupSnapshot(BackupSnapshotCommand cmd) { + String snapshotPath = cmd.getSnapshotUuid(); + MockVolumeVO snapshot = _mockVolumeDao.findByStoragePathAndType(snapshotPath); + if (snapshot == null) { + return new BackupSnapshotAnswer(cmd, false, "can't find snapshot" + snapshotPath, null, true); + } + + String secStorageUrl = cmd.getSecondaryStoragePoolURL(); + MockSecStorageVO secStorage = _mockSecStorageDao.findByUrl(secStorageUrl); + if (secStorage == null) { + return new BackupSnapshotAnswer(cmd, false, "can't find sec storage" + snapshotPath, null, true); + } + MockVolumeVO newsnapshot = new MockVolumeVO(); + String name = UUID.randomUUID().toString(); + newsnapshot.setName(name); + newsnapshot.setPath(secStorage.getMountPoint() + name); + newsnapshot.setPoolId(secStorage.getId()); + newsnapshot.setSize(snapshot.getSize()); + newsnapshot.setStatus(Status.DOWNLOADED); + newsnapshot.setType(MockVolumeType.SNAPSHOT); + newsnapshot = _mockVolumeDao.persist(newsnapshot); + + return new BackupSnapshotAnswer(cmd, true, null, newsnapshot.getName(), true); + } + + @Override + public Answer DeleteSnapshotBackup(DeleteSnapshotBackupCommand cmd) { + + MockVolumeVO backSnapshot = _mockVolumeDao.findByName(cmd.getSnapshotUuid()); + if (backSnapshot == null) { + return new Answer(cmd, false, "can't find the backupsnapshot: " + cmd.getSnapshotUuid()); + } + + _mockVolumeDao.remove(backSnapshot.getId()); + + return new Answer(cmd); + } + + @Override + public CreateVolumeFromSnapshotAnswer CreateVolumeFromSnapshot(CreateVolumeFromSnapshotCommand cmd) { + MockVolumeVO backSnapshot = _mockVolumeDao.findByName(cmd.getSnapshotUuid()); + if (backSnapshot == null) { + return new CreateVolumeFromSnapshotAnswer(cmd, false, "can't find the backupsnapshot: " + cmd.getSnapshotUuid(), null); + } + + MockStoragePoolVO primary = _mockStoragePoolDao.findByUuid(cmd.getPrimaryStoragePoolNameLabel()); + if (primary == null) { + return new CreateVolumeFromSnapshotAnswer(cmd, false, "can't find the primary storage: " + cmd.getPrimaryStoragePoolNameLabel(), null); + } + + String uuid = UUID.randomUUID().toString(); + MockVolumeVO volume = new MockVolumeVO(); + + volume.setName(uuid); + volume.setPath(primary.getMountPoint() + uuid); + volume.setPoolId(primary.getId()); + volume.setSize(backSnapshot.getSize()); + volume.setStatus(Status.DOWNLOADED); + volume.setType(MockVolumeType.VOLUME); + _mockVolumeDao.persist(volume); + + return new CreateVolumeFromSnapshotAnswer(cmd, true, null, volume.getPath()); + } + + @Override + public Answer DeleteTemplate(DeleteTemplateCommand cmd) { + MockVolumeVO template = _mockVolumeDao.findByStoragePathAndType(cmd.getTemplatePath()); + if (template == null) { + return new Answer(cmd, false, "can't find template:" + cmd.getTemplatePath()); + } + + _mockVolumeDao.remove(template.getId()); + + return new Answer(cmd); + } + + @Override + public Answer SecStorageVMSetup(SecStorageVMSetupCommand cmd) { + return new Answer(cmd); + } + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + // TODO Auto-generated method stub + return true; + } + + @Override + public boolean start() { + // TODO Auto-generated method stub + return true; + } + + @Override + public boolean stop() { + // TODO Auto-generated method stub + return true; + } + + @Override + public String getName() { + return this.getClass().getSimpleName(); + } + + @Override + public void preinstallTemplates(String url, long zoneId) { + MockSecStorageVO storage = _mockSecStorageDao.findByUrl(url); + if (storage == null) { + storage = new MockSecStorageVO(); + URI uri; + try { + uri = new URI(url); + } catch (URISyntaxException e) { + return; + } + + String nfsHost = uri.getHost(); + String nfsPath = uri.getPath(); + String path = nfsHost + ":" + nfsPath; + String dir = "/mnt/" + UUID.nameUUIDFromBytes(path.getBytes()).toString() + File.separator; + + storage.setUrl(url); + storage.setCapacity(DEFAULT_HOST_STORAGE_SIZE); + + storage.setMountPoint(dir); + + storage = _mockSecStorageDao.persist(storage); + + //preinstall default templates into secondary storage + long defaultTemplateSize = 2 * 1024 * 1024 * 1024L; + MockVolumeVO template = new MockVolumeVO(); + template.setName("simulator-domR"); + template.setPath(storage.getMountPoint() + "template/tmpl/1/9/" + UUID.randomUUID().toString()); + template.setPoolId(storage.getId()); + template.setSize(defaultTemplateSize); + template.setType(MockVolumeType.TEMPLATE); + template.setStatus(Status.DOWNLOADED); + _mockVolumeDao.persist(template); + + template = new MockVolumeVO(); + template.setName("simulator-Centos"); + template.setPath(storage.getMountPoint() + "template/tmpl/1/10/" + UUID.randomUUID().toString()); + template.setPoolId(storage.getId()); + template.setSize(defaultTemplateSize); + template.setType(MockVolumeType.TEMPLATE); + _mockVolumeDao.persist(template); + } + + } + + @Override + public StoragePoolInfo getLocalStorage(String hostGuid) { + MockHost host = _mockHostDao.findByGuid(hostGuid); + + MockStoragePoolVO storagePool = _mockStoragePoolDao.findByHost(hostGuid); + if (storagePool == null) { + String uuid = UUID.randomUUID().toString(); + storagePool = new MockStoragePoolVO(); + storagePool.setUuid(uuid); + storagePool.setMountPoint("/mnt/" + uuid + File.separator); + storagePool.setCapacity(DEFAULT_HOST_STORAGE_SIZE); + storagePool.setHostGuid(hostGuid); + storagePool.setStorageType(StoragePoolType.Filesystem); + storagePool = _mockStoragePoolDao.persist(storagePool); + } + + + return new StoragePoolInfo(storagePool.getUuid(), host.getPrivateIpAddress(), storagePool.getMountPoint(), storagePool.getMountPoint(), storagePool.getPoolType(), storagePool.getCapacity(), 0 ); + } + + @Override + public StoragePoolInfo getLocalStorage(String hostGuid, Long storageSize) { + MockHost host = _mockHostDao.findByGuid(hostGuid); + if (storageSize == null) { + storageSize = DEFAULT_HOST_STORAGE_SIZE; + } + MockStoragePoolVO storagePool = _mockStoragePoolDao.findByHost(hostGuid); + if (storagePool == null) { + String uuid = UUID.randomUUID().toString(); + storagePool = new MockStoragePoolVO(); + storagePool.setUuid(uuid); + storagePool.setMountPoint("/mnt/" + uuid + File.separator); + storagePool.setCapacity(storageSize); + storagePool.setHostGuid(hostGuid); + storagePool.setStorageType(StoragePoolType.Filesystem); + storagePool = _mockStoragePoolDao.persist(storagePool); + } + + + return new StoragePoolInfo(storagePool.getUuid(), host.getPrivateIpAddress(), storagePool.getMountPoint(), storagePool.getMountPoint(), storagePool.getPoolType(), storagePool.getCapacity(), 0 ); + } + + @Override + public CreatePrivateTemplateAnswer CreatePrivateTemplateFromSnapshot(CreatePrivateTemplateFromSnapshotCommand cmd) { + String snapshotUUId = cmd.getSnapshotUuid(); + MockVolumeVO snapshot = _mockVolumeDao.findByName(snapshotUUId); + if (snapshot == null) { + snapshotUUId = cmd.getSnapshotName(); + snapshot = _mockVolumeDao.findByName(snapshotUUId); + if (snapshot == null) { + return new CreatePrivateTemplateAnswer(cmd, false, "can't find snapshot:" + snapshotUUId); + } + } + + MockSecStorageVO sec = _mockSecStorageDao.findByUrl(cmd.getSecondaryStoragePoolURL()); + if (sec == null) { + return new CreatePrivateTemplateAnswer(cmd, false, "can't find secondary storage"); + } + + MockVolumeVO template = new MockVolumeVO(); + String uuid = UUID.randomUUID().toString(); + template.setName(uuid); + template.setPath(sec.getMountPoint() + uuid); + template.setPoolId(sec.getId()); + template.setSize(snapshot.getSize()); + template.setStatus(Status.DOWNLOADED); + template.setType(MockVolumeType.TEMPLATE); + template = _mockVolumeDao.persist(template); + + return new CreatePrivateTemplateAnswer(cmd, true, "", template.getName(), template.getSize(), template.getSize(), template.getName(), ImageFormat.QCOW2); + } + + @Override + public Answer ComputeChecksum(ComputeChecksumCommand cmd) { + MockVolumeVO volume = _mockVolumeDao.findByName(cmd.getTemplatePath()); + if (volume == null) { + return new Answer(cmd, false, "cant' find volume:" + cmd.getTemplatePath()); + } + String md5 = null; + try { + MessageDigest md = MessageDigest.getInstance("md5"); + md5 = String.format("%032x", new BigInteger(1, md.digest(cmd.getTemplatePath().getBytes()))); + } catch (NoSuchAlgorithmException e) { + s_logger.debug("failed to gernerate md5:" + e.toString()); + } + + return new Answer(cmd, true, md5); + } + @Override + public CreatePrivateTemplateAnswer CreatePrivateTemplateFromVolume(CreatePrivateTemplateFromVolumeCommand cmd) { + MockVolumeVO volume = _mockVolumeDao.findByStoragePathAndType(cmd.getVolumePath()); + if (volume == null) { + return new CreatePrivateTemplateAnswer(cmd, false, "cant' find volume" + cmd.getVolumePath()); + } + + MockSecStorageVO sec = _mockSecStorageDao.findByUrl(cmd.getSecondaryStoragePoolURL()); + if (sec == null) { + return new CreatePrivateTemplateAnswer(cmd, false, "can't find secondary storage"); + } + + MockVolumeVO template = new MockVolumeVO(); + String uuid = UUID.randomUUID().toString(); + template.setName(uuid); + template.setPath(sec.getMountPoint() + uuid); + template.setPoolId(sec.getId()); + template.setSize(volume.getSize()); + template.setStatus(Status.DOWNLOADED); + template.setType(MockVolumeType.TEMPLATE); + template = _mockVolumeDao.persist(template); + + return new CreatePrivateTemplateAnswer(cmd, true, "", template.getName(), template.getSize(), template.getSize(), template.getName(), ImageFormat.QCOW2); + } + +} + diff --git a/agent-simulator/src/com/cloud/agent/manager/MockVmManager.java b/agent-simulator/src/com/cloud/agent/manager/MockVmManager.java new file mode 100644 index 00000000000..a3c6a3a8667 --- /dev/null +++ b/agent-simulator/src/com/cloud/agent/manager/MockVmManager.java @@ -0,0 +1,86 @@ +/** + * Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + */ + +package com.cloud.agent.manager; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CheckVirtualMachineCommand; +import com.cloud.agent.api.CleanupNetworkRulesCmd; +import com.cloud.agent.api.GetVmStatsCommand; +import com.cloud.agent.api.GetVncPortCommand; +import com.cloud.agent.api.MigrateAnswer; +import com.cloud.agent.api.MigrateCommand; +import com.cloud.agent.api.NetworkUsageAnswer; +import com.cloud.agent.api.NetworkUsageCommand; +import com.cloud.agent.api.RebootCommand; +import com.cloud.agent.api.SecurityIngressRulesCmd; +import com.cloud.agent.api.StartCommand; +import com.cloud.agent.api.StopCommand; +import com.cloud.agent.api.VmStatsEntry; +import com.cloud.agent.api.check.CheckSshAnswer; +import com.cloud.agent.api.check.CheckSshCommand; +import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; +import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; +import com.cloud.agent.api.routing.DhcpEntryCommand; +import com.cloud.agent.api.routing.IpAssocCommand; +import com.cloud.agent.api.routing.LoadBalancerConfigCommand; +import com.cloud.agent.api.routing.SavePasswordCommand; +import com.cloud.agent.api.routing.SetPortForwardingRulesAnswer; +import com.cloud.agent.api.routing.SetPortForwardingRulesCommand; +import com.cloud.agent.api.routing.SetStaticNatRulesAnswer; +import com.cloud.agent.api.routing.SetStaticNatRulesCommand; +import com.cloud.agent.api.routing.VmDataCommand; +import com.cloud.agent.api.storage.DestroyCommand; +import com.cloud.agent.api.to.NicTO; +import com.cloud.simulator.MockVm; +import com.cloud.utils.Pair; +import com.cloud.utils.component.Manager; +import com.cloud.vm.VirtualMachine.State; + +public interface MockVmManager extends Manager { + public Answer stopVM(StopCommand cmd); + public Answer rebootVM(RebootCommand cmd); + + public boolean migrate(String vmName, String params); + + public Answer checkVmState(CheckVirtualMachineCommand cmd, String hostGuid); + public Map getVmStates(String hostGuid); + public Answer getVncPort(GetVncPortCommand cmd); + + Answer startVM(StartCommand cmd, String hostGuid); + + Answer getVmStats(GetVmStatsCommand cmd); + public CheckSshAnswer checkSshCommand(CheckSshCommand cmd); + + Answer SetStaticNatRules(SetStaticNatRulesCommand cmd); + + Answer SetPortForwardingRules(SetPortForwardingRulesCommand cmd); + + Answer getNetworkUsage(NetworkUsageCommand cmd); + + Answer Migrate(MigrateCommand cmd, String hostGuid); + + Answer IpAssoc(IpAssocCommand cmd); + + Answer LoadBalancerConfig(LoadBalancerConfigCommand cmd); + + Answer AddDhcpEntry(DhcpEntryCommand cmd); + + Answer setVmData(VmDataCommand cmd); + Answer CleanupNetworkRules(CleanupNetworkRulesCmd cmd, String hostGuid); + + Answer CheckConsoleProxyLoad(CheckConsoleProxyLoadCommand cmd); + Answer WatchConsoleProxyLoad(WatchConsoleProxyLoadCommand cmd); + + Answer AddSecurityIngressRules(SecurityIngressRulesCmd cmd); + Answer SavePassword(SavePasswordCommand cmd); + HashMap> syncNetworkGroups(String hostGuid); + +} diff --git a/agent-simulator/src/com/cloud/agent/manager/MockVmManagerImpl.java b/agent-simulator/src/com/cloud/agent/manager/MockVmManagerImpl.java new file mode 100644 index 00000000000..d8907389a5d --- /dev/null +++ b/agent-simulator/src/com/cloud/agent/manager/MockVmManagerImpl.java @@ -0,0 +1,398 @@ +/** + * Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + */ + +package com.cloud.agent.manager; + + +import java.util.HashMap; + +import java.util.List; +import java.util.Map; + +import javax.ejb.Local; +import javax.naming.ConfigurationException; + +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CheckVirtualMachineAnswer; +import com.cloud.agent.api.CheckVirtualMachineCommand; +import com.cloud.agent.api.CleanupNetworkRulesCmd; +import com.cloud.agent.api.GetVmStatsAnswer; +import com.cloud.agent.api.GetVmStatsCommand; +import com.cloud.agent.api.GetVncPortAnswer; +import com.cloud.agent.api.GetVncPortCommand; +import com.cloud.agent.api.MigrateAnswer; +import com.cloud.agent.api.MigrateCommand; +import com.cloud.agent.api.NetworkUsageAnswer; +import com.cloud.agent.api.NetworkUsageCommand; +import com.cloud.agent.api.RebootCommand; +import com.cloud.agent.api.SecurityIngressRuleAnswer; +import com.cloud.agent.api.SecurityIngressRulesCmd; +import com.cloud.agent.api.StartAnswer; +import com.cloud.agent.api.StartCommand; +import com.cloud.agent.api.StopAnswer; +import com.cloud.agent.api.StopCommand; +import com.cloud.agent.api.VmStatsEntry; +import com.cloud.agent.api.check.CheckSshAnswer; +import com.cloud.agent.api.check.CheckSshCommand; +import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; +import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; +import com.cloud.agent.api.routing.DhcpEntryCommand; +import com.cloud.agent.api.routing.IpAssocCommand; +import com.cloud.agent.api.routing.LoadBalancerConfigCommand; +import com.cloud.agent.api.routing.SavePasswordCommand; +import com.cloud.agent.api.routing.SetPortForwardingRulesAnswer; +import com.cloud.agent.api.routing.SetPortForwardingRulesCommand; +import com.cloud.agent.api.routing.SetStaticNatRulesAnswer; +import com.cloud.agent.api.routing.SetStaticNatRulesCommand; +import com.cloud.agent.api.routing.VmDataCommand; +import com.cloud.agent.api.storage.DestroyCommand; +import com.cloud.agent.api.to.NicTO; +import com.cloud.agent.api.to.VirtualMachineTO; + +import com.cloud.network.Networks.TrafficType; + +import com.cloud.simulator.MockHost; +import com.cloud.simulator.MockHostVO; +import com.cloud.simulator.MockSecurityRulesVO; +import com.cloud.simulator.MockVMVO; +import com.cloud.simulator.MockVm; +import com.cloud.simulator.dao.MockHostDao; +import com.cloud.simulator.dao.MockSecurityRulesDao; +import com.cloud.simulator.dao.MockVMDao; +import com.cloud.utils.Pair; +import com.cloud.utils.component.Inject; + +import com.cloud.vm.VirtualMachine.State; + +@Local(value = { MockVmManager.class }) +public class MockVmManagerImpl implements MockVmManager { + private static final Logger s_logger = Logger.getLogger(MockVmManagerImpl.class); + + @Inject MockVMDao _mockVmDao = null; + @Inject MockAgentManager _mockAgentMgr = null; + @Inject MockHostDao _mockHostDao = null; + @Inject MockSecurityRulesDao _mockSecurityDao = null; + + public MockVmManagerImpl() { + } + + @Override + public boolean configure(String name, Map params) + throws ConfigurationException { + + return true; + } + + public String startVM(String vmName, NicTO[] nics, + int cpuHz, long ramSize, + String bootArgs, String hostGuid) { + + MockHost host = _mockHostDao.findByGuid(hostGuid); + if (host == null) { + return "can't find host"; + } + + MockVm vm = _mockVmDao.findByVmName(vmName); + if(vm == null) { + int vncPort = 0; + if(vncPort < 0) + return "Unable to allocate VNC port"; + vm = new MockVMVO(); + vm.setCpu(cpuHz); + vm.setMemory(ramSize); + vm.setState(State.Running); + vm.setName(vmName); + vm.setVncPort(vncPort); + vm.setHostId(host.getId()); + vm = _mockVmDao.persist((MockVMVO)vm); + } else { + if(vm.getState() == State.Stopped) { + vm.setState(State.Running); + _mockVmDao.update(vm.getId(), (MockVMVO)vm); + } + } + + if (vm.getState() == State.Running && vmName.startsWith("s-")) { + String prvIp = null; + String prvMac = null; + String prvNetMask = null; + + for (NicTO nic : nics) { + if (nic.getType() == TrafficType.Management) { + prvIp = nic.getIp(); + prvMac = nic.getMac(); + prvNetMask = nic.getNetmask(); + } + } + long dcId = 0; + long podId = 0; + String name = null; + String vmType = null; + String url = null; + String[] args = bootArgs.trim().split(" "); + for (String arg : args) { + String[] params = arg.split("="); + if (params.length < 1) { + continue; + } + + if (params[0].equalsIgnoreCase("zone")) { + dcId = Long.parseLong(params[1]); + } else if (params[0].equalsIgnoreCase("name")) { + name = params[1]; + } else if (params[0].equalsIgnoreCase("type")) { + vmType = params[1]; + } else if (params[0].equalsIgnoreCase("url")) { + url = params[1]; + } else if (params[0].equalsIgnoreCase("pod")) { + podId = Long.parseLong(params[1]); + } + } + + _mockAgentMgr.handleSystemVMStart(vm.getId(), prvIp, prvMac, prvNetMask, dcId, podId, name, vmType, url); + } + + return null; + } + + public boolean rebootVM(String vmName) { + MockVm vm = _mockVmDao.findByVmName(vmName); + if(vm != null) { + vm.setState(State.Running); + _mockVmDao.update(vm.getId(), (MockVMVO)vm); + } + return true; + } + + @Override + public boolean migrate(String vmName, String params) { + MockVm vm = _mockVmDao.findByVmName(vmName); + if(vm != null) { + vm.setState(State.Stopped); + _mockVmDao.remove(vm.getId()); + return true; + } + + return false; + } + + @Override + public Map getVmStates(String hostGuid) { + Map states = new HashMap(); + List vms = _mockVmDao.findByHostGuid(hostGuid); + if (vms.isEmpty()) { + return states; + } + + for(MockVm vm : vms) { + states.put(vm.getName(), vm.getState()); + } + + return states; + } + + @Override + public boolean start() { + return true; + } + + @Override + public boolean stop() { + return true; + } + + @Override + public String getName() { + return this.getClass().getSimpleName(); + } + + @Override + public Answer getVmStats(GetVmStatsCommand cmd) { + HashMap vmStatsNameMap = new HashMap(); + List vmNames = cmd.getVmNames(); + for (String vmName : vmNames) { + VmStatsEntry entry = new VmStatsEntry(0, 0, 0, 0, "vm"); + entry.setNetworkReadKBs(32768); // default values 256 KBps + entry.setNetworkWriteKBs(16384); + entry.setCPUUtilization(10); + entry.setNumCPUs(1); + vmStatsNameMap.put(vmName, entry); + } + return new GetVmStatsAnswer(cmd, vmStatsNameMap); + } + + @Override + public CheckVirtualMachineAnswer checkVmState(CheckVirtualMachineCommand cmd, String hostGuid) { + MockVMVO vm = _mockVmDao.findByVmNameAndHost(cmd.getVmName(), hostGuid); + if (vm == null) { + return new CheckVirtualMachineAnswer(cmd, "can't find vm:" + cmd.getVmName()); + } + + return new CheckVirtualMachineAnswer(cmd, vm.getState(), vm.getVncPort()); + } + + @Override + public Answer startVM(StartCommand cmd, String hostGuid) { + VirtualMachineTO vm = cmd.getVirtualMachine(); + String result = startVM(vm.getName(), vm.getNics(), vm.getCpus()* vm.getSpeed(), vm.getMaxRam(), vm.getBootArgs(), hostGuid); + if (result != null) { + return new StartAnswer(cmd, result); + } else { + return new StartAnswer(cmd); + } + } + + @Override + public CheckSshAnswer checkSshCommand(CheckSshCommand cmd) { + return new CheckSshAnswer(cmd); + } + + @Override + public Answer SetStaticNatRules(SetStaticNatRulesCommand cmd) { + return new Answer(cmd); + } + + @Override + public Answer SetPortForwardingRules(SetPortForwardingRulesCommand cmd) { + return new Answer(cmd); + } + + @Override + public NetworkUsageAnswer getNetworkUsage(NetworkUsageCommand cmd) { + return new NetworkUsageAnswer(cmd, null, 100L, 100L); + } + + @Override + public MigrateAnswer Migrate(MigrateCommand cmd, String hostGuid) { + String vmName = cmd.getVmName(); + String destGuid = cmd.getHostGuid(); + MockVMVO vm = _mockVmDao.findByVmNameAndHost(vmName, hostGuid); + if (vm == null) { + return new MigrateAnswer(cmd, false, "can;t find vm:" + vmName + " on host:" + hostGuid, null); + } + + MockHost destHost = _mockHostDao.findByGuid(destGuid); + if (destHost == null) { + return new MigrateAnswer(cmd, false, "can;t find host:" + hostGuid, null); + } + vm.setHostId(destHost.getId()); + _mockVmDao.update(vm.getId(), vm); + return new MigrateAnswer(cmd, true,null, 0); + } + + @Override + public Answer IpAssoc(IpAssocCommand cmd) { + return new Answer(cmd); + } + + @Override + public Answer LoadBalancerConfig(LoadBalancerConfigCommand cmd) { + return new Answer(cmd); + } + + @Override + public Answer AddDhcpEntry(DhcpEntryCommand cmd) { + return new Answer(cmd); + } + + @Override + public Answer setVmData(VmDataCommand cmd) { + return new Answer(cmd); + } + + @Override + public Answer CleanupNetworkRules(CleanupNetworkRulesCmd cmd, String hostGuid) { + List rules = _mockSecurityDao.findByHost(hostGuid); + for (MockSecurityRulesVO rule : rules) { + MockVMVO vm = _mockVmDao.findByVmNameAndHost(rule.getVmName(), hostGuid); + if (vm == null) { + _mockSecurityDao.remove(rule.getId()); + } + } + return new Answer(cmd); + } + + @Override + public Answer stopVM(StopCommand cmd) { + String vmName = cmd.getVmName(); + MockVm vm = _mockVmDao.findByVmName(vmName); + if(vm != null) { + vm.setState(State.Stopped); + _mockVmDao.update(vm.getId(), (MockVMVO)vm); + } + + if (vmName.startsWith("s-")) { + _mockAgentMgr.handleSystemVMStop(vm.getId()); + } + + return new StopAnswer(cmd, null, new Integer(0), new Long(100), new Long(200)); + } + + @Override + public Answer rebootVM(RebootCommand cmd) { + return new Answer(cmd); + } + + @Override + public Answer getVncPort(GetVncPortCommand cmd) { + return new GetVncPortAnswer(cmd, 0); + } + + @Override + public Answer CheckConsoleProxyLoad(CheckConsoleProxyLoadCommand cmd) { + return Answer.createUnsupportedCommandAnswer(cmd); + } + + @Override + public Answer WatchConsoleProxyLoad(WatchConsoleProxyLoadCommand cmd) { + return Answer.createUnsupportedCommandAnswer(cmd); + } + + @Override + public SecurityIngressRuleAnswer AddSecurityIngressRules(SecurityIngressRulesCmd cmd) { + MockVMVO vm = _mockVmDao.findByVmName(cmd.getVmName()); + if (vm == null) { + return new SecurityIngressRuleAnswer(cmd, false, "cant' find the vm: " + cmd.getVmName()); + } + + MockSecurityRulesVO rules = _mockSecurityDao.findByVmId(cmd.getVmId()); + if (rules == null) { + rules = new MockSecurityRulesVO(); + rules.setRuleSet(cmd.stringifyRules()); + rules.setSeqNum(cmd.getSeqNum()); + rules.setSignature(cmd.getSignature()); + rules.setVmId(vm.getId()); + rules.setHostId(vm.getHostId()); + + _mockSecurityDao.persist(rules); + } else { + rules.setSeqNum(cmd.getSeqNum()); + rules.setSignature(cmd.getSignature()); + rules.setRuleSet(cmd.stringifyRules()); + rules.setVmId(cmd.getVmId()); + rules.setHostId(vm.getHostId()); + _mockSecurityDao.update(rules.getId(), rules); + } + + return new SecurityIngressRuleAnswer(cmd); + } + + @Override + public Answer SavePassword(SavePasswordCommand cmd) { + return new Answer(cmd); + } + + @Override + public HashMap> syncNetworkGroups(String hostGuid) { + HashMap> maps = new HashMap>(); + List rules = _mockSecurityDao.findByHost(hostGuid); + for (MockSecurityRulesVO rule : rules) { + maps.put(rule.getVmName(), new Pair(rule.getVmId(), rule.getSeqNum())); + } + return maps; + } + +} diff --git a/agent-simulator/src/com/cloud/agent/manager/SimulatorManager.java b/agent-simulator/src/com/cloud/agent/manager/SimulatorManager.java new file mode 100644 index 00000000000..537ee9775d4 --- /dev/null +++ b/agent-simulator/src/com/cloud/agent/manager/SimulatorManager.java @@ -0,0 +1,60 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + + */ + +package com.cloud.agent.manager; + +import java.util.HashMap; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.StoragePoolInfo; +import com.cloud.utils.Pair; +import com.cloud.utils.component.Manager; + +public interface SimulatorManager extends Manager { + public static final String Name = "simulator manager"; + + public enum AgentType { + Computing(0), // not used anymore + Routing(1), + Storage(2); + + int value; + + AgentType(int value) { + this.value = value; + } + + public int value() { + return value; + } + } + + MockVmManager getVmMgr(); + + MockStorageManager getStorageMgr(); + + MockAgentManager getAgentMgr(); + + Answer simulate(Command cmd, String hostGuid); + StoragePoolInfo getLocalStorage(String hostGuid); + + boolean configureSimulator(Long zoneId, Long podId, Long clusterId, Long hostId, String command, String values); + public HashMap> syncNetworkGroups(String hostGuid); +} \ No newline at end of file diff --git a/agent-simulator/src/com/cloud/agent/manager/SimulatorManagerImpl.java b/agent-simulator/src/com/cloud/agent/manager/SimulatorManagerImpl.java new file mode 100644 index 00000000000..43bcefe2696 --- /dev/null +++ b/agent-simulator/src/com/cloud/agent/manager/SimulatorManagerImpl.java @@ -0,0 +1,275 @@ +package com.cloud.agent.manager; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import javax.ejb.Local; +import javax.naming.ConfigurationException; + +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.AttachIsoCommand; +import com.cloud.agent.api.AttachVolumeCommand; +import com.cloud.agent.api.BackupSnapshotCommand; +import com.cloud.agent.api.CheckHealthCommand; +import com.cloud.agent.api.CleanupNetworkRulesCmd; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.ComputeChecksumCommand; +import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand; +import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand; +import com.cloud.agent.api.CreateStoragePoolCommand; +import com.cloud.agent.api.CreateVolumeFromSnapshotCommand; +import com.cloud.agent.api.DeleteSnapshotBackupCommand; +import com.cloud.agent.api.DeleteStoragePoolCommand; +import com.cloud.agent.api.GetHostStatsCommand; +import com.cloud.agent.api.GetStorageStatsCommand; +import com.cloud.agent.api.GetVmStatsCommand; +import com.cloud.agent.api.GetVncPortCommand; +import com.cloud.agent.api.MaintainCommand; +import com.cloud.agent.api.ManageSnapshotCommand; +import com.cloud.agent.api.MigrateCommand; +import com.cloud.agent.api.ModifyStoragePoolCommand; +import com.cloud.agent.api.NetworkUsageCommand; +import com.cloud.agent.api.PingTestCommand; +import com.cloud.agent.api.RebootCommand; +import com.cloud.agent.api.SecStorageSetupCommand; +import com.cloud.agent.api.SecStorageVMSetupCommand; +import com.cloud.agent.api.SecurityIngressRulesCmd; +import com.cloud.agent.api.StartCommand; +import com.cloud.agent.api.StopCommand; +import com.cloud.agent.api.StoragePoolInfo; +import com.cloud.agent.api.check.CheckSshCommand; +import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; +import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; +import com.cloud.agent.api.routing.DhcpEntryCommand; +import com.cloud.agent.api.routing.IpAssocCommand; +import com.cloud.agent.api.routing.LoadBalancerConfigCommand; +import com.cloud.agent.api.routing.SavePasswordCommand; +import com.cloud.agent.api.routing.SetPortForwardingRulesCommand; +import com.cloud.agent.api.routing.SetStaticNatRulesCommand; +import com.cloud.agent.api.routing.VmDataCommand; +import com.cloud.agent.api.storage.CreateCommand; +import com.cloud.agent.api.storage.DeleteTemplateCommand; +import com.cloud.agent.api.storage.DestroyCommand; +import com.cloud.agent.api.storage.DownloadCommand; +import com.cloud.agent.api.storage.DownloadProgressCommand; +import com.cloud.agent.api.storage.ListTemplateCommand; +import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; +import com.cloud.resource.AgentResourceBase; +import com.cloud.simulator.MockConfigurationVO; +import com.cloud.simulator.MockHost; +import com.cloud.simulator.MockHostVO; +import com.cloud.simulator.dao.MockConfigurationDao; +import com.cloud.simulator.dao.MockHostDao; +import com.cloud.utils.Pair; +import com.cloud.utils.component.Inject; +import com.cloud.utils.db.ConnectionConcierge; +import com.cloud.utils.db.DB; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.exception.CloudRuntimeException; +@Local(value = { SimulatorManager.class }) +public class SimulatorManagerImpl implements SimulatorManager { + private static final Logger s_logger = Logger.getLogger(SimulatorManagerImpl.class); + @Inject + MockVmManager _mockVmMgr = null; + @Inject + MockStorageManager _mockStorageMgr = null; + @Inject + MockAgentManager _mockAgentMgr = null; + @Inject + MockConfigurationDao _mockConfigDao = null; + @Inject + MockHostDao _mockHost = null; + private ConnectionConcierge _concierge; + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + try { + Connection conn = Transaction.getStandaloneConnectionWithException(); + conn.setAutoCommit(true); + _concierge = new ConnectionConcierge("AgentMonitor", conn, false); + } catch (SQLException e) { + throw new CloudRuntimeException("Unable to get a db connection", e); + } + return true; + } + + @Override + public boolean start() { + return true; + } + + @Override + public boolean stop() { + return true; + } + + @Override + public String getName() { + return this.getClass().getSimpleName(); + } + + @Override + public MockVmManager getVmMgr() { + return _mockVmMgr; + } + + @Override + public MockStorageManager getStorageMgr() { + return _mockStorageMgr; + } + + @Override + public MockAgentManager getAgentMgr() { + return _mockAgentMgr; + } + + @DB + @Override + public Answer simulate(Command cmd, String hostGuid) { + MockHost host = _mockHost.findByGuid(hostGuid); + MockConfigurationVO config = _mockConfigDao.findByCommand(host.getDataCenterId(), host.getPodId(), host.getClusterId(), host.getId(), cmd.toString()); + if (config == null) { + config = _mockConfigDao.findByGlobal(cmd.toString()); + } + + if (config != null) { + Map configParameters = config.getParameters(); + if (configParameters.get("enabled").equalsIgnoreCase("false")) { + return new Answer(cmd, false, "cmd is disabled"); + } + } + + Transaction txn = Transaction.currentTxn(); + txn.transitToUserManagedConnection(_concierge.conn()); + + try { + if (cmd instanceof GetHostStatsCommand) { + return _mockAgentMgr.getHostStatistic((GetHostStatsCommand)cmd); + } else if (cmd instanceof CheckHealthCommand) { + return _mockAgentMgr.checkHealth((CheckHealthCommand)cmd); + } else if (cmd instanceof PingTestCommand) { + return _mockAgentMgr.pingTest((PingTestCommand)cmd); + } else if (cmd instanceof MigrateCommand) { + return _mockVmMgr.Migrate((MigrateCommand)cmd, hostGuid); + } else if (cmd instanceof StartCommand) { + return _mockVmMgr.startVM((StartCommand)cmd, hostGuid); + } else if (cmd instanceof CheckSshCommand) { + return _mockVmMgr.checkSshCommand((CheckSshCommand)cmd); + } else if (cmd instanceof SetStaticNatRulesCommand) { + return _mockVmMgr.SetStaticNatRules((SetStaticNatRulesCommand)cmd); + } else if (cmd instanceof SetPortForwardingRulesCommand) { + return _mockVmMgr.SetPortForwardingRules((SetPortForwardingRulesCommand)cmd); + } else if (cmd instanceof NetworkUsageCommand) { + return _mockVmMgr.getNetworkUsage((NetworkUsageCommand)cmd); + } else if (cmd instanceof IpAssocCommand) { + return _mockVmMgr.IpAssoc((IpAssocCommand)cmd); + } else if (cmd instanceof LoadBalancerConfigCommand) { + return _mockVmMgr.LoadBalancerConfig((LoadBalancerConfigCommand)cmd); + } else if (cmd instanceof DhcpEntryCommand) { + return _mockVmMgr.AddDhcpEntry((DhcpEntryCommand)cmd); + } else if (cmd instanceof VmDataCommand) { + return _mockVmMgr.setVmData((VmDataCommand)cmd); + } else if (cmd instanceof CleanupNetworkRulesCmd) { + return _mockVmMgr.CleanupNetworkRules((CleanupNetworkRulesCmd)cmd, hostGuid); + } else if (cmd instanceof StopCommand) { + return _mockVmMgr.stopVM((StopCommand)cmd); + } else if (cmd instanceof RebootCommand) { + return _mockVmMgr.rebootVM((RebootCommand)cmd); + } else if (cmd instanceof GetVncPortCommand) { + return _mockVmMgr.getVncPort((GetVncPortCommand)cmd); + } else if (cmd instanceof CheckConsoleProxyLoadCommand) { + return _mockVmMgr.CheckConsoleProxyLoad((CheckConsoleProxyLoadCommand)cmd); + } else if (cmd instanceof WatchConsoleProxyLoadCommand) { + return _mockVmMgr.WatchConsoleProxyLoad((WatchConsoleProxyLoadCommand)cmd); + } else if (cmd instanceof SecurityIngressRulesCmd) { + return _mockVmMgr.AddSecurityIngressRules((SecurityIngressRulesCmd)cmd); + } else if (cmd instanceof SavePasswordCommand) { + return _mockVmMgr.SavePassword((SavePasswordCommand)cmd); + } else if (cmd instanceof PrimaryStorageDownloadCommand) { + return _mockStorageMgr.primaryStorageDownload((PrimaryStorageDownloadCommand)cmd); + } else if (cmd instanceof CreateCommand) { + return _mockStorageMgr.createVolume((CreateCommand)cmd); + } else if (cmd instanceof AttachVolumeCommand) { + return _mockStorageMgr.AttachVolume((AttachVolumeCommand)cmd); + } else if (cmd instanceof AttachIsoCommand) { + return _mockStorageMgr.AttachIso((AttachIsoCommand)cmd); + } else if (cmd instanceof DeleteStoragePoolCommand) { + return _mockStorageMgr.DeleteStoragePool((DeleteStoragePoolCommand)cmd); + } else if (cmd instanceof ModifyStoragePoolCommand) { + return _mockStorageMgr.ModifyStoragePool((ModifyStoragePoolCommand)cmd); + } else if (cmd instanceof CreateStoragePoolCommand) { + return _mockStorageMgr.CreateStoragePool((CreateStoragePoolCommand)cmd); + } else if (cmd instanceof SecStorageSetupCommand) { + return _mockStorageMgr.SecStorageSetup((SecStorageSetupCommand)cmd); + } else if (cmd instanceof ListTemplateCommand) { + return _mockStorageMgr.ListTemplates((ListTemplateCommand)cmd); + } else if (cmd instanceof DestroyCommand) { + return _mockStorageMgr.Destroy((DestroyCommand)cmd); + } else if (cmd instanceof DownloadProgressCommand) { + return _mockStorageMgr.DownloadProcess((DownloadProgressCommand)cmd); + } else if (cmd instanceof DownloadCommand) { + return _mockStorageMgr.Download((DownloadCommand)cmd); + } else if (cmd instanceof GetStorageStatsCommand) { + return _mockStorageMgr.GetStorageStats((GetStorageStatsCommand)cmd); + } else if (cmd instanceof ManageSnapshotCommand) { + return _mockStorageMgr.ManageSnapshot((ManageSnapshotCommand)cmd); + } else if (cmd instanceof BackupSnapshotCommand) { + return _mockStorageMgr.BackupSnapshot((BackupSnapshotCommand)cmd); + } else if (cmd instanceof DeleteSnapshotBackupCommand) { + return _mockStorageMgr.DeleteSnapshotBackup((DeleteSnapshotBackupCommand)cmd); + } else if (cmd instanceof CreateVolumeFromSnapshotCommand) { + return _mockStorageMgr.CreateVolumeFromSnapshot((CreateVolumeFromSnapshotCommand)cmd); + } else if (cmd instanceof DeleteTemplateCommand) { + return _mockStorageMgr.DeleteTemplate((DeleteTemplateCommand)cmd); + } else if (cmd instanceof SecStorageVMSetupCommand) { + return _mockStorageMgr.SecStorageVMSetup((SecStorageVMSetupCommand)cmd); + } else if (cmd instanceof CreatePrivateTemplateFromSnapshotCommand) { + return _mockStorageMgr.CreatePrivateTemplateFromSnapshot((CreatePrivateTemplateFromSnapshotCommand)cmd); + } else if (cmd instanceof ComputeChecksumCommand) { + return _mockStorageMgr.ComputeChecksum((ComputeChecksumCommand)cmd); + } else if (cmd instanceof CreatePrivateTemplateFromVolumeCommand) { + return _mockStorageMgr.CreatePrivateTemplateFromVolume((CreatePrivateTemplateFromVolumeCommand)cmd); + } else if (cmd instanceof MaintainCommand) { + return _mockAgentMgr.MaintainCommand((MaintainCommand)cmd); + } else if (cmd instanceof GetVmStatsCommand) { + return _mockVmMgr.getVmStats((GetVmStatsCommand)cmd); + } else { + return Answer.createUnsupportedCommandAnswer(cmd); + } + } catch(Exception e) { + s_logger.debug("Failed execute cmd: " + e.toString()); + txn.rollback(); + return new Answer(cmd, false, e.toString()); + } finally { + txn.transitToAutoManagedConnection(Transaction.CLOUD_DB); + } + } + + @Override + public StoragePoolInfo getLocalStorage(String hostGuid) { + return _mockStorageMgr.getLocalStorage(hostGuid); + } + + @Override + public boolean configureSimulator(Long zoneId, Long podId, Long clusterId, Long hostId, String command, String values) { + MockConfigurationVO config = new MockConfigurationVO(); + config.setClusterId(clusterId); + config.setDataCenterId(zoneId); + config.setPodId(podId); + config.setHostId(hostId); + config.setName(command); + config.setValues(values); + _mockConfigDao.persist(config); + return true; + } + + @Override + public HashMap> syncNetworkGroups(String hostGuid) { + return _mockVmMgr.syncNetworkGroups(hostGuid); + } + +} diff --git a/agent-simulator/src/com/cloud/api/commands/ConfigureSimulatorCmd.java b/agent-simulator/src/com/cloud/api/commands/ConfigureSimulatorCmd.java new file mode 100644 index 00000000000..6af52801423 --- /dev/null +++ b/agent-simulator/src/com/cloud/api/commands/ConfigureSimulatorCmd.java @@ -0,0 +1,65 @@ +package com.cloud.api.commands; + +import org.apache.log4j.Logger; + +import com.cloud.agent.manager.SimulatorManager; +import com.cloud.api.ApiConstants; +import com.cloud.api.BaseCmd; +import com.cloud.api.Parameter; +import com.cloud.api.ServerApiException; +import com.cloud.api.response.BaseResponse; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.server.ManagementService; +import com.cloud.user.Account; +import com.cloud.utils.component.ComponentLocator; + +public class ConfigureSimulatorCmd extends BaseCmd { + public static final Logger s_logger = Logger.getLogger(ConfigureSimulatorCmd.class.getName()); + private static final String s_name = "configuresimulatorresponse"; + + @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, description="configure range: in a zone") + private Long zoneId; + + @Parameter(name=ApiConstants.POD_ID, type=CommandType.LONG, description="configure range: in a pod") + private Long podId; + + @Parameter(name=ApiConstants.CLUSTER_ID, type=CommandType.LONG, description="configure range: in a cluster") + private Long clusterId; + + @Parameter(name=ApiConstants.HOST_ID, type=CommandType.LONG, description="configure range: in a host") + private Long hostId; + + @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, required=true, description="which command needs to be configured") + private String command; + + @Parameter(name=ApiConstants.VALUE, type=CommandType.STRING, required=true, description="configuration options for this command, which is seperated by ;") + private String values; + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException { + ComponentLocator locator = ComponentLocator.getLocator(ManagementService.Name); + SimulatorManager _simMgr = locator.getManager(SimulatorManager.class); + boolean result = _simMgr.configureSimulator(zoneId, podId, clusterId, hostId, command, values); + if (!result) { + throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to configure simulator"); + } + + BaseResponse response = new BaseResponse(); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + +} diff --git a/agent-simulator/src/com/cloud/configuration/SimulatorComponentLibrary.java b/agent-simulator/src/com/cloud/configuration/SimulatorComponentLibrary.java new file mode 100644 index 00000000000..7206d3f5592 --- /dev/null +++ b/agent-simulator/src/com/cloud/configuration/SimulatorComponentLibrary.java @@ -0,0 +1,36 @@ +package com.cloud.configuration; + +import com.cloud.agent.manager.MockAgentManagerImpl; +import com.cloud.agent.manager.MockStorageManagerImpl; +import com.cloud.agent.manager.MockVmManagerImpl; +import com.cloud.agent.manager.SimulatorManagerImpl; +import com.cloud.network.NetworkUsageManagerImpl; + +import com.cloud.simulator.dao.MockConfigurationDaoImpl; +import com.cloud.simulator.dao.MockHostDaoImpl; +import com.cloud.simulator.dao.MockSecStorageDaoImpl; +import com.cloud.simulator.dao.MockSecurityRulesDaoImpl; +import com.cloud.simulator.dao.MockStoragePoolDaoImpl; +import com.cloud.simulator.dao.MockVMDaoImpl; +import com.cloud.simulator.dao.MockVolumeDaoImpl; + +public class SimulatorComponentLibrary extends PremiumComponentLibrary { + @Override + protected void populateManagers() { + addManager("VM Manager", MockVmManagerImpl.class); + addManager("agent manager", MockAgentManagerImpl.class); + addManager("storage manager", MockStorageManagerImpl.class); + addManager("SimulatorManager", SimulatorManagerImpl.class); + } + + @Override + protected void populateDaos() { + addDao("mock Host", MockHostDaoImpl.class); + addDao("mock secondary storage", MockSecStorageDaoImpl.class); + addDao("mock storage pool", MockStoragePoolDaoImpl.class); + addDao("mock vm", MockVMDaoImpl.class); + addDao("mock volume", MockVolumeDaoImpl.class); + addDao("mock config", MockConfigurationDaoImpl.class); + addDao("mock security rules", MockSecurityRulesDaoImpl.class); + } +} diff --git a/agent-simulator/src/com/cloud/resource/AgentResourceBase.java b/agent-simulator/src/com/cloud/resource/AgentResourceBase.java new file mode 100644 index 00000000000..663c2118b87 --- /dev/null +++ b/agent-simulator/src/com/cloud/resource/AgentResourceBase.java @@ -0,0 +1,278 @@ +/** + * Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + */ + +package com.cloud.resource; + +import java.io.File; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.InetAddress; +import java.net.URL; +import java.util.ArrayList; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import javax.naming.ConfigurationException; + +import org.apache.log4j.Logger; + +import com.cloud.agent.IAgentControl; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.PingCommand; +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.manager.MockAgentManager; +import com.cloud.agent.manager.MockStorageManager; +import com.cloud.agent.manager.MockStorageManagerImpl; +import com.cloud.agent.manager.MockVmManager; +import com.cloud.agent.manager.SimulatorManager; +import com.cloud.agent.manager.SimulatorManager.AgentType; +import com.cloud.host.Host; +import com.cloud.host.Host.Type; +import com.cloud.resource.ServerResource; +import com.cloud.simulator.MockHost; +import com.cloud.utils.component.ComponentLocator; +import com.cloud.utils.net.MacAddress; +import com.cloud.utils.net.NetUtils; + +public class AgentResourceBase implements ServerResource { + private static final Logger s_logger = Logger + .getLogger(AgentResourceBase.class); + + protected String _name; + private List _warnings = new LinkedList(); + private List _errors = new LinkedList(); + + private transient IAgentControl _agentControl; + + protected long _instanceId; + + private Type _type; + + private transient ComponentLocator _locator = null; + protected transient SimulatorManager _simMgr; + protected MockHost agentHost = null; + protected boolean stopped = false; + protected String hostGuid = null; + + + public AgentResourceBase(long instanceId, AgentType agentType, SimulatorManager simMgr, String hostGuid) { + _instanceId = instanceId; + + if(s_logger.isDebugEnabled()) { + s_logger.info("New Routing host instantiated with guid:" + hostGuid); + } + + if (agentType == AgentType.Routing) { + _type = Host.Type.Routing; + } else { + _type = Host.Type.Storage; + } + + this.hostGuid = hostGuid; + } + + protected MockVmManager getVmMgr() { + return _simMgr.getVmMgr(); + } + + protected MockStorageManager getStorageMgr() { + return _simMgr.getStorageMgr(); + } + + protected MockAgentManager getAgentMgr() { + return _simMgr.getAgentMgr(); + } + + protected long getInstanceId() { + return _instanceId; + } + + public AgentResourceBase() { + if(s_logger.isDebugEnabled()) { + s_logger.debug("Deserializing simulated agent on reconnect"); + } + + } + + @Override + public String getName() { + return _name; + } + + public void setName(String name) { + _name = name; + } + + @Override + public boolean configure(String name, Map params) + throws ConfigurationException { + hostGuid = (String)params.get("guid"); + _locator = ComponentLocator.getLocator("management-server"); + _simMgr = _locator.getManager(SimulatorManager.class); + + agentHost = getAgentMgr().getHost(hostGuid); + return true; + } + + + private void reconnect(MockHost host) { + if(s_logger.isDebugEnabled()) { + s_logger.debug("Reconfiguring existing simulated host w/ name: " + host.getName() + " and guid: " + host.getGuid()); + } + this.agentHost = host; + } + + + @Override + public void disconnected() { + this.stopped = true; + } + + protected void recordWarning(String msg, Throwable th) { + String str = getLogStr(msg, th); + synchronized (_warnings) { + _warnings.add(str); + } + } + + protected void recordWarning(String msg) { + recordWarning(msg, null); + } + + protected List getWarnings() { + synchronized (this) { + List results = _warnings; + _warnings = new ArrayList(); + return results; + } + } + + protected List getErrors() { + synchronized (this) { + List result = _errors; + _errors = new ArrayList(); + return result; + } + } + + protected void recordError(String msg, Throwable th) { + String str = getLogStr(msg, th); + synchronized (_errors) { + _errors.add(str); + } + } + + protected void recordError(String msg) { + recordError(msg, null); + } + + protected Answer createErrorAnswer(Command cmd, String msg, Throwable th) { + StringWriter writer = new StringWriter(); + if (msg != null) { + writer.append(msg); + } + writer.append("===>Stack<==="); + th.printStackTrace(new PrintWriter(writer)); + return new Answer(cmd, false, writer.toString()); + } + + protected String createErrorDetail(String msg, Throwable th) { + StringWriter writer = new StringWriter(); + if (msg != null) { + writer.append(msg); + } + writer.append("===>Stack<==="); + th.printStackTrace(new PrintWriter(writer)); + return writer.toString(); + } + + protected String getLogStr(String msg, Throwable th) { + StringWriter writer = new StringWriter(); + writer.append(new Date().toString()).append(": ").append(msg); + if (th != null) { + writer.append("\n Exception: "); + th.printStackTrace(new PrintWriter(writer)); + } + return writer.toString(); + } + + @Override + public boolean start() { + return true; + } + + @Override + public boolean stop() { + this.stopped = true; + return true; + } + + @Override + public IAgentControl getAgentControl() { + return _agentControl; + } + + @Override + public void setAgentControl(IAgentControl agentControl) { + _agentControl = agentControl; + } + + protected String findScript(String script) { + s_logger.debug("Looking for " + script + " in the classpath"); + URL url = ClassLoader.getSystemResource(script); + File file = null; + if (url == null) { + file = new File("./" + script); + s_logger.debug("Looking for " + script + " in " + + file.getAbsolutePath()); + if (!file.exists()) { + return null; + } + } else { + file = new File(url.getFile()); + } + return file.getAbsolutePath(); + } + + + @Override + public Answer executeRequest(Command cmd) { + return null; + } + + @Override + public PingCommand getCurrentStatus(long id) { + return null; + } + + @Override + public Type getType() { + return _type; + } + + public void setType(Host.Type _type) { + this._type = _type; + } + + @Override + public StartupCommand[] initialize() { + return null; + } + + public SimulatorManager getSimulatorManager() { + return _simMgr; + } + + public void setSimulatorManager(SimulatorManager simMgr) { + _simMgr = simMgr; + } + + public boolean isStopped() { + return this.stopped; + } +} diff --git a/agent-simulator/src/com/cloud/resource/AgentRoutingResource.java b/agent-simulator/src/com/cloud/resource/AgentRoutingResource.java new file mode 100644 index 00000000000..ca1ba99bfb3 --- /dev/null +++ b/agent-simulator/src/com/cloud/resource/AgentRoutingResource.java @@ -0,0 +1,320 @@ +/** + * Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + */ + +package com.cloud.resource; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.naming.ConfigurationException; + +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CheckVirtualMachineAnswer; +import com.cloud.agent.api.CheckVirtualMachineCommand; +import com.cloud.agent.api.Command; + +import com.cloud.agent.api.PingCommand; +import com.cloud.agent.api.PingRoutingCommand; +import com.cloud.agent.api.PingRoutingWithNwGroupsCommand; +import com.cloud.agent.api.PrepareForMigrationCommand; +import com.cloud.agent.api.ReadyAnswer; +import com.cloud.agent.api.ReadyCommand; +import com.cloud.agent.api.ShutdownCommand; +import com.cloud.agent.api.StartAnswer; +import com.cloud.agent.api.StartCommand; +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.StartupRoutingCommand; +import com.cloud.agent.api.StartupStorageCommand; +import com.cloud.agent.api.StopAnswer; +import com.cloud.agent.api.StopCommand; +import com.cloud.agent.api.StoragePoolInfo; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.agent.manager.SimulatorManager; +import com.cloud.agent.manager.SimulatorManager.AgentType; +import com.cloud.host.Host; +import com.cloud.host.Host.Type; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.network.Networks.RouterPrivateIpStrategy; +import com.cloud.storage.Storage.StorageResourceType; +import com.cloud.storage.template.TemplateInfo; +import com.cloud.utils.Pair; +import com.cloud.vm.VirtualMachine.State; + +public class AgentRoutingResource extends AgentStorageResource { + private static final Logger s_logger = Logger.getLogger(AgentRoutingResource.class); + + protected Map _vms = new HashMap(20); + protected String _mountParent; + + + public AgentRoutingResource(long instanceId, AgentType agentType, SimulatorManager simMgr, String hostGuid) { + super(instanceId, agentType, simMgr, hostGuid); + } + + public AgentRoutingResource() { + setType(Host.Type.Routing); + } + + @Override + public Answer executeRequest(Command cmd) { + try { + if (cmd instanceof StartCommand) { + return execute((StartCommand) cmd); + } else if (cmd instanceof StopCommand) { + return execute((StopCommand) cmd); + } else if (cmd instanceof PrepareForMigrationCommand) { + return execute((PrepareForMigrationCommand) cmd); + } else if (cmd instanceof CheckVirtualMachineCommand) { + return execute((CheckVirtualMachineCommand) cmd); + } else if (cmd instanceof ReadyCommand) { + return new ReadyAnswer((ReadyCommand)cmd); + } else if (cmd instanceof ShutdownCommand) { + return execute((ShutdownCommand)cmd); + } else { + return _simMgr.simulate(cmd, hostGuid); + } + } catch (IllegalArgumentException e) { + return new Answer(cmd, false, e.getMessage()); + } + } + + @Override + public Type getType() { + return Host.Type.Routing; + } + + @Override + public PingCommand getCurrentStatus(long id) { + if (isStopped()) { + return null; + } + final HashMap newStates = sync(); + HashMap> nwGrpStates = _simMgr.syncNetworkGroups(hostGuid); + return new PingRoutingWithNwGroupsCommand(getType(), id, newStates, nwGrpStates); + } + + @Override + public StartupCommand[] initialize() { + synchronized (_vms) { + _vms.clear(); + } + Map changes = sync(); + List info = getHostInfo(); + + StartupRoutingCommand cmd = new StartupRoutingCommand((Integer) info.get(0), (Long) info.get(1), (Long) info.get(2), (Long) info.get(4), (String) info.get(3), HypervisorType.Simulator, + RouterPrivateIpStrategy.HostLocal); + cmd.setStateChanges(changes); + + Map hostDetails = new HashMap(); + hostDetails.put(RouterPrivateIpStrategy.class.getCanonicalName(), RouterPrivateIpStrategy.DcGlobal.toString()); + + cmd.setHostDetails(hostDetails); + cmd.setAgentTag("agent-simulator"); + cmd.setPrivateIpAddress(agentHost.getPrivateIpAddress()); + cmd.setPrivateNetmask(agentHost.getPrivateNetMask()); + cmd.setPrivateMacAddress(agentHost.getPrivateMacAddress()); + cmd.setStorageIpAddress(agentHost.getStorageIpAddress()); + cmd.setStorageNetmask(agentHost.getStorageNetMask()); + cmd.setStorageMacAddress(agentHost.getStorageMacAddress()); + cmd.setStorageIpAddressDeux(agentHost.getStorageIpAddress()); + cmd.setStorageNetmaskDeux(agentHost.getStorageNetMask()); + cmd.setStorageMacAddressDeux(agentHost.getStorageIpAddress()); + + cmd.setName(agentHost.getName()); + cmd.setGuid(agentHost.getGuid()); + cmd.setVersion(agentHost.getVersion()); + cmd.setAgentTag("agent-simulator"); + cmd.setDataCenter(String.valueOf(agentHost.getDataCenterId())); + cmd.setPod(String.valueOf(agentHost.getPodId())); + cmd.setCluster(String.valueOf(agentHost.getClusterId())); + + StartupStorageCommand ssCmd = initializeLocalSR(); + + return new StartupCommand[] { cmd, ssCmd }; + } + + private StartupStorageCommand initializeLocalSR() { + Map tInfo = new HashMap(); + + StoragePoolInfo poolInfo = _simMgr.getLocalStorage(hostGuid); + + StartupStorageCommand cmd = new StartupStorageCommand(poolInfo.getHostPath(), poolInfo.getPoolType(), poolInfo.getCapacityBytes(), tInfo); + + cmd.setPoolInfo(poolInfo); + cmd.setGuid(agentHost.getGuid()); + cmd.setResourceType(StorageResourceType.STORAGE_POOL); + return cmd; + } + + protected synchronized Answer execute(StartCommand cmd) + throws IllegalArgumentException { + VirtualMachineTO vmSpec = cmd.getVirtualMachine(); + String vmName = vmSpec.getName(); + + State state = State.Stopped; + synchronized (_vms) { + _vms.put(vmName, State.Starting); + } + + try { + Answer result = _simMgr.simulate(cmd, hostGuid); + if (!result.getResult()) { + return new StartAnswer(cmd, result.getDetails()); + } + + state = State.Running; + + } finally { + synchronized (_vms) { + _vms.put(vmName, state); + } + } + + return new StartAnswer(cmd); + + } + + protected synchronized StopAnswer execute(StopCommand cmd) { + + StopAnswer answer = null; + String vmName = cmd.getVmName(); + + State state = null; + synchronized (_vms) { + state = _vms.get(vmName); + _vms.put(vmName, State.Stopping); + } + try { + Answer result = _simMgr.simulate(cmd, hostGuid); + + if (!result.getResult()) { + return new StopAnswer(cmd, result.getDetails()); + } + + answer = new StopAnswer(cmd, null, 0, new Long(100), new Long(200)); + + state = State.Stopped; + + } finally { + synchronized (_vms) { + _vms.put(vmName, state); + } + } + + return answer; + } + + protected CheckVirtualMachineAnswer execute(final CheckVirtualMachineCommand cmd) { + final String vmName = cmd.getVmName(); + CheckVirtualMachineAnswer result = (CheckVirtualMachineAnswer)_simMgr.simulate(cmd, hostGuid); + State state = result.getState(); + if (state == State.Running) { + synchronized (_vms) { + _vms.put(vmName, State.Running); + } + } + return result; + } + + protected List getHostInfo() { + ArrayList info = new ArrayList(); + long speed = agentHost.getCpuSpeed(); + long cpus = agentHost.getCpuCount(); + long ram = agentHost.getMemorySize(); + long dom0Ram = agentHost.getMemorySize()/10; + + info.add((int) cpus); + info.add(speed); + info.add(ram); + info.add(agentHost.getCapabilities()); + info.add(dom0Ram); + + return info; + } + + protected HashMap sync() { + Map newStates; + Map oldStates = null; + + HashMap changes = new HashMap(); + + synchronized (_vms) { + newStates = getVmMgr().getVmStates(hostGuid); + oldStates = new HashMap(_vms.size()); + oldStates.putAll(_vms); + + for (Map.Entry entry : newStates.entrySet()) { + String vm = entry.getKey(); + + State newState = entry.getValue(); + State oldState = oldStates.remove(vm); + + if (s_logger.isTraceEnabled()) { + s_logger.trace("VM " + vm + ": has state " + newState + " and we have state " + (oldState != null ? oldState.toString() : "null")); + } + + if (oldState == null) { + _vms.put(vm, newState); + changes.put(vm, newState); + } else if (oldState == State.Starting) { + if (newState == State.Running) { + _vms.put(vm, newState); + } else if (newState == State.Stopped) { + s_logger.debug("Ignoring vm " + vm + " because of a lag in starting the vm."); + } + } else if (oldState == State.Stopping) { + if (newState == State.Stopped) { + _vms.put(vm, newState); + } else if (newState == State.Running) { + s_logger.debug("Ignoring vm " + vm + " because of a lag in stopping the vm. "); + } + } else if (oldState != newState) { + _vms.put(vm, newState); + changes.put(vm, newState); + } + } + + for (Map.Entry entry : oldStates.entrySet()) { + String vm = entry.getKey(); + State oldState = entry.getValue(); + + if (s_logger.isTraceEnabled()) { + s_logger.trace("VM " + vm + " is now missing from simulator agent so reporting stopped"); + } + + if (oldState == State.Stopping) { + s_logger.debug("Ignoring VM " + vm + " in transition state stopping."); + _vms.remove(vm); + } else if (oldState == State.Starting) { + s_logger.debug("Ignoring VM " + vm + " in transition state starting."); + } else if (oldState == State.Stopped) { + _vms.remove(vm); + } else { + changes.put(entry.getKey(), State.Stopped); + } + } + } + + return changes; + } + + private Answer execute(ShutdownCommand cmd) { + this.stopped = true; + return new Answer(cmd); + } + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + if (!super.configure(name, params)) { + s_logger.warn("Base class was unable to configure"); + return false; + } + return true; + } +} diff --git a/agent-simulator/src/com/cloud/resource/AgentStorageResource.java b/agent-simulator/src/com/cloud/resource/AgentStorageResource.java new file mode 100644 index 00000000000..8aae4a63388 --- /dev/null +++ b/agent-simulator/src/com/cloud/resource/AgentStorageResource.java @@ -0,0 +1,112 @@ +/** + * Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + */ + +package com.cloud.resource; +import java.util.HashMap; +import java.util.Map; + + +import javax.naming.ConfigurationException; + +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; + +import com.cloud.agent.api.Command; + +import com.cloud.agent.api.PingCommand; +import com.cloud.agent.api.PingStorageCommand; +import com.cloud.agent.api.ReadyAnswer; +import com.cloud.agent.api.ReadyCommand; + +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.StartupSecondaryStorageCommand; + +import com.cloud.agent.api.storage.ssCommand; + +import com.cloud.agent.manager.SimulatorManager; +import com.cloud.agent.manager.SimulatorManager.AgentType; +import com.cloud.host.Host; +import com.cloud.host.Host.Type; + +import com.cloud.storage.resource.SecondaryStorageResource; + +import com.cloud.vm.SecondaryStorageVm; + + +public class AgentStorageResource extends AgentResourceBase implements SecondaryStorageResource { + private static final Logger s_logger = Logger.getLogger(AgentStorageResource.class); + + final protected String _parent = "/mnt/SecStorage"; + protected String _role; + + public AgentStorageResource(long instanceId, AgentType agentType, SimulatorManager simMgr, String hostGuid) { + super(instanceId, agentType, simMgr, hostGuid); + } + + public AgentStorageResource() { + setType(Host.Type.SecondaryStorage); + } + + @Override + public Answer executeRequest(Command cmd) { + if (cmd instanceof ReadyCommand) { + return new ReadyAnswer((ReadyCommand)cmd); + } else { + return _simMgr.simulate(cmd, hostGuid); + } + } + + @Override + public PingCommand getCurrentStatus(long id) { + if (isStopped()) { + return null; + } + return new PingStorageCommand(Host.Type.Storage, id, new HashMap()); + } + + @Override + public Type getType() { + if(SecondaryStorageVm.Role.templateProcessor.toString().equals(_role)) + return Host.Type.SecondaryStorage; + return Host.Type.SecondaryStorageCmdExecutor; + } + + @Override + public StartupCommand[] initialize() { + StartupSecondaryStorageCommand cmd = new StartupSecondaryStorageCommand(); + + cmd.setPrivateIpAddress(agentHost.getPrivateIpAddress()); + cmd.setPrivateNetmask(agentHost.getPrivateNetMask()); + cmd.setPrivateMacAddress(agentHost.getPrivateMacAddress()); + cmd.setStorageIpAddress(agentHost.getStorageIpAddress()); + cmd.setStorageNetmask(agentHost.getStorageNetMask()); + cmd.setStorageMacAddress(agentHost.getStorageMacAddress()); + cmd.setPublicIpAddress(agentHost.getPublicIpAddress()); + + cmd.setName(agentHost.getName()); + cmd.setAgentTag("agent-simulator"); + cmd.setVersion(agentHost.getVersion()); + cmd.setDataCenter(String.valueOf(agentHost.getDataCenterId())); + cmd.setPod(String.valueOf(agentHost.getPodId())); + cmd.setGuid(agentHost.getGuid()); + return new StartupCommand[] { cmd }; + } + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + if (!super.configure(name, params)) { + s_logger.warn("Base class was unable to configure"); + return false; + } + + return true; + } + + @Override + public String getRootDir(ssCommand cmd) { + // TODO Auto-generated method stub + return null; + } +} diff --git a/agent-simulator/src/com/cloud/resource/SimulatorDiscoverer.java b/agent-simulator/src/com/cloud/resource/SimulatorDiscoverer.java new file mode 100755 index 00000000000..dff0cce760d --- /dev/null +++ b/agent-simulator/src/com/cloud/resource/SimulatorDiscoverer.java @@ -0,0 +1,308 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +package com.cloud.resource; + +import java.net.URI; +import java.net.URLDecoder; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import javax.ejb.Local; +import javax.naming.ConfigurationException; + +import org.apache.log4j.Logger; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.Listener; +import com.cloud.agent.api.AgentControlAnswer; +import com.cloud.agent.api.AgentControlCommand; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.manager.MockAgentManager; +import com.cloud.agent.manager.MockStorageManager; +import com.cloud.agent.manager.SimulatorManager; +import com.cloud.agent.manager.SimulatorManagerImpl; +import com.cloud.dc.ClusterVO; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.exception.ConnectionException; +import com.cloud.exception.DiscoveryException; +import com.cloud.resource.Discoverer; +import com.cloud.host.Host; +import com.cloud.host.HostVO; +import com.cloud.host.Status; +import com.cloud.host.dao.HostDao; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.VMTemplateHostVO; +import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.VMTemplateZoneVO; +import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.storage.dao.VMTemplateHostDao; +import com.cloud.storage.dao.VMTemplateZoneDao; +import com.cloud.storage.VMTemplateStorageResourceAssoc; +import com.cloud.utils.component.Inject; + +/** + * @author prasanna + * + */ +@Local(value = Discoverer.class) +public class SimulatorDiscoverer extends DiscovererBase implements Discoverer, Listener { + private static final Logger s_logger = Logger + .getLogger(SimulatorDiscoverer.class); + + @Inject HostDao _hostDao; + @Inject VMTemplateDao _vmTemplateDao; + @Inject VMTemplateHostDao _vmTemplateHostDao; + @Inject VMTemplateZoneDao _vmTemplateZoneDao; + @Inject ClusterDao _clusterDao; + @Inject AgentManager _agentMgr = null; + @Inject MockAgentManager _mockAgentMgr = null; + @Inject MockStorageManager _mockStorageMgr = null; + + /** + * Finds ServerResources of an in-process simulator + * + * @see com.cloud.resource.Discoverer#find(long, java.lang.Long, + * java.lang.Long, java.net.URI, java.lang.String, java.lang.String) + */ + @Override + public Map> find(long dcId, + Long podId, Long clusterId, URI uri, String username, + String password, List hostTags) throws DiscoveryException { + Map> resources; + + try { + //http://sim/count=$count, it will add $count number of hosts into the cluster + String scheme = uri.getScheme(); + String host = uri.getAuthority(); + String commands = URLDecoder.decode(uri.getPath()); + + long cpuSpeed = _mockAgentMgr.DEFAULT_HOST_SPEED_MHZ; + long cpuCores = _mockAgentMgr.DEFAULT_HOST_CPU_CORES; + long memory = _mockAgentMgr.DEFAULT_HOST_MEM_SIZE; + long localstorageSize = _mockStorageMgr.DEFAULT_HOST_STORAGE_SIZE; + if (scheme.equals("http")) { + if (host == null || !host.equalsIgnoreCase("sim")) { + String msg = "uri is not of simulator type so we're not taking care of the discovery for this: " + + uri; + if(s_logger.isDebugEnabled()) { + s_logger.debug(msg); + } + return null; + } + if (commands != null) { + int index = commands.lastIndexOf("/"); + if (index != -1) { + commands = commands.substring(index+1); + + String[] cmds = commands.split("&"); + for (String cmd : cmds) { + String[] parameter = cmd.split("="); + if (parameter[0].equalsIgnoreCase("cpuspeed") && parameter[1] != null) { + cpuSpeed = Long.parseLong(parameter[1]); + } else if (parameter[0].equalsIgnoreCase("cpucore") && parameter[1] != null) { + cpuCores = Long.parseLong(parameter[1]); + } else if (parameter[0].equalsIgnoreCase("memory") && parameter[1] != null) { + memory = Long.parseLong(parameter[1]); + } else if (parameter[0].equalsIgnoreCase("localstorage") && parameter[1] != null) { + localstorageSize = Long.parseLong(parameter[1]); + } + } + } + } + } else { + String msg = "uriString is not http so we're not taking care of the discovery for this: " + + uri; + if(s_logger.isDebugEnabled()) { + s_logger.debug(msg); + } + return null; + } + + String cluster = null; + if (clusterId == null) { + String msg = "must specify cluster Id when adding host"; + if(s_logger.isDebugEnabled()) { + s_logger.debug(msg); + } + throw new RuntimeException(msg); + } else { + ClusterVO clu = _clusterDao.findById(clusterId); + if (clu == null + || (clu.getHypervisorType() != HypervisorType.Simulator)) { + if (s_logger.isInfoEnabled()) + s_logger.info("invalid cluster id or cluster is not for Simulator hypervisors"); + return null; + } + cluster = Long.toString(clusterId); + if(clu.getGuid() == null) { + clu.setGuid(UUID.randomUUID().toString()); + } + _clusterDao.update(clusterId, clu); + } + + String pod; + if (podId == null) { + String msg = "must specify pod Id when adding host"; + if(s_logger.isDebugEnabled()) { + s_logger.debug(msg); + } + throw new RuntimeException(msg); + } else { + pod = Long.toString(podId); + } + + Map details = new HashMap(); + Map params = new HashMap(); + details.put("username", username); + params.put("username", username); + details.put("password", password); + params.put("password", password); + params.put("zone", Long.toString(dcId)); + params.put("pod", pod); + params.put("cluster", cluster); + params.put("cpuspeed", Long.toString(cpuSpeed)); + params.put("cpucore", Long.toString(cpuCores)); + params.put("memory", Long.toString(memory)); + params.put("localstorage", Long.toString(localstorageSize)); + + resources = createAgentResources(params); + return resources; + } catch (Exception ex) { + s_logger.error("Exception when discovering simulator hosts: " + + ex.getMessage()); + } + return null; + } + + private Map> createAgentResources( + Map params) { + try { + s_logger.info("Creating Simulator Resources"); + return _mockAgentMgr.createServerResources(params); + } catch (Exception ex) { + s_logger.warn("Caught exception at agent resource creation: " + + ex.getMessage(), ex); + } + return null; + } + + @Override + public void postDiscovery(List hosts, long msId) { + + for (HostVO h : hosts) { + associateTemplatesToZone(h.getId(), h.getDataCenterId()); + } + } + + private void associateTemplatesToZone(long hostId, long dcId){ + VMTemplateZoneVO tmpltZone; + + List allTemplates = _vmTemplateDao.listAll(); + for (VMTemplateVO vt: allTemplates){ + if (vt.isCrossZones()) { + tmpltZone = _vmTemplateZoneDao.findByZoneTemplate(dcId, vt.getId()); + if (tmpltZone == null) { + VMTemplateZoneVO vmTemplateZone = new VMTemplateZoneVO(dcId, vt.getId(), new Date()); + _vmTemplateZoneDao.persist(vmTemplateZone); + } + } + } + } + + @Override + public HypervisorType getHypervisorType() { + return HypervisorType.Simulator; + } + + @Override + public boolean matchHypervisor(String hypervisor) { + return hypervisor.equalsIgnoreCase(HypervisorType.Simulator.toString()); + } + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + super.configure(name, params); + _agentMgr.registerForHostEvents(this, true, false, false); + return true; + } + + @Override + public boolean processAnswers(long agentId, long seq, Answer[] answers) { + return false; + } + + @Override + public boolean processCommands(long agentId, long seq, Command[] commands) { + return false; + } + + @Override + public AgentControlAnswer processControlCommand(long agentId, AgentControlCommand cmd) { + return null; + } + + @Override + public void processConnect(HostVO host, StartupCommand cmd, boolean forRebalance) throws ConnectionException { + /* + if(forRebalance) + return; + if ( Host.Type.SecondaryStorage == host.getType() ) { + List tmplts = _vmTemplateDao.listAll(); + for( VMTemplateVO tmplt : tmplts ) { + VMTemplateHostVO vmTemplateHost = _vmTemplateHostDao.findByHostTemplate(host.getId(), tmplt.getId()); + if (vmTemplateHost == null) { + vmTemplateHost = new VMTemplateHostVO(host.getId(), tmplt.getId(), new Date(), 100, + VMTemplateStorageResourceAssoc.Status.DOWNLOADED, null, null, null, null, tmplt.getUrl()); + _vmTemplateHostDao.persist(vmTemplateHost); + } else { + vmTemplateHost.setDownloadState(VMTemplateStorageResourceAssoc.Status.DOWNLOADED); + vmTemplateHost.setDownloadPercent(100); + _vmTemplateHostDao.update(vmTemplateHost.getId(), vmTemplateHost); + } + } + } + */ + } + + @Override + public boolean processDisconnect(long agentId, Status state) { + return false; + } + + @Override + public boolean isRecurring() { + return false; + } + + @Override + public int getTimeout() { + return 0; + } + + @Override + public boolean processTimeout(long agentId, long seq) { + return false; + } + +} \ No newline at end of file diff --git a/agent-simulator/src/com/cloud/resource/SimulatorSecondaryDiscoverer.java b/agent-simulator/src/com/cloud/resource/SimulatorSecondaryDiscoverer.java new file mode 100644 index 00000000000..d3b74f29057 --- /dev/null +++ b/agent-simulator/src/com/cloud/resource/SimulatorSecondaryDiscoverer.java @@ -0,0 +1,30 @@ +package com.cloud.resource; + +import java.util.List; +import java.util.Map; + +import javax.ejb.Local; +import javax.naming.ConfigurationException; + +import com.cloud.agent.manager.MockStorageManager; +import com.cloud.host.HostVO; +import com.cloud.storage.secondary.SecondaryStorageDiscoverer; +import com.cloud.utils.component.Inject; +@Local(value=Discoverer.class) +public class SimulatorSecondaryDiscoverer extends SecondaryStorageDiscoverer { + @Inject + MockStorageManager _mockStorageMgr = null; + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + return super.configure(name, params); + } + + @Override + public void postDiscovery(List hosts, long msId) { + super.postDiscovery(hosts, msId); + for (HostVO host: hosts) { + _mockStorageMgr.preinstallTemplates(host.getStorageUrl(), host.getDataCenterId()); + } + } +} diff --git a/agent-simulator/src/com/cloud/server/ManagementServerSimulatorImpl.java b/agent-simulator/src/com/cloud/server/ManagementServerSimulatorImpl.java new file mode 100644 index 00000000000..03a736f3a06 --- /dev/null +++ b/agent-simulator/src/com/cloud/server/ManagementServerSimulatorImpl.java @@ -0,0 +1,17 @@ +package com.cloud.server; + +import com.cloud.server.ManagementServerExtImpl; + +public class ManagementServerSimulatorImpl extends ManagementServerExtImpl { + @Override + public String[] getApiConfig() { + String[] apis = super.getApiConfig(); + String[] newapis = new String[apis.length + 1]; + for (int i = 0; i < apis.length; i++) { + newapis[i] = apis[i]; + } + + newapis[apis.length] = "commands-simulator.properties"; + return newapis; + } +} diff --git a/agent-simulator/src/com/cloud/simulator/MockConfigurationVO.java b/agent-simulator/src/com/cloud/simulator/MockConfigurationVO.java new file mode 100644 index 00000000000..f167949c735 --- /dev/null +++ b/agent-simulator/src/com/cloud/simulator/MockConfigurationVO.java @@ -0,0 +1,105 @@ +package com.cloud.simulator; + +import java.util.HashMap; +import java.util.Map; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name="mockconfiguration") +public class MockConfigurationVO { + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id") + private long id; + + @Column(name="data_center_id", nullable=false) + private Long dataCenterId; + + @Column(name="pod_id") + private Long podId; + + @Column(name="cluster_id") + private Long clusterId; + + @Column(name="host_id") + private Long hostId; + + @Column(name="name") + private String name; + + @Column(name="values") + private String values; + + public long getId() { + return this.id; + } + + public Long getDataCenterId() { + return this.dataCenterId; + } + + public void setDataCenterId(Long dcId) { + this.dataCenterId = dcId; + } + + public Long getPodId() { + return this.podId; + } + + public void setPodId(Long podId) { + this.podId = podId; + } + + public Long getClusterId() { + return this.clusterId; + } + + public void setClusterId(Long clusterId) { + this.clusterId = clusterId; + } + + public Long getHostId() { + return this.hostId; + } + + public void setHostId(Long hostId) { + this.hostId = hostId; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public String getValues() { + return this.values; + } + + public Map getParameters() { + Map maps = new HashMap(); + if (this.values == null) { + return maps; + } + + String[] vals = this.values.split(";"); + for (String val : vals) { + String[] paras = val.split("="); + maps.put(paras[0], paras[1]); + } + return maps; + } + + public void setValues(String values) { + this.values = values; + } +} + diff --git a/agent-simulator/src/com/cloud/simulator/MockHost.java b/agent-simulator/src/com/cloud/simulator/MockHost.java new file mode 100644 index 00000000000..4755acef75c --- /dev/null +++ b/agent-simulator/src/com/cloud/simulator/MockHost.java @@ -0,0 +1,46 @@ +package com.cloud.simulator; + +public interface MockHost { + public long getCpuSpeed(); + public long getCpuCount(); + + + public long getMemorySize(); + + public String getCapabilities(); + + public long getId(); + + public String getName(); + + public String getGuid(); + + + public String getVersion(); + + public Long getDataCenterId(); + + public Long getPodId(); + + public Long getClusterId(); + + public String getPrivateIpAddress(); + + public String getPrivateNetMask(); + + public String getPrivateMacAddress(); + + + public String getPublicIpAddress(); + + public String getPublicNetMask(); + + public String getPublicMacAddress(); + + public String getStorageIpAddress(); + + public String getStorageNetMask(); + + public String getStorageMacAddress(); + +} diff --git a/agent-simulator/src/com/cloud/simulator/MockHostVO.java b/agent-simulator/src/com/cloud/simulator/MockHostVO.java new file mode 100644 index 00000000000..677d84a2c89 --- /dev/null +++ b/agent-simulator/src/com/cloud/simulator/MockHostVO.java @@ -0,0 +1,264 @@ +package com.cloud.simulator; + +import javax.persistence.Column; +import javax.persistence.DiscriminatorColumn; +import javax.persistence.DiscriminatorType; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.Table; + +@Entity +@Table(name="mockhost") + +public class MockHostVO implements MockHost { + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id") + private long id; + + @Column(name="name", nullable=false) + private String name = null; + + @Column(name="private_ip_address", nullable=false) + private String privateIpAddress; + + @Column(name="private_mac_address", nullable=false) + private String privateMacAddress; + + @Column(name="private_netmask", nullable=false) + private String privateNetmask; + + @Column(name="public_netmask") + private String publicNetmask; + + @Column(name="public_ip_address") + private String publicIpAddress; + + @Column(name="public_mac_address") + private String publicMacAddress; + + @Column(name="storage_ip_address") + private String storageIpAddress; + + @Column(name="storage_mac_address") + private String storageMacAddress; + + @Column(name="storage_netmask") + private String storageNetMask; + + @Column(name="guid") + private String guid; + + @Column(name="version") + private String version; + + @Column(name="data_center_id", nullable=false) + private long dataCenterId; + + @Column(name="pod_id") + private Long podId; + + @Column(name="cluster_id") + private Long clusterId; + + @Column(name="speed") + private long cpuSpeed; + + @Column(name="cpus") + private long cpuCount; + + @Column(name="ram") + private long memorySize; + + @Column(name="capabilities") + private String capabilities; + + @Column(name="vm_id") + private long vmId; + + @Column(name="resource") + private String resource; + + + + public MockHostVO() { + + } + + + public long getVmId() { + return vmId; + } + + public void setVmId(long vmId) { + this.vmId = vmId; + } + + public String getResource() { + return this.resource; + } + + public void setResource(String resource) { + this.resource = resource; + } + + public long getCpuSpeed() { + return this.cpuSpeed; + } + + public void setCpuSpeed(long cpuSpeed) { + this.cpuSpeed = cpuSpeed; + } + + public long getCpuCount() { + return this.cpuCount; + } + + public void setCpuCount(long cpuCount) { + this.cpuCount = cpuCount; + } + + public long getMemorySize() { + return this.memorySize; + } + + public void setMemorySize(long memorySize) { + this.memorySize = memorySize; + } + + public String getCapabilities() { + return this.capabilities; + } + + public void setCapabilities(String capabilities) { + this.capabilities = capabilities; + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getGuid() { + return this.guid; + } + + public void setGuid(String guid) { + this.guid = guid; + } + + public String getVersion() { + return this.version; + } + + public void setVersion(String version) { + this.version = version; + } + + public Long getDataCenterId() { + return this.dataCenterId; + } + + public void setDataCenterId(Long dataCenterId) { + this.dataCenterId = dataCenterId; + } + + public Long getPodId() { + return this.podId; + } + + public void setPodId(long podId) { + this.podId = podId; + } + + public Long getClusterId() { + return this.clusterId; + } + + public void setClusterId(Long clusterId) { + this.clusterId = clusterId; + } + + public String getPrivateIpAddress() { + return privateIpAddress; + } + + public void setPrivateIpAddress(String privateIpAddress) { + this.privateIpAddress = privateIpAddress; + } + + public String getPrivateNetMask() { + return this.privateNetmask; + } + + public void setPrivateNetMask(String privateNetmask) { + this.privateNetmask = privateNetmask; + } + + public String getPrivateMacAddress() { + return this.privateMacAddress; + } + + public void setPrivateMacAddress(String privateMacAddress) { + this.privateMacAddress = privateMacAddress; + } + + public String getPublicIpAddress() { + return this.publicIpAddress; + } + + public void setPublicIpAddress(String publicIpAddress) { + this.publicIpAddress = publicIpAddress; + } + + public String getPublicNetMask() { + return this.publicNetmask; + } + + public void setPublicNetMask(String publicNetMask) { + this.publicNetmask = publicNetMask; + } + + public String getPublicMacAddress() { + return this.publicMacAddress; + } + + public void setPublicMacAddress(String publicMacAddress) { + this.publicMacAddress = publicMacAddress; + } + + public String getStorageIpAddress() { + return this.storageIpAddress; + } + + public void setStorageIpAddress(String storageIpAddress) { + this.storageIpAddress = storageIpAddress; + } + + public String getStorageNetMask() { + return this.storageNetMask; + } + + public void setStorageNetMask(String storageNetMask) { + this.storageNetMask = storageNetMask; + } + + public String getStorageMacAddress() { + return this.storageMacAddress; + } + + public void setStorageMacAddress(String storageMacAddress) { + this.storageMacAddress = storageMacAddress; + } +} diff --git a/agent-simulator/src/com/cloud/simulator/MockSecStorageVO.java b/agent-simulator/src/com/cloud/simulator/MockSecStorageVO.java new file mode 100644 index 00000000000..91d05cc38cf --- /dev/null +++ b/agent-simulator/src/com/cloud/simulator/MockSecStorageVO.java @@ -0,0 +1,64 @@ +package com.cloud.simulator; + +import javax.persistence.Column; +import javax.persistence.DiscriminatorColumn; +import javax.persistence.DiscriminatorType; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.Table; + +@Entity +@Table(name="mocksecstorage") + +public class MockSecStorageVO { + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id") + private long id; + + @Column(name="url") + private String url; + + @Column(name="capacity") + private long capacity; + + @Column(name="mount_point") + private String mountPoint; + + + public MockSecStorageVO() { + + } + + public long getId() { + return this.id; + } + + public String getMountPoint() { + return this.mountPoint; + } + + public void setMountPoint(String mountPoint) { + this.mountPoint = mountPoint; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public long getCapacity() { + return this.capacity; + } + + public void setCapacity(long capacity) { + this.capacity = capacity; + } +} diff --git a/agent-simulator/src/com/cloud/simulator/MockSecurityRulesVO.java b/agent-simulator/src/com/cloud/simulator/MockSecurityRulesVO.java new file mode 100644 index 00000000000..e4c8857d7b9 --- /dev/null +++ b/agent-simulator/src/com/cloud/simulator/MockSecurityRulesVO.java @@ -0,0 +1,88 @@ +package com.cloud.simulator; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + + +@Entity +@Table(name="mocksecurityrules") +public class MockSecurityRulesVO { + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id") + private long id; + + @Column(name="vmid") + private Long vmId; + + @Column(name="signature") + private String signature; + + @Column(name="seqnum") + private Long seqnum; + + @Column(name="ruleset") + private String ruleset; + + @Column(name="hostid") + private Long hostId; + + @Column(name="vmname") + public String vmName; + + public String getVmName() { + return this.vmName; + } + + public void setVmName(String vmName) { + this.vmName = vmName; + } + + public Long getHostId() { + return this.hostId; + } + + public void setHostId(Long hostId) { + this.hostId = hostId; + } + + public long getId() { + return this.id; + } + + public Long getVmId() { + return this.vmId; + } + + public void setVmId(Long vmId) { + this.vmId = vmId; + } + + public String getSignature() { + return this.signature; + } + + public void setSignature(String sig) { + this.signature = sig; + } + + public Long getSeqNum() { + return this.seqnum; + } + + public void setSeqNum(Long seqNum) { + this.seqnum = seqNum; + } + + public String getRuleSet() { + return this.ruleset; + } + + public void setRuleSet(String ruleset) { + this.ruleset = ruleset; + } +} diff --git a/agent-simulator/src/com/cloud/simulator/MockStoragePoolVO.java b/agent-simulator/src/com/cloud/simulator/MockStoragePoolVO.java new file mode 100644 index 00000000000..efabec2d58c --- /dev/null +++ b/agent-simulator/src/com/cloud/simulator/MockStoragePoolVO.java @@ -0,0 +1,90 @@ +package com.cloud.simulator; + +import javax.persistence.Column; +import javax.persistence.DiscriminatorColumn; +import javax.persistence.DiscriminatorType; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.Table; + +import com.cloud.storage.Storage.StoragePoolType; + +@Entity +@Table(name="mockstoragepool") + +public class MockStoragePoolVO { + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id") + private long id; + + @Column(name="guid") + private String uuid; + + @Column(name="mount_point") + private String mountPoint; + + @Column(name="capacity") + private long capacity; + + @Column(name="hostguid") + private String hostGuid; + + @Column(name="pool_type") + @Enumerated(value=EnumType.STRING) + private StoragePoolType poolType; + + public MockStoragePoolVO() { + + } + + public String getHostGuid() { + return this.hostGuid; + } + + public void setHostGuid(String hostGuid) { + this.hostGuid = hostGuid; + } + + public long getId() { + return this.id; + } + + public StoragePoolType getPoolType() { + return this.poolType; + } + + public void setStorageType(StoragePoolType poolType) { + this.poolType = poolType; + } + + public String getUuid() { + return this.uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getMountPoint() { + return this.mountPoint; + } + + public void setMountPoint(String mountPoint) { + this.mountPoint = mountPoint; + } + + public long getCapacity() { + return this.capacity; + } + + public void setCapacity(long capacity) { + this.capacity = capacity; + } +} diff --git a/agent-simulator/src/com/cloud/simulator/MockVMVO.java b/agent-simulator/src/com/cloud/simulator/MockVMVO.java new file mode 100644 index 00000000000..af11eff15e5 --- /dev/null +++ b/agent-simulator/src/com/cloud/simulator/MockVMVO.java @@ -0,0 +1,110 @@ +package com.cloud.simulator; + +import javax.persistence.Column; +import javax.persistence.DiscriminatorColumn; +import javax.persistence.DiscriminatorType; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.Table; + +import com.cloud.vm.VirtualMachine.State; + +@Entity +@Table(name="mockvm") + +public class MockVMVO implements MockVm{ + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id") + private long id; + + @Column(name="name") + private String name; + + @Column(name="host_id") + private long hostId; + + @Column(name="type") + private String vmType; + + @Column(name="state") + private State state; + + @Column(name="vnc_port") + private int vncPort; + + @Column(name="memory") + private long memory; + + @Column(name="cpu") + private int cpu; + + public MockVMVO() { + + } + + public long getId() { + return this.id; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public long getHostId() { + return this.hostId; + } + + public void setHostId(long hostId) { + this.hostId = hostId; + } + + public String getVmType() { + return this.vmType; + } + + public void setVmType(String vmType) { + this.vmType = vmType; + } + + public State getState() { + return this.state; + } + + public void setState(State state) { + this.state = state; + } + + public int getVncPort() { + return this.vncPort; + } + + public void setVncPort(int vncPort) { + this.vncPort = vncPort; + } + + public long getMemory() { + return this.memory; + } + + public void setMemory(long memory) { + this.memory = memory; + } + + public int getCpu() { + return this.cpu; + } + + public void setCpu(int cpu) { + this.cpu = cpu; + } + +} diff --git a/agent-simulator/src/com/cloud/simulator/MockVm.java b/agent-simulator/src/com/cloud/simulator/MockVm.java new file mode 100644 index 00000000000..c4ba8632c0d --- /dev/null +++ b/agent-simulator/src/com/cloud/simulator/MockVm.java @@ -0,0 +1,33 @@ +/** + * Copyright (C) 2011 Cloud.com, Inc. All rights reserved. + */ + +package com.cloud.simulator; + +import com.cloud.vm.VirtualMachine.State; + +// As storage is mapped from storage device, can virtually treat that VM here does +// not need any local storage resource, therefore we don't have attribute here for storage +public interface MockVm { + + + public String getName(); + + public State getState(); + + public void setState(State state); + + public void setHostId(long hostId); + public long getMemory(); + + public int getCpu(); + + public int getVncPort(); + + public void setName(String name); + public void setMemory(long memory); + public void setCpu(int cpu); + public void setVncPort(int vncPort); + public long getId(); +} + diff --git a/agent-simulator/src/com/cloud/simulator/MockVolumeVO.java b/agent-simulator/src/com/cloud/simulator/MockVolumeVO.java new file mode 100644 index 00000000000..0f9acb4dff4 --- /dev/null +++ b/agent-simulator/src/com/cloud/simulator/MockVolumeVO.java @@ -0,0 +1,106 @@ +package com.cloud.simulator; + +import javax.persistence.Column; +import javax.persistence.DiscriminatorColumn; +import javax.persistence.DiscriminatorType; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.Table; + +import com.cloud.storage.VMTemplateStorageResourceAssoc; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; + + +@Entity +@Table(name="mockvolume") + +public class MockVolumeVO { + public enum MockVolumeType { + VOLUME, + TEMPLATE, + ISO, + SNAPSHOT; + } + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id") + private long id; + + @Column(name="name") + private String name; + + @Column(name="size") + private long size; + + @Column(name="path") + private String path; + + @Column(name="pool_id") + private long poolId; + + @Column(name="type") + @Enumerated(value=EnumType.STRING) + private MockVolumeType type; + + @Column(name="status") + @Enumerated(value=EnumType.STRING) + private VMTemplateStorageResourceAssoc.Status status; + + public long getId() { + return id; + } + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public long getSize() { + return this.size; + } + + public void setSize(long size) { + this.size = size; + } + + public String getPath() { + return this.path; + } + + public void setPath(String path) { + this.path = path; + } + + public long getPoolId() { + return this.poolId; + } + + public void setPoolId(long poolId) { + this.poolId = poolId; + } + + public MockVolumeType getType() { + return this.type; + } + + public void setType(MockVolumeType type) { + this.type = type; + } + + public Status getStatus() { + return this.status; + } + + public void setStatus(Status status) { + this.status = status; + } + +} diff --git a/agent-simulator/src/com/cloud/simulator/SimulatorGuru.java b/agent-simulator/src/com/cloud/simulator/SimulatorGuru.java new file mode 100644 index 00000000000..19e6707f265 --- /dev/null +++ b/agent-simulator/src/com/cloud/simulator/SimulatorGuru.java @@ -0,0 +1,61 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +package com.cloud.simulator; + +import javax.ejb.Local; + +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.hypervisor.HypervisorGuru; +import com.cloud.hypervisor.HypervisorGuruBase; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.GuestOSVO; +import com.cloud.storage.dao.GuestOSDao; +import com.cloud.utils.component.Inject; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineProfile; + +@Local(value=HypervisorGuru.class) +public class SimulatorGuru extends HypervisorGuruBase implements HypervisorGuru { + @Inject GuestOSDao _guestOsDao; + + protected SimulatorGuru() { + super(); + } + + @Override + public HypervisorType getHypervisorType() { + return HypervisorType.Simulator; + } + + @Override + public VirtualMachineTO implement(VirtualMachineProfile vm) { + VirtualMachineTO to = toVirtualMachineTO(vm); + + // Determine the VM's OS description + GuestOSVO guestOS = _guestOsDao.findById(vm.getVirtualMachine().getGuestOSId()); + to.setOs(guestOS.getDisplayName()); + + return to; + } + + @Override + public boolean trackVmHostChange() { + return false; + } +} diff --git a/agent-simulator/src/com/cloud/simulator/dao/MockConfigurationDao.java b/agent-simulator/src/com/cloud/simulator/dao/MockConfigurationDao.java new file mode 100644 index 00000000000..d684a349c61 --- /dev/null +++ b/agent-simulator/src/com/cloud/simulator/dao/MockConfigurationDao.java @@ -0,0 +1,10 @@ +package com.cloud.simulator.dao; + +import com.cloud.simulator.MockConfigurationVO; +import com.cloud.utils.db.GenericDao; + +public interface MockConfigurationDao extends GenericDao { + MockConfigurationVO findByCommand(Long dcId, Long podId, Long clusterId, Long hostId, String name); + + MockConfigurationVO findByGlobal(String name); +} diff --git a/agent-simulator/src/com/cloud/simulator/dao/MockConfigurationDaoImpl.java b/agent-simulator/src/com/cloud/simulator/dao/MockConfigurationDaoImpl.java new file mode 100644 index 00000000000..aa3a9f0f30a --- /dev/null +++ b/agent-simulator/src/com/cloud/simulator/dao/MockConfigurationDaoImpl.java @@ -0,0 +1,91 @@ +package com.cloud.simulator.dao; + +import javax.ejb.Local; + +import com.cloud.simulator.MockConfigurationVO; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; + +@Local(value={MockConfigurationDao.class}) +public class MockConfigurationDaoImpl extends GenericDaoBase implements MockConfigurationDao { + private SearchBuilder _searchByDcIdName; + private SearchBuilder _searchByDcIDPodIdName; + private SearchBuilder _searchByDcIDPodIdClusterIdName; + private SearchBuilder _searchByDcIDPodIdClusterIdHostIdName; + private SearchBuilder _searchByGlobalName; + + public MockConfigurationDaoImpl() { + _searchByGlobalName = createSearchBuilder(); + _searchByGlobalName.and("dcId", _searchByGlobalName.entity().getDataCenterId(), SearchCriteria.Op.NULL); + _searchByGlobalName.and("name", _searchByGlobalName.entity().getName(), SearchCriteria.Op.EQ); + _searchByGlobalName.done(); + + _searchByDcIdName = createSearchBuilder(); + _searchByDcIdName.and("dcId", _searchByDcIdName.entity().getDataCenterId(), SearchCriteria.Op.EQ); + _searchByDcIdName.and("name", _searchByDcIdName.entity().getName(), SearchCriteria.Op.EQ); + _searchByDcIdName.done(); + + _searchByDcIDPodIdName = createSearchBuilder(); + _searchByDcIDPodIdName.and("dcId", _searchByDcIDPodIdName.entity().getDataCenterId(), SearchCriteria.Op.EQ); + _searchByDcIDPodIdName.and("podId", _searchByDcIDPodIdName.entity().getPodId(), SearchCriteria.Op.EQ); + _searchByDcIDPodIdName.and("name", _searchByDcIDPodIdName.entity().getName(), SearchCriteria.Op.EQ); + _searchByDcIDPodIdName.done(); + + _searchByDcIDPodIdClusterIdName = createSearchBuilder(); + _searchByDcIDPodIdClusterIdName.and("dcId", _searchByDcIDPodIdClusterIdName.entity().getDataCenterId(), SearchCriteria.Op.EQ); + _searchByDcIDPodIdClusterIdName.and("podId", _searchByDcIDPodIdClusterIdName.entity().getPodId(), SearchCriteria.Op.EQ); + _searchByDcIDPodIdClusterIdName.and("clusterId", _searchByDcIDPodIdClusterIdName.entity().getClusterId(), SearchCriteria.Op.EQ); + _searchByDcIDPodIdClusterIdName.and("name", _searchByDcIDPodIdClusterIdName.entity().getName(), SearchCriteria.Op.EQ); + _searchByDcIDPodIdClusterIdName.done(); + + _searchByDcIDPodIdClusterIdHostIdName = createSearchBuilder(); + _searchByDcIDPodIdClusterIdHostIdName.and("dcId", _searchByDcIDPodIdClusterIdHostIdName.entity().getDataCenterId(), SearchCriteria.Op.EQ); + _searchByDcIDPodIdClusterIdHostIdName.and("podId", _searchByDcIDPodIdClusterIdHostIdName.entity().getPodId(), SearchCriteria.Op.EQ); + _searchByDcIDPodIdClusterIdHostIdName.and("clusterId", _searchByDcIDPodIdClusterIdHostIdName.entity().getClusterId(), SearchCriteria.Op.EQ); + _searchByDcIDPodIdClusterIdHostIdName.and("hostId", _searchByDcIDPodIdClusterIdHostIdName.entity().getHostId(), SearchCriteria.Op.EQ); + _searchByDcIDPodIdClusterIdHostIdName.and("name", _searchByDcIDPodIdClusterIdHostIdName.entity().getName(), SearchCriteria.Op.EQ); + _searchByDcIDPodIdClusterIdHostIdName.done(); + } + @Override + public MockConfigurationVO findByCommand(Long dcId, Long podId, Long clusterId, Long hostId, String name) { + + if (dcId == null) { + SearchCriteria sc = _searchByGlobalName.create(); + sc.setParameters("name", name); + return findOneBy(sc); + } else if (podId == null) { + SearchCriteria sc = _searchByDcIdName.create(); + sc.setParameters("name", name); + sc.setParameters("dcId", dcId); + return findOneBy(sc); + } else if (clusterId == null) { + SearchCriteria sc = _searchByDcIDPodIdName.create(); + sc.setParameters("name", name); + sc.setParameters("dcId", dcId); + sc.setParameters("podId", podId); + return findOneBy(sc); + } else if (hostId == null) { + SearchCriteria sc = _searchByDcIDPodIdClusterIdName.create(); + sc.setParameters("name", name); + sc.setParameters("dcId", dcId); + sc.setParameters("podId", podId); + sc.setParameters("clusterId", clusterId); + return findOneBy(sc); + } else { + SearchCriteria sc = _searchByDcIDPodIdClusterIdHostIdName.create(); + sc.setParameters("name", name); + sc.setParameters("dcId", dcId); + sc.setParameters("podId", podId); + sc.setParameters("clusterId", clusterId); + sc.setParameters("hostId", hostId); + return findOneBy(sc); + } + } + + @Override + public MockConfigurationVO findByGlobal(String name) { + return this.findByCommand(null, null, null, null, name); + } + +} diff --git a/agent-simulator/src/com/cloud/simulator/dao/MockHostDao.java b/agent-simulator/src/com/cloud/simulator/dao/MockHostDao.java new file mode 100644 index 00000000000..f228dfe211b --- /dev/null +++ b/agent-simulator/src/com/cloud/simulator/dao/MockHostDao.java @@ -0,0 +1,11 @@ +package com.cloud.simulator.dao; + +import com.cloud.simulator.MockHost; +import com.cloud.simulator.MockHostVO; +import com.cloud.utils.db.GenericDao; + +public interface MockHostDao extends GenericDao { + public MockHost findByGuid(String guid); + public MockHost findByVmId(long vmId); + public boolean removeByGuid(String guid); +} diff --git a/agent-simulator/src/com/cloud/simulator/dao/MockHostDaoImpl.java b/agent-simulator/src/com/cloud/simulator/dao/MockHostDaoImpl.java new file mode 100644 index 00000000000..43a77d3248a --- /dev/null +++ b/agent-simulator/src/com/cloud/simulator/dao/MockHostDaoImpl.java @@ -0,0 +1,42 @@ +package com.cloud.simulator.dao; + +import javax.ejb.Local; + + +import com.cloud.simulator.MockHost; +import com.cloud.simulator.MockHostVO; + +import com.cloud.utils.db.GenericDaoBase; + +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; + +@Local(value={MockHostDao.class}) +public class MockHostDaoImpl extends GenericDaoBase implements MockHostDao { + protected final SearchBuilder GuidSearch; + public MockHostDaoImpl() { + GuidSearch = createSearchBuilder(); + GuidSearch.and("guid", GuidSearch.entity().getGuid(), SearchCriteria.Op.EQ); + GuidSearch.done(); + } + @Override + public MockHost findByGuid(String guid) { + SearchCriteria sc = GuidSearch.create(); + sc.setParameters("guid", guid); + return findOneBy(sc); + } + @Override + public MockHost findByVmId(long vmId) { + // TODO Auto-generated method stub + return null; + } + @Override + public boolean removeByGuid(String guid) { + MockHost host = this.findByGuid(guid); + if (host == null) { + return false; + } + return this.remove(host.getId()); + } + +} diff --git a/agent-simulator/src/com/cloud/simulator/dao/MockSecStorageDao.java b/agent-simulator/src/com/cloud/simulator/dao/MockSecStorageDao.java new file mode 100644 index 00000000000..0ad5b1e03d9 --- /dev/null +++ b/agent-simulator/src/com/cloud/simulator/dao/MockSecStorageDao.java @@ -0,0 +1,8 @@ +package com.cloud.simulator.dao; + +import com.cloud.simulator.MockSecStorageVO; +import com.cloud.utils.db.GenericDao; + +public interface MockSecStorageDao extends GenericDao { + public MockSecStorageVO findByUrl(String url); +} diff --git a/agent-simulator/src/com/cloud/simulator/dao/MockSecStorageDaoImpl.java b/agent-simulator/src/com/cloud/simulator/dao/MockSecStorageDaoImpl.java new file mode 100644 index 00000000000..c94d51d68ed --- /dev/null +++ b/agent-simulator/src/com/cloud/simulator/dao/MockSecStorageDaoImpl.java @@ -0,0 +1,28 @@ +package com.cloud.simulator.dao; + +import javax.ejb.Local; + +import com.cloud.simulator.MockHostVO; +import com.cloud.simulator.MockSecStorageVO; +import com.cloud.simulator.MockVMVO; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; + +@Local(value={MockSecStorageDao.class}) +public class MockSecStorageDaoImpl extends GenericDaoBase implements MockSecStorageDao { + protected final SearchBuilder urlSearch; + @Override + public MockSecStorageVO findByUrl(String url) { + SearchCriteria sc = urlSearch.create(); + sc.setParameters("url", url); + return findOneBy(sc); + } + + public MockSecStorageDaoImpl() { + urlSearch = createSearchBuilder(); + urlSearch.and("url", urlSearch.entity().getUrl(), SearchCriteria.Op.EQ); + urlSearch.done(); + } + +} diff --git a/agent-simulator/src/com/cloud/simulator/dao/MockSecurityRulesDao.java b/agent-simulator/src/com/cloud/simulator/dao/MockSecurityRulesDao.java new file mode 100644 index 00000000000..a755fccd6c8 --- /dev/null +++ b/agent-simulator/src/com/cloud/simulator/dao/MockSecurityRulesDao.java @@ -0,0 +1,11 @@ +package com.cloud.simulator.dao; + +import java.util.List; + +import com.cloud.simulator.MockSecurityRulesVO; +import com.cloud.utils.db.GenericDao; + +public interface MockSecurityRulesDao extends GenericDao { + public MockSecurityRulesVO findByVmId(Long vmId); + public List findByHost(String hostGuid); +} diff --git a/agent-simulator/src/com/cloud/simulator/dao/MockSecurityRulesDaoImpl.java b/agent-simulator/src/com/cloud/simulator/dao/MockSecurityRulesDaoImpl.java new file mode 100644 index 00000000000..9a31772ef27 --- /dev/null +++ b/agent-simulator/src/com/cloud/simulator/dao/MockSecurityRulesDaoImpl.java @@ -0,0 +1,47 @@ +package com.cloud.simulator.dao; + +import java.util.List; + +import java.util.Map; + +import javax.ejb.Local; +import javax.naming.ConfigurationException; + +import com.cloud.simulator.MockSecurityRulesVO; + +import com.cloud.utils.db.GenericDaoBase; + +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +@Local(value={MockSecurityRulesDao.class}) +public class MockSecurityRulesDaoImpl extends GenericDaoBase implements MockSecurityRulesDao { + protected SearchBuilder vmIdSearch; + protected SearchBuilder hostSearch; + @Override + public MockSecurityRulesVO findByVmId(Long vmId) { + SearchCriteria sc = vmIdSearch.create(); + sc.setParameters("vmId", vmId); + return findOneBy(sc); + } + + @Override + public List findByHost(String hostGuid) { + SearchCriteria sc = hostSearch.create(); + sc.setParameters("host", hostGuid); + return listBy(sc); + } + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + vmIdSearch = createSearchBuilder(); + vmIdSearch.and("vmId", vmIdSearch.entity().getVmId(), SearchCriteria.Op.EQ); + vmIdSearch.done(); + + hostSearch = createSearchBuilder(); + hostSearch.and("host", hostSearch.entity().getHostId(), SearchCriteria.Op.EQ); + hostSearch.done(); + + return true; + } + +} diff --git a/agent-simulator/src/com/cloud/simulator/dao/MockStoragePoolDao.java b/agent-simulator/src/com/cloud/simulator/dao/MockStoragePoolDao.java new file mode 100644 index 00000000000..9c4f2114a35 --- /dev/null +++ b/agent-simulator/src/com/cloud/simulator/dao/MockStoragePoolDao.java @@ -0,0 +1,9 @@ +package com.cloud.simulator.dao; + +import com.cloud.simulator.MockStoragePoolVO; +import com.cloud.utils.db.GenericDao; + +public interface MockStoragePoolDao extends GenericDao { + public MockStoragePoolVO findByUuid(String uuid); + public MockStoragePoolVO findByHost(String hostUuid); +} diff --git a/agent-simulator/src/com/cloud/simulator/dao/MockStoragePoolDaoImpl.java b/agent-simulator/src/com/cloud/simulator/dao/MockStoragePoolDaoImpl.java new file mode 100644 index 00000000000..ad4355c7db9 --- /dev/null +++ b/agent-simulator/src/com/cloud/simulator/dao/MockStoragePoolDaoImpl.java @@ -0,0 +1,41 @@ +package com.cloud.simulator.dao; + +import javax.ejb.Local; + +import com.cloud.simulator.MockStoragePoolVO; +import com.cloud.storage.Storage.StoragePoolType; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; + +@Local(value={MockStoragePoolDao.class}) +public class MockStoragePoolDaoImpl extends GenericDaoBase implements MockStoragePoolDao { + protected final SearchBuilder uuidSearch; + protected final SearchBuilder hostguidSearch; + @Override + public MockStoragePoolVO findByUuid(String uuid) { + SearchCriteria sc = uuidSearch.create(); + sc.setParameters("uuid", uuid); + return findOneBy(sc); + } + + public MockStoragePoolDaoImpl() { + uuidSearch = createSearchBuilder(); + uuidSearch.and("uuid", uuidSearch.entity().getUuid(), SearchCriteria.Op.EQ); + uuidSearch.done(); + + hostguidSearch = createSearchBuilder(); + hostguidSearch.and("hostguid", hostguidSearch.entity().getHostGuid(), SearchCriteria.Op.EQ); + hostguidSearch.and("type", hostguidSearch.entity().getPoolType(), SearchCriteria.Op.EQ); + hostguidSearch.done(); + } + + @Override + public MockStoragePoolVO findByHost(String hostUuid) { + SearchCriteria sc = hostguidSearch.create(); + sc.setParameters("hostguid", hostUuid); + sc.setParameters("type", StoragePoolType.Filesystem.toString()); + return findOneBy(sc); + } + +} diff --git a/agent-simulator/src/com/cloud/simulator/dao/MockVMDao.java b/agent-simulator/src/com/cloud/simulator/dao/MockVMDao.java new file mode 100644 index 00000000000..32e6a32de2f --- /dev/null +++ b/agent-simulator/src/com/cloud/simulator/dao/MockVMDao.java @@ -0,0 +1,13 @@ +package com.cloud.simulator.dao; + +import java.util.List; + +import com.cloud.simulator.MockVMVO; +import com.cloud.utils.db.GenericDao; + +public interface MockVMDao extends GenericDao { + public List findByHostId(long hostId); + public List findByHostGuid(String guid); + public MockVMVO findByVmName(String vmName); + public MockVMVO findByVmNameAndHost(String vmName, String hostGuid); +} diff --git a/agent-simulator/src/com/cloud/simulator/dao/MockVMDaoImpl.java b/agent-simulator/src/com/cloud/simulator/dao/MockVMDaoImpl.java new file mode 100644 index 00000000000..9d7b1e23497 --- /dev/null +++ b/agent-simulator/src/com/cloud/simulator/dao/MockVMDaoImpl.java @@ -0,0 +1,75 @@ +package com.cloud.simulator.dao; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.ejb.Local; +import javax.naming.ConfigurationException; + +import com.cloud.simulator.MockHostVO; +import com.cloud.simulator.MockVMVO; +import com.cloud.utils.component.Inject; +import com.cloud.utils.db.Filter; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.GenericSearchBuilder; +import com.cloud.utils.db.JoinBuilder; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; + +@Local(value={MockVMDao.class}) +public class MockVMDaoImpl extends GenericDaoBase implements MockVMDao { + protected SearchBuilder GuidSearch; + protected SearchBuilder vmNameSearch; + protected SearchBuilder vmhostSearch; + @Inject MockHostDao _mockHostDao; + @Override + public List findByHostId(long hostId) { + return new ArrayList(); + } + + @Override + public MockVMVO findByVmName(String vmName) { + SearchCriteria sc = vmNameSearch.create(); + sc.setParameters("name", vmName); + return findOneBy(sc); + } + + @Override + public List findByHostGuid(String guid) { + SearchCriteria sc = GuidSearch.create(); + sc.setJoinParameters("host", "guid", guid); + return listBy(sc); + } + + @Override + public MockVMVO findByVmNameAndHost(String vmName, String hostGuid) { + SearchCriteria sc = vmhostSearch.create(); + sc.setJoinParameters("host", "guid", hostGuid); + sc.setParameters("name", vmName); + return findOneBy(sc); + } + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + SearchBuilder host = _mockHostDao.createSearchBuilder(); + host.and("guid", host.entity().getGuid(), SearchCriteria.Op.EQ); + + GuidSearch = createSearchBuilder(); + GuidSearch.join("host", host, host.entity().getId(), GuidSearch.entity().getHostId(), JoinBuilder.JoinType.INNER); + GuidSearch.done(); + + vmNameSearch = createSearchBuilder(); + vmNameSearch.and("name", vmNameSearch.entity().getName(), SearchCriteria.Op.EQ); + vmNameSearch.done(); + + SearchBuilder newhost = _mockHostDao.createSearchBuilder(); + newhost.and("guid", newhost.entity().getGuid(), SearchCriteria.Op.EQ); + vmhostSearch = createSearchBuilder(); + vmhostSearch.and("name", vmhostSearch.entity().getName(), SearchCriteria.Op.EQ); + vmhostSearch.join("host", newhost, newhost.entity().getId(), vmhostSearch.entity().getHostId(), JoinBuilder.JoinType.INNER); + vmhostSearch.done(); + + return true; + } +} diff --git a/agent-simulator/src/com/cloud/simulator/dao/MockVolumeDao.java b/agent-simulator/src/com/cloud/simulator/dao/MockVolumeDao.java new file mode 100644 index 00000000000..9848d89c6c8 --- /dev/null +++ b/agent-simulator/src/com/cloud/simulator/dao/MockVolumeDao.java @@ -0,0 +1,14 @@ +package com.cloud.simulator.dao; + +import java.util.List; + +import com.cloud.simulator.MockVolumeVO; +import com.cloud.utils.db.GenericDao; + +public interface MockVolumeDao extends GenericDao { + public List findByStorageIdAndType(long id, MockVolumeVO.MockVolumeType type); + public MockVolumeVO findByStoragePathAndType(String path); + public MockVolumeVO findByNameAndPool(String volumeName, String poolUUID); + public MockVolumeVO findByName(String volumeName); + Long findTotalStorageId(long id); +} diff --git a/agent-simulator/src/com/cloud/simulator/dao/MockVolumeDaoImpl.java b/agent-simulator/src/com/cloud/simulator/dao/MockVolumeDaoImpl.java new file mode 100644 index 00000000000..4527e6610e3 --- /dev/null +++ b/agent-simulator/src/com/cloud/simulator/dao/MockVolumeDaoImpl.java @@ -0,0 +1,85 @@ +package com.cloud.simulator.dao; + +import java.util.List; + +import javax.ejb.Local; + +import com.cloud.simulator.MockVolumeVO; +import com.cloud.simulator.MockVolumeVO.MockVolumeType; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.GenericSearchBuilder; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Func; + +@Local(value={MockVolumeDao.class}) +public class MockVolumeDaoImpl extends GenericDaoBase implements MockVolumeDao { + protected final SearchBuilder idTypeSearch; + protected final SearchBuilder pathTypeSearch; + protected final SearchBuilder namePoolSearch; + protected final SearchBuilder nameSearch; + protected final GenericSearchBuilder totalSearch; + @Override + public List findByStorageIdAndType(long id, MockVolumeType type) { + SearchCriteria sc = idTypeSearch.create(); + sc.setParameters("storageId", id); + sc.setParameters("type", type); + return listBy(sc); + } + + @Override + public Long findTotalStorageId(long id) { + SearchCriteria sc = totalSearch.create(); + + sc.setParameters("poolId", id); + return customSearch(sc, null).get(0); + } + + @Override + public MockVolumeVO findByStoragePathAndType(String path) { + SearchCriteria sc = pathTypeSearch.create(); + sc.setParameters("path", "%" + path + "%"); + return findOneBy(sc); + } + + @Override + public MockVolumeVO findByNameAndPool(String volumeName, String poolUUID) { + SearchCriteria sc = namePoolSearch.create(); + sc.setParameters("name", volumeName); + sc.setParameters("poolUuid", poolUUID); + return findOneBy(sc); + } + + @Override + public MockVolumeVO findByName(String volumeName) { + SearchCriteria sc = nameSearch.create(); + sc.setParameters("name", volumeName); + return findOneBy(sc); + } + + public MockVolumeDaoImpl() { + idTypeSearch = createSearchBuilder(); + idTypeSearch.and("storageId", idTypeSearch.entity().getPoolId(), SearchCriteria.Op.EQ); + idTypeSearch.and("type", idTypeSearch.entity().getType(), SearchCriteria.Op.EQ); + idTypeSearch.done(); + + pathTypeSearch = createSearchBuilder(); + pathTypeSearch.and("path", pathTypeSearch.entity().getPath(), SearchCriteria.Op.LIKE); + pathTypeSearch.done(); + + namePoolSearch = createSearchBuilder(); + namePoolSearch.and("name", namePoolSearch.entity().getName(), SearchCriteria.Op.EQ); + namePoolSearch.and("poolUuid", namePoolSearch.entity().getPoolId(), SearchCriteria.Op.EQ); + namePoolSearch.done(); + + nameSearch = createSearchBuilder(); + nameSearch.and("name", nameSearch.entity().getName(), SearchCriteria.Op.EQ); + nameSearch.done(); + + totalSearch = createSearchBuilder(Long.class); + totalSearch.select(null, Func.SUM, totalSearch.entity().getSize()); + totalSearch.and("poolId", totalSearch.entity().getPoolId(), SearchCriteria.Op.EQ); + totalSearch.done(); + + } +} diff --git a/agent-simulator/tomcatconf/commands-simulator.properties.in b/agent-simulator/tomcatconf/commands-simulator.properties.in new file mode 100644 index 00000000000..862b60dbbc6 --- /dev/null +++ b/agent-simulator/tomcatconf/commands-simulator.properties.in @@ -0,0 +1 @@ +configureSimulatorCmd=com.cloud.api.commands.ConfigureSimulatorCmd;1 \ No newline at end of file diff --git a/agent-simulator/tomcatconf/components-simulator.xml.in b/agent-simulator/tomcatconf/components-simulator.xml.in new file mode 100755 index 00000000000..f0af2ab7197 --- /dev/null +++ b/agent-simulator/tomcatconf/components-simulator.xml.in @@ -0,0 +1,35 @@ + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + diff --git a/build/build-tests.xml b/build/build-tests.xml new file mode 100755 index 00000000000..408e811b7d7 --- /dev/null +++ b/build/build-tests.xml @@ -0,0 +1,248 @@ + + + + + + Cloud Stack ant build file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+
+
+
+ +
+ + diff --git a/build/package.xml b/build/package.xml index 480164ea365..8a3a1ee23c9 100755 --- a/build/package.xml +++ b/build/package.xml @@ -141,7 +141,17 @@ - + + + + + + + + + + + diff --git a/test/.classpath b/test/.classpath new file mode 100644 index 00000000000..7dd07c2f699 --- /dev/null +++ b/test/.classpath @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/test/.project b/test/.project new file mode 100644 index 00000000000..5853edd2b0f --- /dev/null +++ b/test/.project @@ -0,0 +1,19 @@ + + + test + + + thirdparty + utils + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/test/bindir/cloud-run-test.in b/test/bindir/cloud-run-test.in new file mode 100755 index 00000000000..68b3932b35f --- /dev/null +++ b/test/bindir/cloud-run-test.in @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +set -e + +LIBS=" +commons-httpclient +commons-httpclient-3.1 +commons-logging +commons-logging-1.1.1 +commons-codec +commons-codec-1.3 +log4j +log4j-1.2.15 +cloud-test +cloud-utils +trilead-ssh2 +trilead-ssh2-build213 +" + +JAVADIR="@JAVADIR@" +VMOPSCONF="@SYSCONFDIR@"/vmops/test +if [ "$OSTYPE" == "cygwin" ] ; then + true +else + set +e + CLASSPATH=$(build-classpath $LIBS 2>/dev/null) + set -e + CLASSPATH="$CLASSPATH":"$VMOPSCONF" + export CLASSPATH +fi + +test="$1" +shift || true +if [ "$test" == "" ] ; then + echo usage: $0 test.to.run \ > /dev/stderr + exit 64 +fi +java -cp "$CLASSPATH" com.cloud.test."$test" "$@" diff --git a/test/conf/README b/test/conf/README new file mode 100644 index 00000000000..6836c0f8b7f --- /dev/null +++ b/test/conf/README @@ -0,0 +1,8 @@ +To run submitCertEC2 and deleteCertEC2 scripts, update parameters in conf/tool.properties file: + +* host - ip address of the host where cloud-bridge software is installed +* port - port cloud-bridge software is listening to +* accesspoint - access point for cloud-bridge REST request +* version - Amazon EC2 api version supported by cloud-bridge +* signaturemethod - HmacSHA1 or HmacSHA256 +* expires - the date when certificate expires \ No newline at end of file diff --git a/test/conf/config.xml b/test/conf/config.xml new file mode 100644 index 00000000000..b8eedbef8dd --- /dev/null +++ b/test/conf/config.xml @@ -0,0 +1,86 @@ + + + + + addSecondaryStorage + + + zoneid + 2 + + + url + nfs://192.168.161.21/export/regression/secondary + + + + + + addHost + + + zoneid + 2 + + + podid + 2 + + + url + http://192.168.161.25 + + + username + root + + + password + password + + + clustername + firstcluster + + + + + + sleep.sh + + Sleep for 3 min to ensure that host is in UP state + + + s + 180 + + + + + + createStoragePool + + + zoneid + 2 + + + podid + 2 + + + name + primary storage + + + url + nfs://192.168.161.21/export/regression/primary + + + clusterid + 1 + + + + + \ No newline at end of file diff --git a/test/conf/deploy.properties b/test/conf/deploy.properties new file mode 100644 index 00000000000..f29222077eb --- /dev/null +++ b/test/conf/deploy.properties @@ -0,0 +1,14 @@ +#!/bin/bash +COMPUTE="192.168.161.25" +SERVER="192.168.131.168" +SECONDARY_STORAGE="192.168.161.21" +SECONDARY_STORAGE_DIR=/export/regression/secondary +PRIMARY_STORAGE="192.168.161.21" +PRIMARY_STORAGE_DIR=/export/regression/primary +#Db server ip address +DB="192.168.131.168" +#Equal to management server ip if management server is not running in cluster +LB="192.168.131.168" +USER=root +CONFIGDIR=/root/test +LOGDIR=/var/log/cloud/management diff --git a/test/conf/deploy.xml b/test/conf/deploy.xml new file mode 100644 index 00000000000..106c185dead --- /dev/null +++ b/test/conf/deploy.xml @@ -0,0 +1,166 @@ + + + + + + + deletePod + + + id + 1 + + + + + + deleteZone + + + id + 1 + + + + + + createZone + + + name + ZONE1 + + + dns1 + 192.168.10.253 + + + dns2 + 192.168.10.254 + + + internaldns1 + 192.168.10.253 + + + vlan + 400-499 + + + guestcidraddress + 10.1.1.0/24 + + + + + + createVlanIpRange + + + name + Public + + + zoneid + 2 + + + vlan + 19 + + + gateway + 172.19.0.1 + + + netmask + 255.255.0.0 + + + startip + 172.19.0.100 + + + endip + 172.19.0.254 + + + + + + createPod + + + name + POD1 + + + zoneid + 2 + + + cidr + 192.168.161.0/24 + + + startip + 192.168.161.100 + + + endip + 192.168.161.200 + + + gateway + 192.168.161.1 + + + + + + + + + + updateConfiguration + + + name + instance.name + + + value + sanity + + + + + + updateConfiguration + + + name + expunge.delay + + + value + 60 + + + + + + updateConfiguration + + + name + expunge.interval + + + value + 60 + + + + + diff --git a/test/conf/log4j-stdout.properties b/test/conf/log4j-stdout.properties new file mode 100644 index 00000000000..5c7801bd31c --- /dev/null +++ b/test/conf/log4j-stdout.properties @@ -0,0 +1,6 @@ +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n +log4j.appender.stdout.threshold=INFO +log4j.rootLogger=INFO, stdout \ No newline at end of file diff --git a/test/conf/log4j.properties b/test/conf/log4j.properties new file mode 100644 index 00000000000..0f45ba603b4 --- /dev/null +++ b/test/conf/log4j.properties @@ -0,0 +1,14 @@ +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n +log4j.appender.stdout.threshold=INFO +log4j.rootLogger=INFO, stdout, rolling +log4j.appender.rolling=org.apache.log4j.DailyRollingFileAppender +log4j.appender.rolling.layout=org.apache.log4j.PatternLayout +log4j.appender.rolling.layout.ConversionPattern=%d %-5p [%c{3}] (%t:%x) %m%n +log4j.appender.rolling.file.threshold=DEBUG +log4j.appender.rolling.File=./logs/testclient.log +log4j.appender.rolling.DatePattern='.'yyy-MM-dd +log4j.appender.rolling.file.append=false +log4j.category.org.apache=INFO, rolling, stdout diff --git a/test/conf/templates.sql b/test/conf/templates.sql new file mode 100644 index 00000000000..230508ecb28 --- /dev/null +++ b/test/conf/templates.sql @@ -0,0 +1 @@ +INSERT INTO `vmops`.`vm_template` (id, unique_name, name, public, created, type, hvm, bits, account_id, url, ready, display_text, enable_password, format, guest_os_id, create_status, cross_zones) VALUES (1, 'routing', 'DomR Template', 0, now(), 'ext3', 0, 64, 1, 'http://nfs1.lab.vmops.com/templates/routing/latest/routing.vhd.bz2', 0, 'DomR Template', 0, 'VHD', 10, 'Creating', 1);INSERT INTO `vmops`.`vm_template` (id, unique_name, name, public, created, type, hvm, bits, account_id, url, ready, display_text, enable_password, format, guest_os_id, create_status, cross_zones) VALUES (2, 'centos53-x86_64', 'CentOS 5.3(x86_64) no GUI', 1, now(), 'ext3', 0, 64, 1, 'http://nfs1.lab.vmops.com/templates/ami-ccb35ea5/ami-ccb35ea5.vhd.bz2', 0, 'CentOS 5.3(x86_64) no GUI', 0, 'VHD', 10, 'Creating', 1);INSERT INTO `vmops`.`vm_template` (id, unique_name, name, public, created, type,hvm, bits, account_id, url, ready, display_text, enable_password, format, guest_os_id, create_status) VALUES (5, 'ubuntu iso', 'Ubuntu iso', 1, now(), 'cdfs', 1, 64, 1, 'http://172.16.0.220/images/sumita/iso/ubuntu-9.04-server-amd64.iso', 0, 'Ubuntu iso', 0, 'ISO', 51, 'Creating');INSERT INTO `vmops`.`guest_os_category` (id, name) VALUES (1, 'CentOS');INSERT INTO `vmops`.`guest_os_category` (id, name) VALUES (2, 'Citrix');INSERT INTO `vmops`.`guest_os_category` (id, name) VALUES (3, 'Debian');INSERT INTO `vmops`.`guest_os_category` (id, name) VALUES (4, 'Oracle');INSERT INTO `vmops`.`guest_os_category` (id, name) VALUES (5, 'RedHat');INSERT INTO `vmops`.`guest_os_category` (id, name) VALUES (6, 'SUSE');INSERT INTO `vmops`.`guest_os_category` (id, name) VALUES (7, 'Windows');INSERT INTO `vmops`.`guest_os_category` (id, name) VALUES (8, 'Other');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (1, 1, 'CentOS 4.5', 'CentOS 4.5');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (2, 1, 'CentOS 4.6', 'CentOS 4.6');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (3, 1, 'CentOS 4.7', 'CentOS 4.7');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (4, 1, 'CentOS 5.0', 'CentOS 5.0');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (5, 1, 'CentOS 5.0 x64', 'CentOS 5.0 x64');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (6, 1, 'CentOS 5.1', 'CentOS 5.1');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (7, 1, 'CentOS 5.1 x64', 'CentOS 5.1 x64');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (8, 1, 'CentOS 5.2', 'CentOS 5.2');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (9, 1, 'CentOS 5.2 x64', 'CentOS 5.2 x64');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (10, 1, 'CentOS 5.3', 'CentOS 5.3');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (11, 1, 'CentOS 5.3 x64', 'CentOS 5.3 x64');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (12, 2, 'Citrix XenApp', 'Citrix XenApp');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (13, 2, 'Citrix XenApp x64', 'Citrix XenApp x64');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (14, 3, 'Debian Lenny 5.0', 'Debian Lenny 5.0');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (15, 4, 'Oracle Enterprise Linux 5.0', 'Oracle Enterprise Linux 5.0');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (16, 4, 'Oracle Enterprise Linux 5.0 x64', 'Oracle Enterprise Linux 5.0 x64');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (17, 4, 'Oracle Enterprise Linux 5.1', 'Oracle Enterprise Linux 5.1');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (18, 4, 'Oracle Enterprise Linux 5.1 x64', 'Oracle Enterprise Linux 5.1 x64');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (19, 4, 'Oracle Enterprise Linux 5.2', 'Oracle Enterprise Linux 5.2');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (20, 4, 'Oracle Enterprise Linux 5.2 x64', 'Oracle Enterprise Linux 5.2 x64');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (21, 5, 'Red Hat Enterprise Linux 4.5', 'Red Hat Enterprise Linux 4.5');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (22, 5, 'Red Hat Enterprise Linux 4.6', 'Red Hat Enterprise Linux 4.6');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (23, 5, 'Red Hat Enterprise Linux 4.7', 'Red Hat Enterprise Linux 4.7');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (24, 5, 'Red Hat Enterprise Linux 5.0', 'Red Hat Enterprise Linux 5.0');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (25, 5, 'Red Hat Enterprise Linux 5.0 x64', 'Red Hat Enterprise Linux 5.0 x64');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (26, 5, 'Red Hat Enterprise Linux 5.1', 'Red Hat Enterprise Linux 5.1');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (27, 5, 'Red Hat Enterprise Linux 5.1 x64', 'Red Hat Enterprise Linux 5.1 x64');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (28, 5, 'Red Hat Enterprise Linux 5.2', 'Red Hat Enterprise Linux 5.2');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (29, 5, 'Red Hat Enterprise Linux 5.2 x64', 'Red Hat Enterprise Linux 5.2 x64');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (30, 5, 'Red Hat Enterprise Linux 5.3', 'Red Hat Enterprise Linux 5.3');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (31, 5, 'Red Hat Enterprise Linux 5.3 x64', 'Red Hat Enterprise Linux 5.3 x64');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (32, 6, 'SUSE Linux Enterprise Server 9 SP4', 'SUSE Linux Enterprise Server 9 SP4');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (33, 6, 'SUSE Linux Enterprise Server 10 SP1', 'SUSE Linux Enterprise Server 10 SP1');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (34, 6, 'SUSE Linux Enterprise Server 10 SP1 x64', 'SUSE Linux Enterprise Server 10 SP1 x64');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (35, 6, 'SUSE Linux Enterprise Server 10 SP2', 'SUSE Linux Enterprise Server 10 SP2');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (36, 6, 'SUSE Linux Enterprise Server 10 SP2 x64', 'SUSE Linux Enterprise Server 10 SP2 x64');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (37, 6, 'SUSE Linux Enterprise Server 11', 'SUSE Linux Enterprise Server 11');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (38, 6, 'SUSE Linux Enterprise Server 11 x64', 'SUSE Linux Enterprise Server 11 x64');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (39, 7, 'Windows 7', 'Windows 7');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (40, 7, 'Windows 7 x64', 'Windows 7 x64');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (41, 7, 'Windows Server 2003', 'Windows Server 2003');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (42, 7, 'Windows Server 2003 x64', 'Windows Server 2003 x64');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (43, 7, 'Windows Server 2008', 'Windows Server 2008');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (44, 7, 'Windows Server 2008 x64', 'Windows Server 2008 x64');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (45, 7, 'Windows Server 2008 R2 x64', 'Windows Server 2008 R2 x64');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (46, 7, 'Windows 2000 SP4', 'Windows 2000 SP4');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (47, 7, 'Windows Vista', 'Windows Vista');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (48, 7, 'Windows XP SP2', 'Windows XP SP2');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (49, 7, 'Windows XP SP3', 'Windows XP SP3');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (50, 8, 'Other install media', 'Ubuntu');INSERT INTO `vmops`.`guest_os` (id, category_id, name, display_name) VALUES (51, 8, 'Other install media', 'Other'); \ No newline at end of file diff --git a/test/conf/tool.properties b/test/conf/tool.properties new file mode 100644 index 00000000000..9cf07da9a2e --- /dev/null +++ b/test/conf/tool.properties @@ -0,0 +1,6 @@ +host=172.16.1.227 +expires=2010-11-15 +version=2010-08-31 +port=8080 +signaturemethod=HmacSHA1 +accesspoint=bridge/rest/AmazonEC2 \ No newline at end of file diff --git a/test/metadata/adapter.xml b/test/metadata/adapter.xml new file mode 100644 index 00000000000..300246ae88c --- /dev/null +++ b/test/metadata/adapter.xml @@ -0,0 +1,318 @@ + + + + + + + 192.168.131.168 + hostip + + + 2 + globalzoneid + + + 7 + globalserviceofferingid + + + 5 + globaldiskofferingid + + + 2 + globaltemplateid + + + XenServer + globalhypervisortype + + + 6 + globalnetworkofferingid + + + 204 + globalnetworkid + + + + + 192.168.131.168 + db + + + 192.168.131.168 + ms1 + + + 192.168.130.199 + ms2 + + + root + dbUserName + + + + dbPassword + + + 72.52.126.11 + dns1 + + + 72.52.126.12 + dns2 + + + 192.168.10.253 + internaldns1 + + + 192.168.10.254 + internaldns2 + + + 4 + mediumglobalserviceofferingid + + + 6 + mediumglobaldiskofferingid + + + 3 + globalzoneid1 + + + ZONE1 + globalzonename + + + 3 + globaltemplateid_passwordenabled + + + 205 + globalisoid + + + http://172.16.0.220/images/sumita/iso/ubuntu-9.04-server-amd64.iso + globalisourl + + + http://172.16.0.220/template/5d67394c-4efd-4b62-966b-51aa53b35277.vhd + globaltemplateurl + + + ../metadata/func/commands + apicommands + + + root + xenusername + + + password + xenpassword + + + 192.168.161.21 + secondary_storage_ip + + + /export/regression/secondary + secondary_storage_dir + + + 13 + flatnetworkserviceofferingid + + + 12 + flatnetworkdiskofferingid + + + + + + ../metadata/func/sanity.xml + SANITY TEST + + + + com.cloud.test.regression.SanityTest + ../metadata/func/regression.xml + REGRESSION TEST + + + + ../metadata/func/templatedwnldstress.xml + TEMPLATE DOWNLOAD STRESS TEST + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/metadata/delegatedAdmin/delegated_admin_cleanup.xml b/test/metadata/delegatedAdmin/delegated_admin_cleanup.xml new file mode 100644 index 00000000000..0f2f73f6798 --- /dev/null +++ b/test/metadata/delegatedAdmin/delegated_admin_cleanup.xml @@ -0,0 +1,108 @@ + + + + + registerUserKeys + + + id + 2 + + + + + apikey + apikey + + + secretkey + secretkey + + + + + + listDomains + true + + + name + 0-1 + + + + + id + level1domain1id + + + + + + + listDomains + true + + + name + 0-2 + + + + + id + level1domain2id + + + + + + deleteUser + + + id + rootadmin1id + + + + + + deleteUser + + + id + rootadmin2id + + + + + + deleteDomain + + + id + level1domain1id + + + cleanup + true + + + + + + deleteDomain + + + id + level1domain2id + + + cleanup + true + + + + + + \ No newline at end of file diff --git a/test/metadata/delegatedAdmin/delegated_admin_createusers.xml b/test/metadata/delegatedAdmin/delegated_admin_createusers.xml new file mode 100644 index 00000000000..5bb0879b16d --- /dev/null +++ b/test/metadata/delegatedAdmin/delegated_admin_createusers.xml @@ -0,0 +1,294 @@ + + + + + + + createDomain + + + name + 0-1 + + + + + id + level1domain1id + + + + + + createDomain + + + name + 0-2 + + + + + id + level1domain2id + + + + + + createDomain + + + name + 0-1-1 + + + parentdomainid + level1domain1id + + + + + id + level2domain1id + + + + + + createDomain + + + name + 0-2-1 + + + parentdomainid + level1domain2id + + + + + id + level2domain2id + + + + + + + + createUser + + + username + + + password + 123 + + + firstname + 123 + + + lastname + 123 + + + email + 123@gmail.com + + + accounttype + 1 + + + + + id + rootadmin1id + + + account + rootadmin1account + + + + + + + createUser + + + username + + + password + 123 + + + firstname + 123 + + + lastname + 123 + + + email + 123@gmail.com + + + accounttype + 1 + + + + + id + rootadmin2id + + + account + rootadmin2account + + + + + + + + createUser + + + username + + + password + 123 + + + firstname + 123 + + + lastname + 123 + + + email + 123@gmail.com + + + accounttype + 2 + + + domainid + level1domain1id + + + + + id + domain11adminid + + + account + domain11adminaccount + + + + + + + + createUser + + + username + + + password + 123 + + + firstname + 123 + + + lastname + 123 + + + email + 123@gmail.com + + + accounttype + 2 + + + domainid + level1domain2id + + + + + id + domain12adminid + + + account + domain12adminaccount + + + + + + + createUser + + + username + + + password + 123 + + + firstname + 123 + + + lastname + 123 + + + email + 123@gmail.com + + + accounttype + 2 + + + domainid + level2domain1id + + + + + id + domain21adminid + + + account + domain21adminaccount + + + + + + \ No newline at end of file diff --git a/test/metadata/delegatedAdmin/delegated_admin_verify_part1.xml b/test/metadata/delegatedAdmin/delegated_admin_verify_part1.xml new file mode 100644 index 00000000000..69f5b65fe37 --- /dev/null +++ b/test/metadata/delegatedAdmin/delegated_admin_verify_part1.xml @@ -0,0 +1,402 @@ + + + + registerUserKeys + + + id + userid1 + + + + + apikey + apikey + + + secretkey + secretkey + + + + + + + deployVirtualMachine + true + + + zoneid + globalzoneid + + + templateid + globaltemplateid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + + + id + vmid + + + + + + + + createVolume + true + + + name + + + zoneid + globalzoneid + + + diskofferingid + globaldiskofferingid + + + + + id + volumeid + + + + + + + + createTemplate + true + + + volumeid + volumeid + + + name + + + displaytext + newtext + + + osTypeId + 1 + + + + + id + privatetemplateid + + + + + + + registerTemplate + Register template + true + + + name + + + displaytext + + + url + globaltemplateurl + + + zoneid + globalzoneid + + + ostypeid + 1 + + + format + vhd + + + + + id + registeredtemplateid + + + + + + + + registerIso + true + Register iso + + + name + + + displaytext + + + url + globalisourl + + + ostypeid + 53 + + + zoneid + globalzoneid + + + + + id + isoid + + + + + + + createSnapshot + true + + + volumeid + volumeid + + + + + id + snapshotid + + + + + + createSnapshotPolicy + true + + + volumeid + volumeid + + + intervaltype + hourly + + + schedule + 10 + + + maxsnaps + 4 + + + timezone + Africa/Casablanca + + + + + id + snapshotpolicyid + + + + + + + + associateIpAddress + true + Associate ip address + + + zoneid + globalzoneid + + + + + ipaddress + ipaddress + + + + + + + + createPortForwardingService + Create port forwarding service + true + + + name + + + description + none + + + + + id + pfgroupid + + + + + + createPortForwardingService + Create port forwarding service + true + + + name + + + description + none + + + + + id + pfgroupid1 + + + + + + createPortForwardingServiceRule + Create port forwarding service rule + true + + + publicport + 22 + + + privateport + 22 + + + portforwardingserviceid + pfgroupid + + + + + id + pfruleid + + + + + + + + createLoadBalancerRule + Create load balancer rule + true + + + name + + + publicip + ipaddress + + + privateport + + + publicport + + + algorithm + roundrobin + + + + + id + lbid + + + + + + + createLoadBalancerRule + Create load balancer rule + true + + + name + + + publicip + ipaddress + + + privateport + + + publicport + + + algorithm + roundrobin + + + + + id + lbid1 + + + + + + assignToLoadBalancerRule + Assign to load balancer + true + + + id + lbid + + + virtualmachineid + vmid + + + + + \ No newline at end of file diff --git a/test/metadata/delegatedAdmin/delegated_admin_verify_part2.xml b/test/metadata/delegatedAdmin/delegated_admin_verify_part2.xml new file mode 100644 index 00000000000..e30d3ad7077 --- /dev/null +++ b/test/metadata/delegatedAdmin/delegated_admin_verify_part2.xml @@ -0,0 +1,934 @@ + + + + registerUserKeys + + + id + userid2 + + + + + apikey + apikey + + + secretkey + secretkey + + + + + + + + rebootVirtualMachine + Reboot virtual machine + true + + + id + vmid + + + + + + startVirtualMachine + Start virtual machine + true + + + id + vmid + + + + + + stopVirtualMachine + Stop virtual machine + true + + + id + vmid + + + + + + resetPasswordForVirtualMachine + Reset password for virtual machine + true + + + id + vmid + + + + + + changeServiceForVirtualMachine + Change service offering for virtual machine + true + + + id + vmid + + + serviceofferingid + 2 + + + + + + updateVirtualMachine + Update virtual machine + true + + + id + vmid + + + haenable + true + + + + + + listVirtualMachines + List virtual machines + true + + + id + vmid + + + + + + deployVirtualMachine + true + + + zoneid + globalzoneid + + + templateid + globaltemplateid + + + serviceofferingid + 1 + + + diskofferingid + globaldiskofferingid + + + domainid + domainid1 + + + account + account1 + + + + + + + + listVolumes + List volumes + true + + + id + volumeid + + + + + + attachVolume + Attach volume + true + + + id + volumeid + + + virtualmachineid + vmid + + + + + + detachVolume + Detach volume + true + + + id + volumeid + + + + + + createVolume + Creating volume + true + + + name + + + zoneid + globalzoneid + + + diskofferingid + globaldiskofferingid + + + domainid + domainid1 + + + account + account1 + + + + + + + + listSnapshots + List snapshots + true + + + id + snapshotid + + + + + + createSnapshot + Creating snapshot + true + + + volumeid + volumeid + + + domainid + domainid1 + + + account + account1 + + + + + + listSnapshotPolicies + Listing snapshot policies + true + + + volumeid + volumeid + + + + + + createSnapshotPolicy + true + + + volumeid + volumeid + + + intervaltype + hourly + + + schedule + 10 + + + maxsnaps + 4 + + + timezone + Africa/Casablanca + + + domainid + domainid1 + + + account + account1 + + + + + + + updateTemplate + Update template + true + + + id + privatetemplateid + + + displaytext + hello + + + + + + updateTemplatePermissions + Update template permissions + true + + + id + privatetemplateid + + + ispublic + true + + + + + + copyTemplate + Copy template + true + + + id + privatetemplateid + + + sourcezoneid + globalzoneid + + + destzoneid + globalzoneid1 + + + + + + listTemplates + List templates + true + + + id + privatetemplateid + + + + + + listTemplatePermissions + List template permissions + true + + + id + privatetemplateid + + + + + + createTemplate + Create template + true + + + volumeid + volumeid + + + name + + + displaytext + newtext + + + osTypeId + 1 + + + domainid + domainid1 + + + account + account1 + + + + + + + + updateTemplate + Update template + true + + + id + registeredtemplateid + + + displaytext + hello + + + + + + updateTemplatePermissions + Update template permissions + true + + + id + registeredtemplateid + + + ispublic + true + + + + + + copyTemplate + Copy template + true + + + id + registeredtemplateid + + + sourcezoneid + globalzoneid + + + destzoneid + globalzoneid1 + + + + + + listTemplates + List templates + true + + + id + registeredtemplateid + + + + + + listTemplatePermissions + List template permissions + true + + + id + registeredtemplateid + + + + + + + + + updateIso + Update iso + true + + + id + isoid + + + displaytext + hello + + + + + + listIsos + List isos + true + + + id + isoid + + + + + + copyIso + Copy iso + true + + + id + isoid + + + sourcezoneid + globalzoneid + + + destzoneid + globalzoneid1 + + + + + + attachIso + true + Attaching iso + + + virtualmachineid + vmid + + + id + isoid + + + + + + detachIso + true + Detaching iso + + + virtualmachineid + vmid + + + + + + + listPublicIpAddresses + true + List public ip addresses + + + ipaddress + ipaddress + + + + + + associateIpAddress + true + Associate ip address + + + zoneid + globalzoneid + + + domainid + domainid1 + + + account + account1 + + + + + + + + listPortForwardingServices + List port forwarding services + true + + + id + pfgroupid + + + + + + listPortForwardingServiceRules + List port forwarding service rule + true + + + id + pfgroupid + + + + + + listPortForwardingServicesByVm + List port forwarding services by vm + true + + + virtualmachineid + vmid + + + + + + removePortForwardingService + true + Remove port forwarding service + + + id + pfgroupid + + + virtualmachineid + vmid + + + publicip + ipaddress + + + + + + assignPortForwardingService + true + Assigning port forwarding service + + + id + pfgroupid1 + + + virtualmachineid + vmid + + + publicip + ipaddress + + + + + + createPortForwardingService + Create port forwarding service + true + + + name + + + description + none + + + domainid + domainid1 + + + account + account1 + + + + + + createPortForwardingServiceRule + Create port forwarding service rule + true + + + publicport + 222 + + + privateport + 222 + + + portforwardingserviceid + pfgroupid + + + + + + deletePortForwardingServiceRule + Delete port forwarding service rule + true + + + id + pfruleid + + + + + + + deletePortForwardingService + true + Deleting port forwarding service + + + id + pfgroupid + + + + + + + + listLoadBalancerRules + List load balancer rules + true + + + id + lbid + + + + + + listLoadBalancerRuleInstances + List load balancer rule instances + true + + + id + lbid + + + + + + removeFromLoadBalancerRule + Remove from load balancer + true + + + id + lbid + + + virtualmachineid + vmid + + + + + + assignToLoadBalancerRule + Assign to load balancer + true + + + id + lbid1 + + + virtualmachineid + vmid + + + + + + deleteLoadBalancerRule + Delete load balancer rule + true + + + id + lbid + + + + + + createLoadBalancerRule + Create load balancer rule + true + + + name + + + publicip + ipaddress + + + privateport + + + publicport + + + algorithm + roundrobin + + + + + + + + disassociateIpAddress + true + Disassociate ip address + + + ipaddress + ipaddress + + + + + deleteSnapshot + Deleting snapshot + true + + + id + snapshotid + + + + + + deleteSnapshotPolicies + Deleting snapshot policy + true + + + id + snapshotpolicyid + + + + + + deleteTemplate + Delete template + true + + + id + privatetemplateid + + + + + + deleteTemplate + Delete template + true + + + id + registeredtemplateid + + + + + + deleteVolume + Deleting volume + true + + + id + volumeid + + + + + + deleteIso + Delete iso + true + + + id + isoid + + + + + + destroyVirtualMachine + Destroy virtual machine + true + + + id + vmid + + + + + \ No newline at end of file diff --git a/test/metadata/delegatedAdmin/pickuser_domainlevel1_domainlevel2.xml b/test/metadata/delegatedAdmin/pickuser_domainlevel1_domainlevel2.xml new file mode 100644 index 00000000000..a3a356534c3 --- /dev/null +++ b/test/metadata/delegatedAdmin/pickuser_domainlevel1_domainlevel2.xml @@ -0,0 +1,104 @@ + + + + + + + listUsers + + + id + domain11adminid + + + + + id + userid1 + + + domainid + domainid1 + + + accounttype + accounttype1 + + + account + account1 + + + + + + listDomains + + + id + domainid1 + + + + + name + domainname1 + + + level + domainlevel1 + + + + + + + + listUsers + + + id + domain21adminid + + + + + id + userid2 + + + domainid + domainid2 + + + accounttype + accounttype2 + + + account + account2 + + + + + + listDomains + + + id + domainid2 + + + + + name + domainname2 + + + level + domainlevel2 + + + + + \ No newline at end of file diff --git a/test/metadata/delegatedAdmin/pickuser_domainlevel1admin_domainlevel1admin.xml b/test/metadata/delegatedAdmin/pickuser_domainlevel1admin_domainlevel1admin.xml new file mode 100644 index 00000000000..fae945a42ae --- /dev/null +++ b/test/metadata/delegatedAdmin/pickuser_domainlevel1admin_domainlevel1admin.xml @@ -0,0 +1,104 @@ + + + + + + + listUsers + + + id + domain11adminid + + + + + id + userid1 + + + domainid + domainid1 + + + accounttype + accounttype1 + + + account + account1 + + + + + + listDomains + + + id + domainid1 + + + + + name + domainname1 + + + level + domainlevel1 + + + + + + + + listUsers + + + id + domain12adminid + + + + + id + userid2 + + + domainid + domainid2 + + + accounttype + accounttype2 + + + account + account2 + + + + + + listDomains + + + id + domainid2 + + + + + name + domainname2 + + + level + domainlevel2 + + + + + \ No newline at end of file diff --git a/test/metadata/delegatedAdmin/pickuser_domainlevel1admin_rootadmin.xml b/test/metadata/delegatedAdmin/pickuser_domainlevel1admin_rootadmin.xml new file mode 100644 index 00000000000..47fbb464b16 --- /dev/null +++ b/test/metadata/delegatedAdmin/pickuser_domainlevel1admin_rootadmin.xml @@ -0,0 +1,104 @@ + + + + + + + listUsers + + + id + domain11adminid + + + + + id + userid1 + + + domainid + domainid1 + + + accounttype + accounttype1 + + + account + account1 + + + + + + listDomains + + + id + domainid1 + + + + + name + domainname1 + + + level + domainlevel1 + + + + + + + + listUsers + + + id + rootadmin1id + + + + + id + userid2 + + + domainid + domainid2 + + + accounttype + accounttype2 + + + account + account2 + + + + + + listDomains + + + id + domainid2 + + + + + name + domainname2 + + + level + domainlevel2 + + + + + \ No newline at end of file diff --git a/test/metadata/delegatedAdmin/pickuser_domainlevel2_child_domainlevel1.xml b/test/metadata/delegatedAdmin/pickuser_domainlevel2_child_domainlevel1.xml new file mode 100644 index 00000000000..61be387a198 --- /dev/null +++ b/test/metadata/delegatedAdmin/pickuser_domainlevel2_child_domainlevel1.xml @@ -0,0 +1,104 @@ + + + + + + + listUsers + + + id + domain21adminid + + + + + id + userid1 + + + domainid + domainid1 + + + accounttype + accounttype1 + + + account + account1 + + + + + + listDomains + + + id + domainid1 + + + + + name + domainname1 + + + level + domainlevel1 + + + + + + + + listUsers + + + id + domain11adminid + + + + + id + userid2 + + + domainid + domainid2 + + + accounttype + accounttype2 + + + account + account2 + + + + + + listDomains + + + id + domainid2 + + + + + name + domainname2 + + + level + domainlevel2 + + + + + \ No newline at end of file diff --git a/test/metadata/delegatedAdmin/pickuser_domainlevel2_nonchild_domainlevel1.xml b/test/metadata/delegatedAdmin/pickuser_domainlevel2_nonchild_domainlevel1.xml new file mode 100644 index 00000000000..73559e73d8a --- /dev/null +++ b/test/metadata/delegatedAdmin/pickuser_domainlevel2_nonchild_domainlevel1.xml @@ -0,0 +1,104 @@ + + + + + + + listUsers + + + id + domain21adminid + + + + + id + userid1 + + + domainid + domainid1 + + + accounttype + accounttype1 + + + account + account1 + + + + + + listDomains + + + id + domainid1 + + + + + name + domainname1 + + + level + domainlevel1 + + + + + + + + listUsers + + + id + domain12adminid + + + + + id + userid2 + + + domainid + domainid2 + + + accounttype + accounttype2 + + + account + account2 + + + + + + listDomains + + + id + domainid2 + + + + + name + domainname2 + + + level + domainlevel2 + + + + + \ No newline at end of file diff --git a/test/metadata/delegatedAdmin/pickuser_domainlevel2_rootadmin1.xml b/test/metadata/delegatedAdmin/pickuser_domainlevel2_rootadmin1.xml new file mode 100644 index 00000000000..7e2ca30641a --- /dev/null +++ b/test/metadata/delegatedAdmin/pickuser_domainlevel2_rootadmin1.xml @@ -0,0 +1,104 @@ + + + + + + + listUsers + + + id + domain21adminid + + + + + id + userid1 + + + domainid + domainid1 + + + accounttype + accounttype1 + + + account + account1 + + + + + + listDomains + + + id + domainid1 + + + + + name + domainname1 + + + level + domainlevel1 + + + + + + + + listUsers + + + id + rootadmin1id + + + + + id + userid2 + + + domainid + domainid2 + + + accounttype + accounttype2 + + + account + account2 + + + + + + listDomains + + + id + domainid2 + + + + + name + domainname2 + + + level + domainlevel2 + + + + + \ No newline at end of file diff --git a/test/metadata/delegatedAdmin/pickuser_rootadmin1_rootadmin2.xml b/test/metadata/delegatedAdmin/pickuser_rootadmin1_rootadmin2.xml new file mode 100644 index 00000000000..6db89b1d263 --- /dev/null +++ b/test/metadata/delegatedAdmin/pickuser_rootadmin1_rootadmin2.xml @@ -0,0 +1,104 @@ + + + + + + + listUsers + + + id + rootadmin1id + + + + + id + userid1 + + + domainid + domainid1 + + + accounttype + accounttype1 + + + account + account1 + + + + + + listDomains + + + id + domainid1 + + + + + name + domainname1 + + + level + domainlevel1 + + + + + + + + listUsers + + + id + rootadmin2id + + + + + id + userid2 + + + domainid + domainid2 + + + accounttype + accounttype2 + + + account + account2 + + + + + + listDomains + + + id + domainid2 + + + + + name + domainname2 + + + level + domainlevel2 + + + + + \ No newline at end of file diff --git a/test/metadata/delegatedAdmin/pickuser_rootadmin_vs_domainlevel1admin.xml b/test/metadata/delegatedAdmin/pickuser_rootadmin_vs_domainlevel1admin.xml new file mode 100644 index 00000000000..8e40722bd35 --- /dev/null +++ b/test/metadata/delegatedAdmin/pickuser_rootadmin_vs_domainlevel1admin.xml @@ -0,0 +1,104 @@ + + + + + + + listUsers + + + id + rootadmin1id + + + + + id + userid1 + + + domainid + domainid1 + + + accounttype + accounttype1 + + + account + account1 + + + + + + listDomains + + + id + domainid1 + + + + + name + domainname1 + + + level + domainlevel1 + + + + + + + + listUsers + + + id + domain11adminid + + + + + id + userid2 + + + domainid + domainid2 + + + accounttype + accounttype2 + + + account + account2 + + + + + + listDomains + + + id + domainid2 + + + + + name + domainname2 + + + level + domainlevel2 + + + + + \ No newline at end of file diff --git a/test/metadata/func/commands b/test/metadata/func/commands new file mode 100644 index 00000000000..6c999aae89e --- /dev/null +++ b/test/metadata/func/commands @@ -0,0 +1,174 @@ +updateAccount=no +listAccounts=no + +createUser=no +updateUser=no +deleteUser=no +listUsers=no +disableUser=yes +enableUser=no +disableAccount=yes +enableAccount=no +lockUser=no +lockAccount=no +deleteAccount=yes + +createDomain=no +updateDomain=no +deleteDomain=yes +listDomains=no +listDomainChildren=no + +updateResourceLimit=no +deleteResourceLimit=no +listResourceLimits=no + +deployVirtualMachine=yes +destroyVirtualMachine=yes +rebootVirtualMachine=yes +startVirtualMachine=yes +stopVirtualMachine=yes +resetPasswordForVirtualMachine=yes +changeServiceForVirtualMachine=no +updateVirtualMachine=no +recoverVirtualMachine=no +listVirtualMachines=no + +createSnapshot=yes +deleteSnapshot=yes +listSnapshots=no +listRecurringSnapshotSchedule=no +createVolumeFromSnapshot=yes +createSnapshotPolicy=no +deleteSnapshotPolicies=no +listSnapshotPolicies=no + +createTemplate=yes +registerTemplate=no +updateTemplate=no +deleteTemplate=no +listTemplates=no +updateTemplatePermissions=no +listTemplatePermissions=no +copyTemplate=yes + +attachIso=yes +detachIso=yes +listIsos=no +registerIso=no +updateIso=no +deleteIso=yes +copyIso=yes + +listOSTypes=no + +createServiceOffering=no +deleteServiceOffering=no +updateServiceOffering=no +listServiceOfferings=no + +createDiskOffering=no +updateDiskOffering=no +deleteDiskOffering=no +listDiskOfferings=no + +createVlan=no +deleteVlan=no + +createVlanIpRange=no +deleteVlanIpRange=no +listVlanIpRanges=no + +createVlanRange=no +deleteVlanRange=no +listVlanRanges=no + +associateIpAddress=yes +disassociateIpAddress=yes +listPublicIpAddresses=no +listPrivateIpAddresses=no +updatePublicIpRange=no +updatePrivateIpRange=no + +createPortForwardingServiceRule=yes +deletePortForwardingServiceRule=yes +listPortForwardingServiceRules=no +createPortForwardingService=no +deletePortForwardingService=yes +assignPortForwardingService=yes +removePortForwardingService=yes +listPortForwardingServices=no +listPortForwardingServicesByVm=no +createPortForwardingRule=no +deletePortForwardingRule=no +listPortForwardingRules=no +updatePortForwardingRule=no + +createIpForwardingRule=yes +deleteIpForwardingRule=yes +listIpForwardingRules=no + +createLoadBalancerRule=no +deleteLoadBalancerRule=yes +removeFromLoadBalancerRule=yes +assignToLoadBalancerRule=yes +listLoadBalancerRules=no +listLoadBalancerRuleInstances=no + +startRouter=yes +rebootRouter=yes +stopRouter=yes +listRouters=no + +startSystemVm=yes +rebootSystemVm=yes +stopSystemVm=yes +listSystemVms=no + +updateConfiguration=no +listConfigurations=no + +createPod=no +updatePod=no +deletePod=no +listPods=no + +createZone=no +updateZone=no +deleteZone=no +listZones=no + +listEvents=no + +listAlerts=no + +listCapacity=no + +addHost=no +reconnectHost=yes +deleteHost=no +prepareHostForMaintenance=yes +cancelHostMaintenance=yes +listHosts=no +addSecondaryStorage=no + +attachVolume=yes +detachVolume=yes +createVolume=yes +deleteVolume=no +listVolumes=no + +registerUserKeys=no + +queryAsyncJobResult=no + +listStoragePools=no +listStoragePoolsAndHosts=no +createStoragePool=no + + +createNetworkGroup=no +revokeNetworkGroupIngress=yes +authorizeNetworkGroupIngress=yes + +createNetwork=no \ No newline at end of file diff --git a/test/metadata/func/directnw_regression.xml b/test/metadata/func/directnw_regression.xml new file mode 100644 index 00000000000..1a69f53706f --- /dev/null +++ b/test/metadata/func/directnw_regression.xml @@ -0,0 +1,1892 @@ + + + + + + + + createAccount + [Create the Account and a User for the account] + + + account + nimbus-account + + + accounttype + 1 + + + domainid + 1 + + + email + admin@gmail.com + + + firstname + admin + + + lastname + adminlastname + + + username + usernameparam + + + password + password + + + + + + id + accountid + + + name + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmavailable + Unlimited + + + vmlimit + Unlimited + + + vmtotal + 0 + + + ipavailable + Unlimited + + + iptotal + 0 + + + iplimit + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + enabled + + + + + + + + + + listUsers + 5 [List the Created User in (3)] + + + account + accountname + + + + + + id + userid + + + username + usernameparam + + + firstname + admin + + + lastname + adminlastname + + + email + admin@gmail.com + + + created + createtimestamp + + + state + enabled + + + account + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + + + + + + + + createUser + 3 [Create User Command] + + + account + nimbus-account + + + accounttype + 0 + + + username + secondusernameparam + + + password + password + + + firstname + nimbus-user + + + lastname + nimbus-userlastname + + + email + nimbus-user@gmail.com + + + + + + id + seconduserid + + + username + usernameparam + + + firstname + nimbus-user + + + lastname + nimbus-userlastname + + + email + nimbus-user@gmail.com + + + account + accountname + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + created + createtimestamp + + + state + enabled + + + + + + + + + listAccounts + 950 [List the Account of the User created in (3)] + + + name + accountname + + + + + + id + accountid + + + name + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + ipavailable + Unlimited + + + iptotal + 0 + + + iplimit + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + enabled + + + + + + + + + updateUser + 6 [Update the User created in (3)] + + + id + userid + + + username + newuser + + + password + password + + + firstname + updatednimbus + + + lastname + updatednimbuslastname + + + email + updatednimbus@gmail.com + + + timezone + PST + + + apikey + userapikey + + + secretkey + usersecretkey + + + + + + id + userid + + + username + newuser + + + firstname + updatednimbus + + + lastname + updatednimbuslastname + + + email + updatednimbus@gmail.com + + + created + createtimestamp + + + state + enabled + + + account + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + timezone + PST + + + apikey + userapikey + + + secretkey + usersecretkey + + + + + + + + + listUsers + 5 [List the Updated User updated in (6)] + + + id + userid + + + + + id + userid + + + username + newuser + + + firstname + updatednimbus + + + lastname + updatednimbuslastname + + + email + updatednimbus@gmail.com + + + created + createtimestamp + + + state + enabled + + + account + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + timezone + PST + + + apikey + userapikey + + + secretkey + usersecretkey + + + + + + + + + + + + + + + disableUser + 428 [Disable the User created in (3)] + + + id + userid + + + + + id + userid + + + username + newuser + + + firstname + updatednimbus + + + lastname + updatednimbuslastname + + + email + updatednimbus@gmail.com + + + created + createtimestamp + + + state + disabled + + + account + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + timezone + PST + + + apikey + userapikey + + + secretkey + usersecretkey + + + + + + + + + enableUser + 9 [Enable the User created in (3)] + + + id + userid + + + + + id + userid + + + username + newuser + + + firstname + updatednimbus + + + lastname + updatednimbuslastname + + + email + updatednimbus@gmail.com + + + created + createtimestamp + + + state + enabled + + + account + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + timezone + PST + + + apikey + userapikey + + + secretkey + usersecretkey + + + + + + + + + disableAccount + [Lock the Account] + + + account + accountname + + + domainid + 1 + + + lock + true + + + + + id + accountid + + + name + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + ipavailable + Unlimited + + + iptotal + 0 + + + iplimit + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + locked + + + + + + + + + enableAccount + [Enable the Locked Account] + + + account + accountname + + + domainid + 1 + + + + + id + accountid + + + name + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + ipavailable + Unlimited + + + iptotal + 0 + + + iplimit + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + enabled + + + + + + + + + disableAccount + [Lock the Account] + + + account + accountname + + + domainid + 1 + + + lock + false + + + + + id + accountid + + + name + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + ipavailable + Unlimited + + + iptotal + 0 + + + iplimit + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + disabled + + + + + + + + + enableAccount + [Enable the Locked Account] + + + account + accountname + + + domainid + 1 + + + + + id + accountid + + + name + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + ipavailable + Unlimited + + + iptotal + 0 + + + iplimit + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + enabled + + + + + + + + + createDomain + 10 [Create Domain] + + + name + domainname + + + + + + name + domainname + + + id + newdomainid + + + level + 1 + + + parentdomainid + 1 + + + parentdomainname + ROOT + + + haschild + false + + + + + + + + + listDomains + 11 [List Domains] + + + name + domainname + + + + + + id + newdomainid + + + name + domainname + + + level + 1 + + + parentdomainid + 1 + + + parentdomainname + ROOT + + + haschild + false + + + + + + + + + updateDomain + 952 [Update the Domain created in (10)] + + + id + newdomainid + + + name + newdomainname + + + + + + id + newdomainid + + + name + newdomainname + + + level + 1 + + + parentdomainid + 1 + + + parentdomainname + ROOT + + + haschild + false + + + + + + + + + + listDomainChildren + - List One of the Children of the Parent Domain - + + + id + 1 + + + + + domain + 0 + + id + newdomainid + + + name + newdomainname + + + level + 1 + + + parentdomainid + 1 + + + parentdomainname + ROOT + + + haschild + false + + + + + + + + + deleteDomain + 654 [Delete Domain created in (10)] + + + id + newdomainid + + + cleanup + true + + + + + + success + true + + + + + + + + + listTemplates + 27 [List Templates - List System Template] + + + templatefilter + self + + + id + 1 + + + + + template + 0 + + id + debian50templateid + + + name + debian50templatename + + + displaytext + debian50templatedisplaytext + + + ispublic + debian50templateispublic + + + created + debian50templatecreated + + + isready + true + + + passwordenabled + debian50templatepasswordenabled + + + format + VHD + + + + isfeatured + false + + + crossZones + true + + + ostypeid + debian50templateostypeid + + + ostypename + debian50templateostypename + + + size + debian50templatesize + + + account + system + + + zoneid + globalzoneid + + + zonename + globalzonename + + + status + Download Complete + + + templatetype + SYSTEM + + + hypervisor + XenServer + + + domain + ROOT + + + domainid + 1 + + + + + + + + listTemplates + - Verify All the Parameters of the Listed Template - + + + name + debian50templatename + + + templatefilter + self + + + + template + 0 + + id + debian50templateid + + + name + debian50templatename + + + displaytext + debian50templatedisplaytext + + + ispublic + debian50templateispublic + + + created + debian50templatecreated + + + isready + true + + + isfeatured + false + + + passwordenabled + debian50templatepasswordenabled + + + crossZones + true + + + format + VHD + + + ostypeid + debian50templateostypeid + + + ostypename + debian50templateostypename + + + account + system + + + domainid + 1 + + + domain + ROOT + + + zoneid + globalzoneid + + + zonename + globalzonename + + + status + Download Complete + + + size + debian50templatesize + + + templatetype + SYSTEM + + + hypervisor + XenServer + + + + + + + + + listServiceOfferings + 28 [List the Small Instance Service Offering] + + + id + globalserviceofferingid + + + + + id + smallofferingid + + + name + smallofferingname + + + displaytext + smallofferingdisplaytext + + + cpunumber + smallofferingcpunumber + + + cpuspeed + smallofferingcpuspeed + + + memory + smallofferingmemory + + + created + smallofferingcreatetime + + + storagetype + smallofferingstoragetype + + + offerha + false + + + + + + + + listServiceOfferings + 876 [Verify the First Service Offering] + + + name + smallofferingname + + + + serviceoffering + 0 + + id + smallofferingid + + + name + smallofferingname + + + displaytext + smallofferingdisplaytext + + + cpunumber + smallofferingcpunumber + + + cpuspeed + smallofferingcpuspeed + + + memory + smallofferingmemory + + + created + smallofferingcreatetime + + + storagetype + smallofferingstoragetype + + + offerha + false + + + + + + + + + listZones + 39 [List the Global Zone with id-2] + + + zone + 0 + + id + globalzoneid + + + name + globalzonename + + + dns1 + dns1 + + + dns2 + dns2 + + + internaldns1 + internaldns1 + + + vlan + + + guestcidraddress + + + networktype + Basic + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/metadata/func/error_events.properties b/test/metadata/func/error_events.properties new file mode 100644 index 00000000000..fd894b08211 --- /dev/null +++ b/test/metadata/func/error_events.properties @@ -0,0 +1,15 @@ +# All the ERROR level events that need to be checked in EventsApiTest + +VM.CREATE=1 +VM.START=1 +VM.STOP=1 +VM.REBOOT=1 +VM.UPGRADE=1 +VM.RESETPASSWORD=1 +ROUTER.CREATE=1 +ROUTER.START=1 +ROUTER.STOP=1 +ROUTER.REBOOT=1 +NET.IPASSIGN=1 +NET.RULEADD=2 +NET.RULEDELETE=2 \ No newline at end of file diff --git a/test/metadata/func/expunge.xml b/test/metadata/func/expunge.xml new file mode 100644 index 00000000000..feb21ea5267 --- /dev/null +++ b/test/metadata/func/expunge.xml @@ -0,0 +1,1189 @@ + + + + + + createAccount + [Create the Account and a User for the account] + + + account + accountname + + + accounttype + 1 + + + domainid + 1 + + + email + admin@gmail.com + + + firstname + volumesexpungeadmin + + + lastname + volumesexpungeadminlastname + + + username + usernameparam + + + password + password + + + + + id + accountid + + + + + + + listUsers + 5 [List the Created User in (3)] + + + account + accountname + + + + + + id + userid + + + + + + + + registerUserKeys + Registering the user + + + id + userid + + + + + apikey + apikey + + + secretkey + secretkey + + + + + + + createNetwork + [Creating default network] + + + zoneid + globalzoneid + + + networkOfferingId + globalnetworkofferingid + + + account + accountname + + + domainid + 1 + + + name + defaultregressionnetwork + + + displaytext + defaultregressionnetwork + + + + + id + networkid + + + + + + + deployVirtualMachine + true + Deploy vm from regular centos template + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + accountname + + + domainid + 1 + + + displayname + VolumeExpungeTest-VM + + + group + group1 + + + networkids + networkid + + + + + id + vmid + + + name + vmname + + + + + + listVirtualMachines + List virtual machines + + + id + vmid + + + + + hostid + vm_hostid + + + + + + listHosts + List host where vm is running + + + id + vm_hostid + + + + + ipaddress + vmhost_ipaddress + + + + + + listRouters + List Routers + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + + id + router_id + + + hostid + router_hostid + + + name + routername + + + + + + listHosts + List host where domR is running + + + id + router_hostid + + + + + ipaddress + routerhost_ipaddress + + + + + + listVolumes + List data disk vm volume + + + virtualmachineid + vmid + + + type + DATADISK + + + + + id + vm_datavolumeid + + + name + vm_datavolumename + + + + + + select path from volumes + true + Getting volume path for the vm DATADISK volume + + + id + vm_datavolumeid + + + + + path + vm_datavolumepath + + + + + + listVolumes + List root disk vm volume + + + virtualmachineid + vmid + + + type + ROOT + + + + + id + vm_rootvolumeid + + + name + vm_rootvolumename + + + + + + select path from volumes + true + Getting volume path for the vm root volume + + + id + vm_rootvolumeid + + + + + path + vm_rootvolumepath + + + + + + select path from volumes + true + Getting volume path for the domR + + + instance_id + router_id + + + + + path + router_rootvolumepath + + + + + + listvdi.sh + + List VDI for vm DATADISK volume before vm is destroyed + + + h + vmhost_ipaddress + + + u + vm_datavolumepath + + + + + + listvdi.sh + + List VDI for vm ROOT volume before vm is destroyed + + + h + vmhost_ipaddress + + + u + vm_rootvolumepath + + + + + + listvdi.sh + + List VDI for router ROOT volume before domR is destroyed + + + h + routerhost_ipaddress + + + u + router_rootvolumepath + + + + + + + destroyVirtualMachine + Destroy virtual machine + + + id + vmid + + + + + + listConfigurations + Getting expunge interval value + + + name + expunge.interval + + + + + value + expunge.interval + + + + + + sleep.sh + + Sleep for expunge interval + + + s + expunge.interval + + + + + + + sleep.sh + + Sleep for another expunge interval + + + s + expunge.interval + + + + + + + listvdi.sh + true + + List VDI for vm DATADISK volume before vm is destroyed + + + h + vmhost_ipaddress + + + u + vm_datavolumepath + + + + + + listvdi.sh + true + + List VDI for vm ROOT volume before vm is destroyed + + + h + vmhost_ipaddress + + + u + vm_rootvolumepath + + + + + + + + createVolume + true + Creating a volume + + + name + + + zoneid + globalzoneid + + + diskofferingid + globaldiskofferingid + + + + + id + volumeid + + + + + + attachVolume + true + Attach the Volume to an Existing VM + + + id + volumeid + + + virtualmachineid + vmid + + + + + + detachVolume + true + Detach the Volume from the VM + + + id + volumeid + + + + + + createSnapshot + true + Create snapshot from detached volume + + + volumeid + volumeid + + + + + id + snapshotid + + + path + snapshotpath + + + + + + select path from volumes + true + Getting volume path for the detached volume + + + id + volumeid + + + + + path + detached_volumepath + + + + + + listvdi.sh + + List VDI for detached volume before the volume is deleted + + + h + vmhost_ipaddress + + + u + detached_volumepath + + + + + + deleteVolume + Delete detached volume + true + + + id + volumeid + + + + + + sleep.sh + + Sleep for expunge interval + + + s + expunge.interval + + + + + + + sleep.sh + + Sleep for another expunge interval + + + s + expunge.interval + + + + + + listvdi.sh + true + + List VDI for detached volume after the volume is deleted + + + h + vmhost_ipaddress + + + u + detached_volumepath + + + + + + + listvdi.sh + + List VDI for snapshot after it's created + + + h + vmhost_ipaddress + + + u + snapshotpath + + + + + + + + stopRouter + Stop the domR + + + id + router_id + + + + + + deleteUser + Deleting the user + + + id + userid + + + + + + listvdi.sh + true + + List VDI for domR after it's destroyed as a part of account cleanup + + + h + routerhost_ipaddress + + + u + router_rootvolumepath + + + + + + listvdi.sh + true + + List VDI for snapshot after corresponding account is deleted + + + h + vmhost_ipaddress + + + u + snapshotpath + + + + + + + + + + updateConfiguration + Updating storage.cleanup.interval + + + name + storage.cleanup.interval + + + value + 60 + + + + + + ms.sh + + Restarting management server + + + h + ms1 + + + o + restart + + + + + + + ms.sh + + Restarting management server + + + h + ms2 + + + o + restart + + + + + + + deployVirtualMachine + true + Deploying virtual machine from centos template + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + accountname + + + domainid + 1 + + + displayname + ExpungeTestVM-1 + + + group + group1 + + + networkids + networkid + + + + + id + vmid + + + + + + listVolumes + + + virtualmachineid + vmid + + + type + ROOT + + + + + id + rootvolumeid + + + + + + stopVirtualMachine + Stop virtual machine + + + id + vmid + + + + + + createTemplate + Create template from root volume + + + volumeid + rootvolumeid + + + name + + + displaytext + newtext + + + osTypeId + 12 + + + + + id + privatetemplateid + + + + + + + deployVirtualMachine + Deploying virtual machine from the private template + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + privatetemplateid + + + account + admin + + + domainid + 1 + + + displayname + VMcreatedfrmTemplate + + + group + group1 + + + networkids + networkid + + + + + id + vmid1 + + + hostid + vm_hostid + + + + + + listHosts + List host where vm is running + + + id + vm_hostid + + + + + ipaddress + vmhost_ipaddress + + + + + + select install_path from template_spool_ref + true + Getting private template vdi from the db + + + template_id + privatetemplateid + + + + + install_path + template_uuid + + + + + + listvdi.sh + + List VDI for template on the xen host before vm is destroyed + + + h + vmhost_ipaddress + + + u + template_uuid + + + + + + destroyVirtualMachine + Destroy virtual machine created from the private template + + + id + vmid1 + + + + + + sleep.sh + + Sleep for storage cleanup interval + + + s + 240 + + + + + + listvdi.sh + true + + List VDI for template on the xen host after vm using template is destroyed + + + h + vmhost_ipaddress + + + u + template_uuid + + + + + + + + destroyVirtualMachine + Destroy virtual machine as a part of cleanup + + + id + vmid + + + + + + deleteTemplate + Delete private template + + + id + privatetemplateid + + + + + + updateConfiguration + Updating storage.cleanup.interval + + + name + storage.cleanup.interval + + + value + 60000 + + + + + + ms.sh + + Restarting management server + + + h + ms1 + + + o + restart + + + + + + ms.sh + + Restarting management server + + + h + ms2 + + + o + restart + + + + + + \ No newline at end of file diff --git a/test/metadata/func/external_firewall.xml b/test/metadata/func/external_firewall.xml new file mode 100644 index 00000000000..bc8a78ef6a0 --- /dev/null +++ b/test/metadata/func/external_firewall.xml @@ -0,0 +1,371 @@ + + + createAccount + Creating account + + + account + accountname + + + accounttype + 1 + + + domainid + 1 + + + email + admin@gmail.com + + + firstname + admin + + + lastname + adminlastname + + + username + usernameparam + + + password + password + + + + + id + accountid + + + + + + + createNetwork + Creating default network + + + zoneid + globalzoneid + + + networkOfferingId + globalnetworkofferingid + + + account + accountname + + + domainid + 1 + + + name + defaultregressionnetwork + + + displaytext + defaultregressionnetwork + + + + + id + networkid + + + + + + deployVirtualMachine + deploying virtual machine + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + templateid + globaltemplateid + + + account + accountname + + + domainid + 1 + + + networkids + networkid + + + + + id + vmid + + + name + vmname + + + ipaddress + vmipaddress + + + + + + + + + associateIpAddress + Associating first public ip address + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + + id + nonsourcenatpublicip1id + + + ipaddress + nonsourcenatpublicip1 + + + + + + associateIpAddress + Associating second public ip address + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + + id + nonsourcenatpublicip2id + + + ipaddress + nonsourcenatpublicip2 + + + + + + + enableStaticNat + Enable Static NAT - 1 + + + ipaddressid + nonsourcenatpublicip1id + + + virtualmachineid + vmid + + + + + + createIpForwardingRule + Creating Ip forwarding rule - 1 + + + ipaddressid + nonsourcenatpublicip1id + + + startPort + 22 + + + endPort + 22 + + + protocol + TCP + + + + + id + ipfwdrule1 + + + + + + sleep.sh + + Sleeping for 2 mins to ensure that vm comes up for ssh test + + + s + 120 + + + + + + ssh.sh + + Ssh test for the vm + + + h + nonsourcenatpublicip1 + + + p + password + + + u + http://yahoo.com + + + + + + + + createLoadBalancerRule + Creating load balancer rule + + + name + lbname + + + publicipid + nonsourcenatpublicip2id + + + privateport + privateport + + + publicport + publicport + + + algorithm + roundrobin + + + account + accountname + + + domainid + 1 + + + + + id + lbid + + + + + + assignToLoadBalancerRule + Assigning vm to the load balancer + + + id + lbid + + + virtualmachineids + vmid + + + + + + deleteLoadBalancerRule + Deleting the load balancer + + + id + lbid + + + + + + disassociateIpAddress + Dissociating first public ip address + + + id + nonsourcenatpublicip1id + + + + + + disassociateIpAddress + Dissociating second public ip address + + + id + nonsourcenatpublicip2id + + + + + + deleteAccount + Delete account + + + id + accountid + + + + + + \ No newline at end of file diff --git a/test/metadata/func/flatnetwork.xml b/test/metadata/func/flatnetwork.xml new file mode 100644 index 00000000000..3f060091e8b --- /dev/null +++ b/test/metadata/func/flatnetwork.xml @@ -0,0 +1,515 @@ + + + createUser + Creating user + + + username + + + password + apiuser + + + firstname + apiuser + + + lastname + apiuser + + + email + apiuser@gmail.com + + + accounttype + 0 + + + + + id + userid + + + account + accountname + + + + + + registerUserKeys + Registering the user + + + id + userid + + + + + apikey + apikey + + + secretkey + secretkey + + + + + + createNetworkGroup + true + Creating a network group + + + name + accountname + + + + + + authorizeNetworkGroupIngress + Authorizing network group ingress + + + networkgroupname + accountname + + + cidrlist + 192.168.1.143/32 + + + endport + 22 + + + startport + 22 + + + protocol + tcp + + + account + accountname + + + domainid + 1 + + + + + + deployVirtualMachine + true + Deploying vm + + + zoneid + globalzoneid + + + serviceofferingid + flatnetworkserviceofferingid + + + networkgrouplist + accountname + + + templateid + globaltemplateid + + + + + id + vmid + + + ipaddress + vmip + + + + + + deployVirtualMachine + true + Deploying vm + + + zoneid + globalzoneid + + + serviceofferingid + flatnetworkserviceofferingid + + + networkgrouplist + accountname + + + templateid + globaltemplateid + + + + + id + vmid1 + + + + + + createVolume + true + Creating a volume + + + name + + + zoneid + globalzoneid + + + diskofferingid + flatnetworkdiskofferingid + + + + + id + volumeid + + + + + + + attachVolume + true + Attaching the volume + + + id + volumeid + + + virtualmachineid + vmid + + + + + + sleep.sh + + Sleep for 2 min + + + s + 120 + + + + + + ssh.sh + + Ssh test for the vm + + + h + vmip + + + p + rs-ccb35ea5 + + + + + + sleep.sh + + Sleep for 1 min + + + s + 60 + + + + + + stopVirtualMachine + true + Stopping vm + + + id + vmid + + + + + + startVirtualMachine + true + Starting vm + + + id + vmid + + + + + + rebootVirtualMachine + true + Rebooting vm + + + id + vmid + + + + + + detachVolume + true + Detaching volume + + + id + volumeid + + + + + + attachVolume + true + Attaching the volume + + + id + volumeid + + + virtualmachineid + vmid1 + + + + + + + stopVirtualMachine + true + Stopping vm + + + id + vmid + + + + + + startVirtualMachine + true + Starting vm + + + id + vmid1 + + + + + + rebootVirtualMachine + true + Rebooting vm + + + id + vmid1 + + + + + + detachVolume + true + Detaching volume + + + id + volumeid + + + + + + + deleteVolume + true + Deleting volume + + + id + volumeid + + + + + + createVolume + true + Creating a new volume + + + name + + + zoneid + globalzoneid + + + diskofferingid + flatnetworkdiskofferingid + + + + + id + volumeid + + + + + + + attachVolume + true + Attaching the volume to the vm + + + id + volumeid + + + virtualmachineid + vmid + + + + + + + revokeNetworkGroupIngress + Revoking network group igress + + + networkgroupname + accountname + + + cidrlist + 192.168.1.143/32 + + + endport + 22 + + + startport + 22 + + + protocol + tcp + + + account + accountname + + + domainid + 1 + + + + + + + ssh.sh + + true + Ssh test for the vm - should fail as network group is revoked + + + h + vmip + + + p + password + + + + + + destroyVirtualMachine + true + Destroying virutal machine + + + id + vmid + + + + + + sleep.sh + + Sleep for 2 min + + + s + 120 + + + + + + + + deleteUser + Deleting the user + + + id + userid + + + + + \ No newline at end of file diff --git a/test/metadata/func/ha.xml b/test/metadata/func/ha.xml new file mode 100644 index 00000000000..19c612f49c9 --- /dev/null +++ b/test/metadata/func/ha.xml @@ -0,0 +1,349 @@ + + + + deployVirtualMachine + Deploy ha disabled vm + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + admin + + + domainid + 1 + + + displayname + HADisabledVM + + + group + group1 + + + networkids + globalnetworkid + + + + + id + vmid + + + name + vmname + + + hostid + hostid + + + + + + deployVirtualMachine + Deploy ha enabled vm + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + admin + + + domainid + 1 + + + displayname + HAEnabledVM + + + group + group2 + + + networkids + globalnetworkid + + + + + id + vmid_ha + + + name + vmname_ha + + + hostid + hostid_ha + + + + + + + updateVirtualMachine + Update virtual machine + + + id + vmid_ha + + + haenable + true + + + + + + + listHosts + List host with ha disabled machine + + + id + hostid + + + + + ipaddress + ipaddress + + + + + + listHosts + List host with ha enabled machine + + + id + hostid_ha + + + + + ipaddress + ipaddress_ha + + + + + + + + select instance_name from vm_instance + true + Getting internal instance name for the vm with ha disabled + + + id + vmid + + + + + instance_name + instance_name + + + + + + select instance_name from vm_instance + true + Getting internal instance name for the vm with ha enabled + + + id + vmid_ha + + + + + instance_name + instance_name_ha + + + + + + + killvm.sh + + Kill ha disabled vm on the backend + + + h + ipaddress + + + n + instance_name + + + + + + killvm.sh + + Kill ha enabled vm on the backend + + + h + ipaddress_ha + + + n + instance_name_ha + + + + + + + sleep.sh + + Sleep for some time + + + s + 300 + + + + + + + listVirtualMachines + List virtual machine with ha disabled + + + id + vmid + + + + + state + Stopped + + + + + + listVirtualMachines + List virtual machine with ha enabled + + + id + vmid_ha + + + + + state + Running + + + hostid + hostid_ha + + + + + + listHosts + List host with ha enabled machine + + + id + hostid_ha + + + + + ipaddress + ipaddress_ha + + + + + + listvm.sh + + List ha enabled machine + + + h + ipaddress_ha + + + n + instance_name_ha + + + + + + + + + destroyVirtualMachine + Destroy ha disabled vm as a part of cleanup + + + id + vmid + + + + + + destroyVirtualMachine + Destroy ha enabled vm as a part of cleanup + + + id + vmid_ha + + + + + \ No newline at end of file diff --git a/test/metadata/func/iso.xml b/test/metadata/func/iso.xml new file mode 100644 index 00000000000..3cbb79f4d0c --- /dev/null +++ b/test/metadata/func/iso.xml @@ -0,0 +1,889 @@ + + + + + registerUserKeys + + + id + 2 + + + + + apikey + apikey + + + secretkey + secretkey + + + + + + deployVirtualMachine + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + admin + + + domainid + 1 + + + displayname + ISOTest-VM-1 + + + group + group1 + + + networkids + globalnetworkid + + + + + id + vmid + + + + + + attachIso + true + 869-1 + + + virtualmachineid + vmid + + + id + globalisoid + + + + + + listVirtualMachines + 869-2 + + + id + vmid + + + + + isoid + globalisoid + + + + + + + + + createAccount + [Create the Account and a User for the account] + + + account + accountname + + + accounttype + 0 + + + domainid + 1 + + + email + admin@gmail.com + + + firstname + admin + + + lastname + adminlastname + + + username + usernamevar + + + password + password + + + + + id + accountid + + + + + + + listUsers + 5 [List the Created User in (3)] + + + account + accountname + + + + + id + userid1 + + + + + + + registerUserKeys + + + id + userid1 + + + + + apikey + apikey + + + secretkey + secretkey + + + + + + attachIso + true + 870 + true + + + virtualmachineid + vmid + + + id + globalisoid + + + + + + + + registerUserKeys + + + id + 2 + + + + + apikey + apikey + + + secretkey + secretkey + + + + + + destroyVirtualMachine + + + id + vmid + + + + + + attachIso + 871 + true + + + virtualmachineid + vmid + + + id + globalisoid + + + + + + + + attachIso + 872 + true + + + virtualmachineid + 600000 + + + id + globalisoid + + + + + + + + deployVirtualMachine + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + admin + + + domainid + 1 + + + displayname + ISOTest-VM-2 + + + group + group1 + + + networkids + globalnetworkid + + + + + id + vmid + + + + + + attachIso + true + + + virtualmachineid + vmid + + + id + globalisoid + + + + + + rebootVirtualMachine + true + 1073-1 + + + id + vmid + + + + + + listVirtualMachines + 1073-2 + + + id + vmid + + + + + isoid + globalisoid + + + + + + + stopVirtualMachine + true + 1074-1 + + + id + vmid + + + + + + listVirtualMachines + 1074-2 + + + id + vmid + + + + + isoid + globalisoid + + + + + + startVirtualMachine + true + 1074-3 + + + id + vmid + + + + + + listVirtualMachines + 1074-4 + + + id + vmid + + + + + isoid + globalisoid + + + + + + + + listRouters + 35 + + + zoneid + globalzoneid + + + account + admin + + + domainid + 1 + + + + router + 0 + + id + routerid + + + + + + attachIso + 1075 + true + + + virtualmachineid + routerid + + + id + globalisoid + + + + + + + detachIso + true + 1076 + + + virtualmachineid + vmid + + + + + + + + attachIso + true + + + virtualmachineid + vmid + + + id + globalisoid + + + + + + stopVirtualMachine + true + + + id + vmid + + + + + + detachIso + true + 1077 + + + virtualmachineid + vmid + + + + + + + + destroyVirtualMachine + Destroying vm as a part of cleanup + + + id + vmid + + + + + + deployVirtualMachine + true + 1078 + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globalisoid + + + account + admin + + + domainid + 1 + + + displayname + ISOTest-VM-3 + + + group + group1 + + + networkids + globalnetworkid + + + + + id + vmid + + + isoid + globalisoid + + + + + + + destroyVirtualMachine + Destroying vm as a part of cleanup + + + id + vmid + + + + + + deployVirtualMachine + true + 1079-1 + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globalisoid + + + account + admin + + + domainid + 1 + + + displayname + ISOTest-VM-4 + + + group + group1 + + + networkids + globalnetworkid + + + + + id + vmid + + + isoid + globalisoid + + + + + + detachIso + true + 1079-2 + + + virtualmachineid + vmid + + + + + + rebootVirtualMachine + true + 1079-3 + + + id + vmid + + + + + + listVirtualMachines + 1079-4 + + + id + vmid + + + + + templateid + globalisoid + + + + + + + + + destroyVirtualMachine + Destroying vm as a part of cleanup + + + id + vmid + + + + + deployVirtualMachine + true + 1080-1 + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globalisoid + + + account + admin + + + domainid + 1 + + + displayname + ISOTest-VM-5 + + + group + group1 + + + networkids + globalnetworkid + + + + + id + vmid + + + isoid + globalisoid + + + + + + detachIso + true + 1080-2 + + + virtualmachineid + vmid + + + + + + stopVirtualMachine + true + 1080-3 + + + id + vmid + + + + + + startVirtualMachine + true + 1080-4 + + + id + vmid + + + + + + listVirtualMachines + 1080-4 + + + id + vmid + + + + + templateid + globalisoid + + + + + + + + deleteUser + Deleting user as a part of cleanup + + + id + userid1 + + + + + + destroyVirtualMachine + Destroying vm as a part of cleanup + + + id + vmid + + + + + \ No newline at end of file diff --git a/test/metadata/func/loadbalancers.xml b/test/metadata/func/loadbalancers.xml new file mode 100644 index 00000000000..195970fdb0c --- /dev/null +++ b/test/metadata/func/loadbalancers.xml @@ -0,0 +1,2018 @@ + + + + + deployVirtualMachine + [Deploy Virtual Machine in the admin account] + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + admin + + + domainid + 1 + + + displayname + LoadBalancer-VM-1 + + + group + group1 + + + networkids + globalnetworkid + + + + + id + vmid + + + + + + associateIpAddress + [Acquire a non-Source NAT IP Address for the Admin Account] + + + zoneid + globalzoneid + + + account + admin + + + domainid + 1 + + + + + ipaddress + nonsourcenatpublicip + + + + + + createLoadBalancerRule + [Create Load Balancing Rule -ve test (Private Port 0)] + true + 853 + + + name + + + publicip + nonsourcenatpublicip + + + privateport + 0 + + + publicport + 986 + + + algorithm + roundrobin + + + account + admin + + + domainid + 1 + + + + + + createLoadBalancerRule + [Create Load Balancing Rule -ve test (Private Port 65536)] + true + 853 + + + name + + + publicip + nonsourcenatpublicip + + + privateport + 65536 + + + publicport + 986 + + + algorithm + roundrobin + + + account + admin + + + domainid + 1 + + + + + + createLoadBalancerRule + [Create Load Balancing Rule -ve test (Private Port 65536)] + true + 853 + + + name + + + publicip + nonsourcenatpublicip + + + privateport + 1 + + + publicport + 0 + + + algorithm + roundrobin + + + account + admin + + + domainid + 1 + + + + + + createLoadBalancerRule + [Create Load Balancing Rule -ve test (Public Port 65536)] + true + 853 + + + name + + + publicip + nonsourcenatpublicip + + + privateport + 65535 + + + publicport + 65536 + + + algorithm + roundrobin + + + account + admin + + + domainid + 1 + + + + + + + createLoadBalancerRule + 919 [Create Load Balancing Rule - 1(Set of LB Rules for Algorithm Validation begins)] + + + name + + + publicip + nonsourcenatpublicip + + + privateport + 9191 + + + publicport + 9191 + + + algorithm + roundrobin + + + account + admin + + + domainid + 1 + + + + + + createLoadBalancerRule + 919-1 [Create Load Balancing Rule - 2] + + + name + + + publicip + nonsourcenatpublicip + + + privateport + 9192 + + + publicport + 9192 + + + algorithm + leastconn + + + account + admin + + + domainid + 1 + + + + + + createLoadBalancerRule + 919-2 [Create Load Balancing Rule - 3] + + + name + + + publicip + nonsourcenatpublicip + + + privateport + 9193 + + + publicport + 9193 + + + algorithm + source + + + account + admin + + + domainid + 1 + + + + + + createLoadBalancerRule + true + 919-3 [Create Load Balancing Rule - 4 (Set of LB Rules for Algorithm Validation ends)] + + + name + + + publicip + nonsourcenatpublicip + + + privateport + 9194 + + + publicport + 9194 + + + algorithm + roundrobinblahblah + + + account + admin + + + domainid + 1 + + + + + + + + + createLoadBalancerRule + 920-1 [Create Load Balancer Rule] + + + name + lbname + + + publicip + nonsourcenatpublicip + + + privateport + 9201 + + + publicport + 9201 + + + algorithm + source + + + account + admin + + + domainid + 1 + + + + + + createLoadBalancerRule + 920-2 [Create a Load Balancer Rule with the Same Name] + + + name + lbname + + + publicip + nonsourcenatpublicip + + + privateport + 9202 + + + publicport + 9202 + + + algorithm + source + + + account + admin + + + domainid + 1 + + + + + + + + createLoadBalancerRule + 921-1 [Create Load Balancer Rule in one account] + + + name + lbname + + + publicip + nonsourcenatpublicip + + + privateport + 921 + + + publicport + 921 + + + algorithm + source + + + account + admin + + + domainid + 1 + + + + + + createAccount + [Create the Account and a User for the account] + + + account + accountvar + + + accounttype + 0 + + + domainid + 1 + + + email + apiuser@gmail.com + + + firstname + apiuser + + + lastname + apiuserlastname + + + username + usernameparam + + + password + password + + + + + id + accountid + + + name + accountvar + + + + + + + listUsers + [List the Created User in that account] + + + account + accountvar + + + + + id + userid + + + + + + + registerUserKeys + [Register User Keys] + + + id + userid + + + + + apikey + apikey + + + secretkey + secretkey + + + + + + createNetwork + [Creating default network] + + + zoneid + globalzoneid + + + networkOfferingId + globalnetworkofferingid + + + account + accountvar + + + domainid + 1 + + + name + loadbalancersregressionnetwork + + + displaytext + loadbalancersregressionnetwork + + + + + id + networkid + + + + + + deployVirtualMachine + [Deploy Virtual Machine in that Account] + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + displayname + namefordisplay + + + group + group1 + + + account + accountvar + + + domainid + 1 + + + networkids + networkid + + + + + id + vmidtemp + + + + + + associateIpAddress + [Acquire a Non-Source NAT IP Address] + true + + + zoneid + globalzoneid + + + account + accountvar + + + domainid + 1 + + + + + ipaddress + nonsourcenatpublicip1 + + + + + + createLoadBalancerRule + [Creating a LB Rule with the same name of a rule in another account] + true + 921-2 + + + name + lbname + + + publicip + nonsourcenatpublicip1 + + + privateport + 9211 + + + publicport + 9211 + + + algorithm + source + + + account + accountvar + + + domainid + 1 + + + + + + + + createLoadBalancerRule + 922 [Create Load Balancer Rule with Non-existing ip address -ve case] + true + + + name + + + publicip + 192.168.0.5 + + + privateport + 922 + + + publicport + 922 + + + algorithm + source + + + domainid + 1 + + + account + admin + + + + + + + + createLoadBalancerRule + true + 923 [Create Load Balancer Rule with Ip Address belonging to different user -ve case] + true + + + name + + + publicip + nonsourcenatpublicip1 + + + privateport + 923 + + + publicport + 923 + + + algorithm + source + + + domainid + 1 + + + account + admin + + + + + + + associateIpAddress + [Acquire a non-Source NAT Ip address] + + + zoneid + globalzoneid + + + account + admin + + + domainid + 1 + + + + + ipaddress + nonsourcenatpublicip + + + + + + createLoadBalancerRule + 924 [Create Load Balancer Rule from non-Source NAT IP Address] + + + name + + + publicip + nonsourcenatpublicip + + + privateport + 924 + + + publicport + 924 + + + algorithm + roundrobin + + + account + admin + + + domainid + 1 + + + + + + + deleteLoadBalancerRule + [Try to a delete a Non-Existing Load Balancer Rule] + true + 925 + + + id + 10000 + + + + + + + deleteAccount + [Delete account] + + + id + accountid + + + + + + createAccount + [Create the Account and a User for the account] + + + account + accountvar + + + accounttype + 0 + + + domainid + 1 + + + email + apiuser@gmail.com + + + firstname + apiuser + + + lastname + apiuserlastname + + + username + usernameparam + + + password + password + + + + + id + accountid + + + name + accountvar + + + + + + + + listUsers + [List the Created User] + + + account + accountvar + + + + + id + userid + + + + + + + registerUserKeys + [Register User Keys] + + + id + userid + + + + + apikey + apikey + + + secretkey + secretkey + + + + + + createNetwork + [Creating default network] + + + zoneid + globalzoneid + + + networkOfferingId + globalnetworkofferingid + + + account + accountvar + + + domainid + 1 + + + name + loadbalancersregressionnetwork + + + displaytext + loadbalancersregressionnetwork + + + + + id + networkid + + + + + + deployVirtualMachine + [Deploy Virtual Machine in the account created] + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + displayname + namefordisplay + + + group + group1 + + + account + accountvar + + + networkids + networkid + + + + + + associateIpAddress + [Acquire a non-Source NAT IP Address for that account] + true + + + zoneid + globalzoneid + + + account + accountvar + + + domainid + 1 + + + + + ipaddress + nonsourcenatpublicip1 + + + + + + createLoadBalancerRule + [Create Load Balancer Rule with the acquired Ip address] + true + + + name + loadb9261 + + + publicip + nonsourcenatpublicip1 + + + privateport + 9261 + + + publicport + 9261 + + + algorithm + source + + + account + accountvar + + + domainid + 1 + + + + + id + lbid1 + + + + + + createLoadBalancerRule + [Create a Second Load Balancer Rule with the Acquired Ip Address] + true + + + name + loadb9262 + + + publicip + nonsourcenatpublicip1 + + + privateport + 9262 + + + publicport + 9262 + + + algorithm + source + + + account + accountvar + + + domainid + 1 + + + + + id + lbid2 + + + + + + createLoadBalancerRule + [Create a Third Load Balancer Rule with the Acquired Ip Address] + true + + + name + loadb9263 + + + publicip + nonsourcenatpublicip1 + + + privateport + 9263 + + + publicport + 9263 + + + algorithm + source + + + account + accountvar + + + domainid + 1 + + + + + id + lbid3 + + + + + + deleteLoadBalancerRule + 926 [Admin allowed to Delete Load Balancer Rule of another account via 8096 port] + + + id + lbid1 + + + + + + + + deleteAccount + [Delete Account as a part of Clean Up] + + + id + accountid + + + + + + createAccount + [Create the Account and a User for the account] + + + account + accountvar + + + accounttype + 0 + + + domainid + 1 + + + email + apiuser@gmail.com + + + firstname + apiuser + + + lastname + apiuserlastname + + + username + usernameparam + + + password + password + + + + + id + accountid + + + name + accountvar + + + + + + + + listUsers + [List the Created User of the Account] + + + account + accountvar + + + + + id + userid + + + + + + + registerUserKeys + [Register User Keys] + + + id + userid + + + + + apikey + apikey + + + secretkey + secretkey + + + + + + deleteLoadBalancerRule + [Admin allowed to Delete Load Balancer Rule of another account via 8080 port] + true + 927 + + + id + lbid2 + + + + + + + + deleteAccount + [Delete Account as part of Clean Up] + + + id + accountid + + + + + + createAccount + [Create the Account and a User for the account] + + + account + accountvar + + + accounttype + 0 + + + domainid + 1 + + + email + apiuser@gmail.com + + + firstname + apiuser + + + lastname + apiuserlastname + + + username + usernameparam + + + password + password + + + + + id + accountid + + + name + accountvar + + + + + + + + listUsers + [List the Created User of the account] + + + account + accountvar + + + + + id + userid + + + + + + + registerUserKeys + [Register User Keys] + + + id + userid + + + domainid + 1 + + + + + apikey + apikey + + + secretkey + secretkey + + + + + + createNetwork + [Creating default network] + + + zoneid + globalzoneid + + + networkOfferingId + globalnetworkofferingid + + + account + accountvar + + + domainid + 1 + + + name + loadbalancers-regressionnetwork + + + displaytext + loadbalancers-defaultregressionnetwork + + + + + id + networkid + + + + + + deleteLoadBalancerRule + true + 928 [Regular User can't Delete LBrule belonging to Another User] + true + + + id + lbid3 + + + + + + + deployVirtualMachine + [Deploy a Virtual Machine-1 to check multiple VMs - LB assignment] + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + admin + + + domainid + 1 + + + displayname + LoadBalancers-VM-1 + + + group + group1 + + + networkids + globalnetworkid + + + + + id + vmid1 + + + + + + deployVirtualMachine + [Deploy a Virtual Machine-2 to check multiple VMs - LB assignment] + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + admin + + + domainid + 1 + + + displayname + LoadBalancers-VM-2 + + + group + group1 + + + networkids + globalnetworkid + + + + + id + vmid2 + + + + + + associateIpAddress + [Acquire a non-Source NAT IP address] + + + zoneid + globalzoneid + + + account + admin + + + domainid + 1 + + + + + ipaddress + nonsourcenatpublicip + + + + + + createLoadBalancerRule + [Create a Load Balancer Rule] + + + name + + + publicip + nonsourcenatpublicip + + + privateport + 931 + + + publicport + 931 + + + algorithm + source + + + domainid + 1 + + + account + admin + + + + + id + lbid + + + + + + assignToLoadBalancerRule + 939 [Assign the First VM to the Load Balancing Rule] + + + id + lbid + + + virtualmachineids + vmid1 + + + + + + assignToLoadBalancerRule + 939 [Assign the Second VM to the Load Balancing Rule] + + + id + lbid + + + virtualmachineids + vmid2 + + + + + + + createLoadBalancerRule + 978 [Create Load Balancing Rule (to test the creation of 2 LB Rules with the same settings )] + + + name + + + publicip + nonsourcenatpublicip + + + privateport + 978 + + + publicport + 978 + + + algorithm + roundrobin + + + account + admin + + + domainid + 1 + + + + + + createLoadBalancerRule + 978 [Creation of Second LoadBalancer Rule should Fail] + true + + + name + + + publicip + nonsourcenatpublicip + + + privateport + 978 + + + publicport + 978 + + + algorithm + roundrobin + + + account + admin + + + domainid + 1 + + + + + + + listRouters + [Obtain the source nat IP Address - List Routers] + + + zoneid + globalzoneid + + + account + admin + + + domainid + 1 + + + + router + 0 + + publicip + sourcenatpublicip + + + + + + createLoadBalancerRule + 1017 [Create Load Balancer Rule with Source NAT IP Address] + + + name + + + publicip + sourcenatpublicip + + + privateport + 1017 + + + publicport + 1017 + + + algorithm + roundrobin + + + account + admin + + + domainid + 1 + + + + + + + + destroyVirtualMachine + [Destroy VM as a Part of Cleanup] + + + id + vmid1 + + + + + + destroyVirtualMachine + [Destroy vm as a part of cleanup] + + + id + vmid2 + + + + + + destroyVirtualMachine + [Destroy vm as a part of cleanup] + + + id + vmid + + + + + + deleteAccount + [Deleting Account as a part of cleanup] + + + id + accountid + + + + + + \ No newline at end of file diff --git a/test/metadata/func/localstorage_volume_test.xml b/test/metadata/func/localstorage_volume_test.xml new file mode 100644 index 00000000000..c9487b77eba --- /dev/null +++ b/test/metadata/func/localstorage_volume_test.xml @@ -0,0 +1,135 @@ + + + deployVirtualMachine + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + templateid + globaltemplateid + + + account + admin + + + domainid + 1 + + + + + id + vmid + + + + + + + createVolume + 1027 + true + + + account + admin + + + domainid + 1 + + + name + + + zoneid + globalzoneid + + + diskofferingid + globaldiskofferingid + + + + + + + + listVolumes + + + virtualmachineid + vmid + + + type + DATADISK + + + + + id + datadiskvolume + + + + + + detachVolume + 1032 + true + + + id + datadiskvolume + + + + + + + + + listVolumes + + + virtualmachineid + vmid + + + type + ROOT + + + + + id + rootdiskvolume + + + + + + detachVolume + 1034 + true + + + id + rootdiskvolume + + + + + + + + + \ No newline at end of file diff --git a/test/metadata/func/mgmtvmsync.xml b/test/metadata/func/mgmtvmsync.xml new file mode 100644 index 00000000000..0f089909106 --- /dev/null +++ b/test/metadata/func/mgmtvmsync.xml @@ -0,0 +1,633 @@ + + + + + deployVirtualMachine + deploy First VM test case + + + + diskofferingid + globaldiskofferingid + + + serviceofferingid + globalserviceofferingid + + + templateid + globaltemplateid + + + zoneid + globalzoneid + + + displayname + FirstVM + + + account + admin + + + domainid + 1 + + + group + group1 + + + networkids + globalnetworkid + + + + + id + vmid_1st + + + name + vmname_1st + + + hostid + hostid_1st + + + + + + deployVirtualMachine + deploy Second VM test case + + + + diskofferingid + globaldiskofferingid + + + serviceofferingid + globalserviceofferingid + + + templateid + globaltemplateid + + + zoneid + globalzoneid + + + displayname + SecondVM + + + account + admin + + + domainid + 1 + + + group + group1 + + + networkids + globalnetworkid + + + + + id + vmid_2nd + + + name + vmname_2nd + + + hostid + hostid_2nd + + + + + + + + updateVirtualMachine + HA disable first virtual machine + + + id + vmid_1st + + + displayname + HAdisabledFirstVirtualMachine + + + haenable + false + + + + + + + updateVirtualMachine + HA disable second virtual machine + + + id + vmid_2nd + + + displayname + HAdisabledSecondVirtualMachine + + + haenable + false + + + + + + + + listHosts + Obtain IP address of ha disabled VM's Host Test Case + + + id + hostid_1st + + + + + ipaddress + ipaddress_1st + + + + + + + + listHosts + Obtain IP address of ha enabled VM's Host Test Case + + + id + hostid_2nd + + + + + ipaddress + ipaddress_2nd + + + + + + + select instance_name from vm_instance + true + Obtaining the internal instance name for the ha disabled VM Test Case + + + id + vmid_1st + + + + + instance_name + instance_name_1st + + + + + + select instance_name from vm_instance + true + Obtaining the internal instance name for the ha enabled VM Test Case + + + id + vmid_2nd + + + + + instance_name + instance_name_2nd + + + + + + + + ms.sh + + Stopping management server + + + h + ms1 + + + o + stop + + + + + + + + + + killvm.sh + Kill the First HA disabled VM + + + + + n + instance_name_1st + + + + h + ipaddress_1st + + + + + + killvm.sh + Kill the Second HA disabled VM + + + + + n + instance_name_2nd + + + + h + ipaddress_2nd + + + + + + + sleep.sh + + Sleep for some time + + + s + 100 + + + + + + + + + ms.sh + + Starting management server + + + h + ms1 + + + o + start + + + + + + + sleep.sh + + Sleep for some time + + + s + 100 + + + + + + + + listVirtualMachines + Check the stopped status of First virtual machine with ha disabled + + + id + vmid_1st + + + + + state + Stopped + + + + + + listVirtualMachines + Check the stopped status of Second virtual machine with ha disabled + + + id + vmid_2nd + + + + + state + Stopped + + + + + + + + + destroyVirtualMachine + Destroy the First vm as a part of cleanup + + + id + vmid_1st + + + + + + destroyVirtualMachine + Destroy the Second vm as a part of cleanup + + + id + vmid_2nd + + + + + + + + + deployVirtualMachine + deploy VM test case + + + + diskofferingid + globaldiskofferingid + + + serviceofferingid + globalserviceofferingid + + + templateid + globaltemplateid + + + zoneid + globalzoneid + + + displayname + FirstVM + + + account + admin + + + domainid + 1 + + + group + group1 + + + networkids + globalnetworkid + + + + + id + vmid_1st + + + name + vmname_1st + + + hostid + hostid_1st + + + + + + + listHosts + Obtain IP address of the VM's Host Test Case + + + id + hostid_1st + + + + + ipaddress + ipaddress_1st + + + + + + + + select instance_name from vm_instance + true + Obtaining the internal instance name for the VM Test Case + + + id + vmid_1st + + + + + instance_name + instance_name_1st + + + + + + + ms.sh + + Stopping management server + + + h + ms1 + + + o + stop + + + + + + + + shutdown.sh + Shut down the VM Test Case + + + + + n + instance_name_1st + + + + h + ipaddress_1st + + + + + + + sleep.sh + + Sleep for some time + + + s + 60 + + + + + + + + ms.sh + + Starting management server + + + h + ms1 + + + o + start + + + + + + + sleep.sh + + Sleep for some time + + + s + 60 + + + + + + + + listVirtualMachines + Check the stopped status of virtual machine + + + id + vmid_1st + + + + + state + Stopped + + + + + + listHosts + List host that is presumed to have the VM Test Case + + + id + hostid_1st + + + + + ipaddress + ipaddress_1st + + + + + + listvm.sh + + VM Not Found on the host Test Case + true + + + h + ipaddress_1st + + + n + instance_name_1st + + + + + \ No newline at end of file diff --git a/test/metadata/func/portforwarding.xml b/test/metadata/func/portforwarding.xml new file mode 100644 index 00000000000..583b41854fe --- /dev/null +++ b/test/metadata/func/portforwarding.xml @@ -0,0 +1,1050 @@ + + + + + + createAccount + [Create the Account and a User for the account] + + + account + accountname + + + accounttype + 0 + + + domainid + 1 + + + email + pfuser@gmail.com + + + firstname + pfuser + + + lastname + pfuserlastname + + + username + usernameparam + + + password + password + + + + + id + accountid + + + name + accountname + + + + + + + listUsers + [List the Created User in (3)] + + + account + accountname + + + + + id + userid + + + + + + createNetwork + [Creating default network] + + + zoneid + globalzoneid + + + networkOfferingId + globalnetworkofferingid + + + account + accountname + + + domainid + 1 + + + name + portforwardingregressionnetwork + + + displaytext + portforwardingregressionnetwork + + + + + id + networkid + + + + + + + deployVirtualMachine + [Deploy Virtual Machine in the created Account] + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + templateid + globaltemplateid + + + account + accountname + + + domainid + 1 + + + displayname + PortForwarding-VM-1 + + + group + group1 + + + networkids + networkid + + + + + id + vmid + + + name + vmname + + + ipaddress + vmipaddress + + + + + + listRouters + [List the Created DomR for the Account] + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + + id + routerid + + + publicip + sourcenatpublicip + + + + + + associateIpAddress + [Acquire a new IP Address for the Account] + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + + ipaddress + nonsourcenatpublicip + + + + + + + createPortForwardingRule + 323 [Create Port Forwarding Rule from Source NAT ip address] + + + privateip + vmipaddress + + + ipaddress + sourcenatpublicip + + + privateport + 22 + + + publicport + 22 + + + protocol + tcp + + + virtualmachineid + vmid + + + account + accountname + + + domainid + 1 + + + + + + + createPortForwardingRule + 324 [Create Port Forwarding Rule from Non-Source NAT ip address] + + + privateip + vmipaddress + + + ipaddress + nonsourcenatpublicip + + + privateport + 22 + + + publicport + 22 + + + protocol + tcp + + + virtualmachineid + vmid + + + account + accountname + + + domainid + 1 + + + + + + + createPortForwardingRule + 325 [Create Port Forwarding Rule with TCP protocol] + + + privateip + vmipaddress + + + ipaddress + nonsourcenatpublicip + + + privateport + 23 + + + publicport + 23 + + + protocol + tcp + + + virtualmachineid + vmid + + + account + accountname + + + domainid + 1 + + + + + + + createPortForwardingRule + 326 [Create Port Forwarding Rule with UDP protocol] + + + privateip + vmipaddress + + + ipaddress + nonsourcenatpublicip + + + privateport + 345 + + + publicport + 345 + + + protocol + udp + + + virtualmachineid + vmid + + + account + accountname + + + domainid + 1 + + + + + + + + + createPortForwardingRule + 328 [Create Port Forwarding Rule with TCP protocol] + + + privateip + vmipaddress + + + ipaddress + nonsourcenatpublicip + + + privateport + 25 + + + publicport + 25 + + + protocol + tcp + + + virtualmachineid + vmid + + + account + accountname + + + domainid + 1 + + + + + + createPortForwardingRule + 328 [Create Port Forwarding Rule with same parameters with UDP protocol] + + + privateip + vmipaddress + + + ipaddress + nonsourcenatpublicip + + + privateport + 25 + + + publicport + 25 + + + protocol + udp + + + virtualmachineid + vmid + + + account + accountname + + + domainid + 1 + + + + + + + associateIpAddress + [Acquire IP Address for the account (del pf rule exercise begin) ] + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + + ipaddress + nonsourcenatpublicip1 + + + + + + createPortForwardingRule + [Create Port Forwarding Rule with the acquired IP Address] + + + privateip + vmipaddress + + + ipaddress + nonsourcenatpublicip1 + + + privateport + 25 + + + publicport + 25 + + + protocol + udp + + + virtualmachineid + vmid + + + account + accountname + + + domainid + 1 + + + + + id + portforwardingruleid1 + + + + + + deletePortForwardingRule + 329 [Delete Port Forwarding Rule] + + + id + portforwardingruleid1 + + + account + accountname + + + domainid + 1 + + + + + + listPortForwardingRules + 329 [Try to list the Deleted Port Forwarding Rules (del pf rule exercise end)] + true + + + ipaddress + nonsourcenatpublicip1 + + + + + + + + + createPortForwardingRule + [Create Port Forwarding Rule with the Non-Source NAT IP Address (del ip exercise begin)] + + + privateip + vmipaddress + + + ipaddress + nonsourcenatpublicip1 + + + privateport + 25 + + + publicport + 25 + + + protocol + udp + + + virtualmachineid + vmid + + + account + accountname + + + domainid + 1 + + + + + id + portforwardingruleid1 + + + + + + disassociateIpAddress + [Release the Non-Source NAT IP Address] + + + ipaddress + nonsourcenatpublicip1 + + + account + accountname + + + domainid + 1 + + + + + + listPortForwardingRules + 331 [Try to List the Port Forwarding Rules created from Released IP Address(del ip exercise end)] + true + + + ipaddress + nonsourcenatpublicip1 + + + + + + + + + createLoadBalancerRule + [Create Load Balancing Rule Inorder to test PF-LBrule collision (pf-lb collision exercise begin)] + + + privateip + vmipaddress + + + publicip + sourcenatpublicip + + + privateport + 220 + + + publicport + 220 + + + algorithm + roundrobin + + + name + + + account + accountname + + + domainid + 1 + + + + + id + lbid + + + + + + + assignToLoadBalancerRule + [Assign the Created LB Rule to the VM created in the Test] + + + virtualmachineids + vmid + + + id + lbid + + + + + + createPortForwardingRule + [Create Port Forwarding Rule to test PF-LBrule collision (pf-lb rule collison exercise end)] + 332 + true + + + privateip + vmipaddress + + + ipaddress + sourcenatpublicip + + + privateport + 220 + + + publicport + 220 + + + protocol + tcp + + + virtualmachineid + vmid + + + account + accountname + + + domainid + 1 + + + + + + + stopRouter + [ Stop the DomR (add new pfrule when domR is stopped exercise begin)] + + + id + routerid + + + + + + createPortForwardingRule + 336 [Create Port Forwarding Rule with the Source NAT IP Address] + + + privateip + vmipaddress + + + ipaddress + sourcenatpublicip + + + privateport + 336 + + + publicport + 336 + + + protocol + tcp + + + virtualmachineid + vmid + + + account + accountname + + + domainid + 1 + + + + + + startRouter + [Start the DomR (add new pfrule when domR is stopped exercise end)] + + + id + routerid + + + + + + + + createPortForwardingRule + 337 [Create Port Forwarding Rule with the Source NAT IP Address] + + + privateip + vmipaddress + + + ipaddress + sourcenatpublicip + + + privateport + 337 + + + publicport + 337 + + + protocol + tcp + + + virtualmachineid + vmid + + + account + accountname + + + domainid + 1 + + + + + id + portforwardingruleid_forremove + + + + + + + + stopRouter + [Stop the DomR (del pf rule exercise begin)] + + + id + routerid + + + + + + deletePortForwardingRule + 338 [Delete Port Forwarding Rule] + + + id + portforwardingruleid_forremove + + + account + accountname + + + domainid + 1 + + + + + + startRouter + [Start the DomR (del pf rule exercise end)] + + + id + routerid + + + + + + + deleteAccount + [Delete Account as part of Clean Up] + + + id + accountid + + + + + \ No newline at end of file diff --git a/test/metadata/func/private_templates.xml b/test/metadata/func/private_templates.xml new file mode 100644 index 00000000000..de622bd6378 --- /dev/null +++ b/test/metadata/func/private_templates.xml @@ -0,0 +1,893 @@ + + + + createAccount + [Create the Account and a User for the account] + + + account + accountvar + + + accounttype + 0 + + + domainid + 1 + + + email + privateuser@gmail.com + + + firstname + privateuser + + + lastname + privateuserlastname + + + username + usernameparam + + + password + password + + + + + id + accountid + + + name + accountvar + + + + + + + + listUsers + 5 [List the Created User in (3)] + + + account + accountvar + + + + + id + userid + + + + + + + registerUserKeys + + + id + userid + + + + + apikey + apikey + + + secretkey + secretkey + + + + + + createNetwork + [Creating default network] + + + zoneid + globalzoneid + + + networkOfferingId + globalnetworkofferingid + + + account + accountvar + + + domainid + 1 + + + name + privatetemplates_regressionnetwork + + + displaytext + privatetemplates_regressionnetwork + + + + + id + networkid + + + + + + deployVirtualMachine + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + accountvar + + + domainid + 1 + + + displayname + PrivateTemplate-VM-1 + + + group + group1 + + + networkids + networkid + + + + + id + vmid + + + + + + + listVolumes + + + virtualmachineid + vmid + + + type + ROOT + + + + + id + rootvolumeid + + + + + + + + stopVirtualMachine + true + + + id + vmid + + + + + + createTemplate + true + 507 + + + volumeid + rootvolumeid + + + name + privatetemplatename + + + displaytext + newtext + + + osTypeId + 12 + + + + + id + privatetemplateid + + + + + + + + startVirtualMachine + true + + + id + vmid + + + + + + createTemplate + true + true + 508 + + + volumeid + rootvolumeid + + + name + + + displaytext + newtext + + + osTypeId + 12 + + + + + + + destroyVirtualMachine + true + + + id + vmid + + + + + + createTemplate + true + true + 509 + + + volumeid + rootvolumeid + + + name + + + displaytext + newtext + + + osTypeId + 12 + + + + + + + deployVirtualMachine + true + 510 + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + privatetemplateid + + + account + accountvar + + + domainid + 1 + + + displayname + PrivateTemplate-VM-2 + + + group + group1 + + + networkids + networkid + + + + + id + vmid + + + templateid + privatetemplateid + + + + + + + listVolumes + + + virtualmachineid + vmid + + + type + ROOT + + + + + id + rootvolumeid + + + + + + stopVirtualMachine + true + + + id + vmid + + + + + + createTemplate + true + + + volumeid + rootvolumeid + + + name + privatetemplatename + + + displaytext + newtext + + + osTypeId + 12 + + + + + id + privatetemplateid + + + + + + deployVirtualMachine + true + 511 + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + privatetemplateid + + + account + accountvar + + + domainid + 1 + + + displayname + PrivateTemplate-VM-3 + + + group + group1 + + + networkids + networkid + + + + + id + vmid + + + templateid + privatetemplateid + + + + + + + createTemplate + true + + + volumeid + rootvolumeid + + + name + privatetemplatename + + + displaytext + newtext + + + osTypeId + 12 + + + + + id + privatetemplateid + + + + + + createTemplate + true + 512 + + + volumeid + rootvolumeid + + + name + privatetemplatename + + + displaytext + newtext + + + osTypeId + 12 + + + + + + + + + createAccount + [Create Different Account and a User for the account] + + + account + accountvar1 + + + accounttype + 0 + + + domainid + 1 + + + email + jack@gmail.com + + + firstname + jack12 + + + lastname + jacklastname + + + username + usernameparam1 + + + password + jack12 + + + + + id + accountid1 + + + name + accountvar1 + + + + + + + + listUsers + 5 [List the Created User in (3)] + + + account + accountvar1 + + + + + id + userid1 + + + + + + + registerUserKeys + + + id + userid1 + + + + + apikey + apikey + + + secretkey + secretkey + + + + + + createNetwork + [Creating default network] + + + zoneid + globalzoneid + + + networkOfferingId + globalnetworkofferingid + + + account + accountvar1 + + + domainid + 1 + + + name + defaultregressionnetwork + + + displaytext + defaultregressionnetwork + + + + + id + networkid + + + + + + deployVirtualMachine + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + accountvar1 + + + domainid + 1 + + + displayname + PrivateTemplate-VM-2 + + + group + group1 + + + networkids + networkid + + + + + id + vmid + + + + + + stopVirtualMachine + true + + + id + vmid + + + + + + listVolumes + + + virtualmachineid + vmid + + + type + ROOT + + + + + id + rootvolumeid1 + + + + + + createTemplate + true + 513 + + + volumeid + rootvolumeid1 + + + name + privatetemplatename + + + displaytext + newtext + + + osTypeId + 12 + + + + + + + + deleteAccount + Deleting First Account as a part of cleanup + + + id + accountvar + + + + + + deleteAccount + Deleting Second Account as a part of cleanup + + + id + accountvar1 + + + + + + + \ No newline at end of file diff --git a/test/metadata/func/regression.xml b/test/metadata/func/regression.xml new file mode 100644 index 00000000000..f5aec9f1111 --- /dev/null +++ b/test/metadata/func/regression.xml @@ -0,0 +1,4425 @@ + + + + + createAccount + [Create the Account and a User for the account] + + + account + accountname + + + accounttype + 1 + + + domainid + 1 + + + email + admin@gmail.com + + + firstname + admin + + + lastname + adminlastname + + + username + usernameparam + + + password + password + + + + + id + accountid + + + name + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmavailable + Unlimited + + + vmlimit + Unlimited + + + vmtotal + 0 + + + ipavailable + Unlimited + + + iptotal + 0 + + + iplimit + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + enabled + + + + + + + listUsers + 5 [List the Created User in (3)] + + + account + accountname + + + + + + id + userid + + + username + usernameparam + + + firstname + admin + + + lastname + adminlastname + + + email + admin@gmail.com + + + created + createtimestamp + + + state + enabled + + + account + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + + + + + + + createUser + 3 [Create User Command] + + + account + accountname + + + accounttype + 1 + + + username + secondusernameparam + + + password + password + + + firstname + nimbus-user + + + lastname + nimbus-userlastname + + + email + nimbus-user@gmail.com + + + domainid + 1 + + + + + + id + seconduserid + + + username + usernameparam + + + firstname + nimbus-user + + + lastname + nimbus-userlastname + + + email + nimbus-user@gmail.com + + + account + accountname + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + created + createtimestamp + + + state + enabled + + + + + + + listAccounts + 950 [List the Account of the User created in (3)] + + + name + accountname + + + + + + id + accountid + + + name + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + ipavailable + Unlimited + + + iptotal + 0 + + + iplimit + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + enabled + + + + + + + updateUser + 6 [Update the User created in (3)] + + + id + userid + + + username + newuser + + + password + password + + + firstname + updatednimbus + + + lastname + updatednimbuslastname + + + email + updatednimbus@gmail.com + + + timezone + PST + + + apikey + userapikey + + + secretkey + usersecretkey + + + + + + id + userid + + + username + newuser + + + firstname + updatednimbus + + + lastname + updatednimbuslastname + + + email + updatednimbus@gmail.com + + + created + createtimestamp + + + state + enabled + + + account + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + timezone + PST + + + apikey + userapikey + + + secretkey + usersecretkey + + + + + + + listUsers + 5 [List the Updated User updated in (6)] + + + id + userid + + + + + id + userid + + + username + newuser + + + firstname + updatednimbus + + + lastname + updatednimbuslastname + + + email + updatednimbus@gmail.com + + + created + createtimestamp + + + state + enabled + + + account + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + timezone + PST + + + apikey + userapikey + + + secretkey + usersecretkey + + + + + + + + + + + + + disableUser + 428 [Disable the User created in (3)] + + + id + userid + + + + + id + userid + + + username + newuser + + + firstname + updatednimbus + + + lastname + updatednimbuslastname + + + email + updatednimbus@gmail.com + + + created + createtimestamp + + + state + disabled + + + account + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + timezone + PST + + + apikey + userapikey + + + secretkey + usersecretkey + + + + + + + enableUser + 9 [Enable the User created in (3)] + + + id + userid + + + + + id + userid + + + username + newuser + + + firstname + updatednimbus + + + lastname + updatednimbuslastname + + + email + updatednimbus@gmail.com + + + created + createtimestamp + + + state + enabled + + + account + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + timezone + PST + + + apikey + userapikey + + + secretkey + usersecretkey + + + + + + + disableAccount + [Disable the Account] + + + account + accountname + + + domainid + 1 + + + lock + true + + + + + id + accountid + + + name + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + ipavailable + Unlimited + + + iptotal + 0 + + + iplimit + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + locked + + + + + + + enableAccount + [Enable the Locked Account] + + + account + accountname + + + domainid + 1 + + + + + id + accountid + + + name + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + ipavailable + Unlimited + + + iptotal + 0 + + + iplimit + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + enabled + + + + + + + disableAccount + [Lock the Account] + + + account + accountname + + + domainid + 1 + + + lock + false + + + + + id + accountid + + + name + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + ipavailable + Unlimited + + + iptotal + 0 + + + iplimit + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + disabled + + + + + + + enableAccount + [Enable the Locked Account] + + + account + accountname + + + domainid + 1 + + + + + id + accountid + + + name + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + ipavailable + Unlimited + + + iptotal + 0 + + + iplimit + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + enabled + + + + + + + + createDomain + 10 [Create Domain] + + + name + domainname + + + + + + name + domainname + + + id + newdomainid + + + level + 1 + + + parentdomainid + 1 + + + parentdomainname + ROOT + + + haschild + false + + + + + + + + + listDomains + 11 [List Domains] + + + name + domainname + + + + + + id + newdomainid + + + name + domainname + + + level + 1 + + + parentdomainid + 1 + + + parentdomainname + ROOT + + + haschild + false + + + + + + + + + updateDomain + 952 [Update the Domain created in (10)] + + + id + newdomainid + + + name + newdomainname + + + + + + id + newdomainid + + + name + newdomainname + + + level + 1 + + + parentdomainid + 1 + + + parentdomainname + ROOT + + + haschild + false + + + + + + + + + + listDomainChildren + - [List One of the Children of the Parent Domain] + + + id + 1 + + + + + domain + 0 + + id + newdomainid + + + name + newdomainname + + + level + 1 + + + parentdomainid + 1 + + + parentdomainname + ROOT + + + haschild + false + + + + + + + + + deleteDomain + 654 [Delete Domain created in (10)] + + + id + newdomainid + + + cleanup + true + + + + + + success + true + + + + + + + + + listTemplates + 27 [List Templates - List System Template] + + + templatefilter + self + + + id + 1 + + + + + template + 0 + + id + debian50templateid + + + name + debian50templatename + + + displaytext + debian50templatedisplaytext + + + ispublic + debian50templateispublic + + + created + debian50templatecreated + + + isready + true + + + passwordenabled + debian50templatepasswordenabled + + + format + VHD + + + + isfeatured + false + + + crossZones + true + + + ostypeid + debian50templateostypeid + + + ostypename + debian50templateostypename + + + size + debian50templatesize + + + account + system + + + zoneid + globalzoneid + + + zonename + globalzonename + + + status + Download Complete + + + templatetype + SYSTEM + + + hypervisor + XenServer + + + domain + ROOT + + + domainid + 1 + + + + + + + + listTemplates + - Verify All the Parameters of the Listed Template - + + + name + debian50templatename + + + templatefilter + self + + + + template + 0 + + id + debian50templateid + + + name + debian50templatename + + + displaytext + debian50templatedisplaytext + + + ispublic + debian50templateispublic + + + created + debian50templatecreated + + + isready + true + + + isfeatured + false + + + passwordenabled + debian50templatepasswordenabled + + + crossZones + true + + + format + VHD + + + ostypeid + debian50templateostypeid + + + ostypename + debian50templateostypename + + + account + system + + + domainid + 1 + + + domain + ROOT + + + zoneid + globalzoneid + + + zonename + globalzonename + + + status + Download Complete + + + size + debian50templatesize + + + templatetype + SYSTEM + + + hypervisor + XenServer + + + + + + + + + listServiceOfferings + 28 [List the Small Instance Service Offering] + + + id + globalserviceofferingid + + + + + id + smallofferingid + + + name + smallofferingname + + + displaytext + smallofferingdisplaytext + + + cpunumber + smallofferingcpunumber + + + cpuspeed + smallofferingcpuspeed + + + memory + smallofferingmemory + + + created + smallofferingcreatetime + + + storagetype + smallofferingstoragetype + + + offerha + false + + + + + + listServiceOfferings + 876 [Verify the First Service Offering] + + + name + smallofferingname + + + + serviceoffering + 0 + + id + smallofferingid + + + name + smallofferingname + + + displaytext + smallofferingdisplaytext + + + cpunumber + smallofferingcpunumber + + + cpuspeed + smallofferingcpuspeed + + + memory + smallofferingmemory + + + created + smallofferingcreatetime + + + storagetype + smallofferingstoragetype + + + offerha + false + + + + + + + + listZones + 39 [List the Global Zone with id-2] + + zone + 0 + + id + globalzoneid + + + name + globalzonename + + + dns1 + dns1 + + + dns2 + dns2 + + + internaldns1 + internaldns1 + + + vlan + + + guestcidraddress + + + networktype + Advanced + + + + + + + createNetwork + [Creating default network] + + + zoneid + globalzoneid + + + networkOfferingId + globalnetworkofferingid + + + account + accountname + + + domainid + 1 + + + name + defaultregressionnetwork + + + displaytext + defaultregressionnetwork + + + + + id + networkid + + + + + + + deployVirtualMachine + 13 + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + accountname + + + domainid + 1 + + + displayname + namefordisplay + + + group + group1 + + + networkids + networkid + + + + + id + vmid + + + name + vmname + + + ipaddress + vmipaddress + + + created + + + zoneid + globalzoneid + + + zonename + globalzonename + + + haenable + false + + + state + Running + + + account + accountname + + + templateid + globaltemplateid + + + serviceofferingid + globalserviceofferingid + + + cpunumber + smallofferingcpunumber + + + cpuspeed + smallofferingcpuspeed + + + memory + smallofferingmemory + + + displayname + namefordisplay + + + group + group1 + + + + + + + + listVirtualMachines + 957 + false + + + name + vmname + + + + + id + vmid + + + name + vmname + + + ipaddress + vmipaddress + + + created + + + zoneid + globalzoneid + + + zonename + globalzonename + + + haenable + false + + + state + Running + + + account + accountname + + + templateid + globaltemplateid + + + serviceofferingid + smallofferingid + + + serviceofferingname + smallofferingname + + + cpunumber + smallofferingcpunumber + + + cpuspeed + smallofferingcpuspeed + + + memory + smallofferingmemory + + + displayname + namefordisplay + + + group + group1 + + + + + + + listRouters + 35 + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + router + 0 + + id + routerid + + + publicip + sourcenatpublicip + + + zoneid + globalzoneid + + + zonename + globalzonename + + + dns1 + dns1 + + + dns2 + dns2 + + + networkdomain + + + gateway + + + name + routername + + + podid + + + privateip + + + privatemacaddress + + + privatenetmask + + + publicmacaddress + routerpublicmacaddress + + + guestipaddress + routeripaddress + + + guestmacaddress + routermacaddress + + + created + + + hostid + + + state + Running + + + + + + + associateIpAddress + 546 + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + + id + nonsourcenatpublicipid + + + ipaddress + nonsourcenatpublicip + + + allocated + + + zoneid + globalzoneid + + + zonename + globalzonename + + + issourcenat + false + + + + + + + + + createLoadBalancerRule + 986 + + + name + lbname + + + publicipid + nonsourcenatpublicipid + + + privateport + privateport + + + publicport + publicport + + + algorithm + roundrobin + + + account + accountname + + + domainid + 1 + + + + + id + lbid + + + name + lbname + + + privateport + privateport + + + publicport + publicport + + + algorithm + roundrobin + + + publicipid + nonsourcenatpublicipid + + + publicip + sourcenatpublicip + + + account + accountname + + + + + + + + listLoadBalancerRules + 988 + false + + + account + accountname + + + domainId + 1 + + + + + + + + assignToLoadBalancerRule + 989 + + + id + lbid + + + virtualmachineids + vmid + + + + + + + deleteLoadBalancerRule + 987 + + + id + lbid + + + + + + listLoadBalancerRules + true + + + + createLoadBalancerRule + + + name + lbname + + + publicipid + nonsourcenatpublicipid + + + privateport + privateport + + + publicport + publicport + + + algorithm + roundrobin + + + account + accountname + + + domainid + 1 + + + + + id + lbid + + + name + lbname + + + privateport + privateport + + + publicport + publicport + + + algorithm + roundrobin + + + publicipid + nonsourcenatpublicipid + + + publicip + sourcenatpublicip + + + account + accountname + + + + + + assignToLoadBalancerRule + + + id + lbid + + + virtualmachineids + vmid + + + + + + + + listLoadBalancerRuleInstances + 991 + false + + + id + lbid + + + + + + + removeFromLoadBalancerRule + 990 + + + id + lbid + + + virtualmachineids + vmid + + + account + accountname + + + + + + listLoadBalancerRuleInstances + true + + + id + lbid + + + + + + + + + + + + rebootVirtualMachine + 16 + + + id + vmid + + + + + + listVirtualMachines + + + account + accountname + + + name + vmname + + + + + state + Running + + + + + + + + stopVirtualMachine + 17 + + + id + vmid + + + + + + listVirtualMachines + + + account + accountname + + + name + vmname + + + + + state + Stopped + + + + + + + + + + listVolumes + + + virtualmachineid + vmid + + + type + ROOT + + + + + id + rootvolumeid + + + + + + listVolumes + + + virtualmachineid + vmid + + + type + DATADISK + + + + + id + datavolumeid + + + + + + + detachVolume + + + id + datavolumeid + + + + + + listVolumes + true + + + virtualmachineid + vmid + + + type + DATADISK + + + + + + + + createVolume + 1026 + + + account + accountname + + + domainid + 1 + + + name + + + zoneid + globalzoneid + + + diskofferingid + globaldiskofferingid + + + + + id + datavolumeid + + + + + + + + attachVolume + + + id + datavolumeid + + + virtualmachineid + vmid + + + + + + listVolumes + false + + + virtualmachineid + vmid + + + type + DATADISK + + + + + + + + createVolume + + + account + accountname + + + domainid + 1 + + + name + + + zoneid + globalzoneid + + + diskofferingid + globaldiskofferingid + + + + + id + datavolumeid1 + + + + + + deleteVolume + + + id + datavolumeid1 + + + + + + listVolumes + true + + + id + datavolumeid1 + + + + + + + + + createSnapshot + + + volumeid + rootvolumeid + + + + + id + snapshotid1 + + + volumeid + rootvolumeid + + + created + + + name + + + account + accountname + + + + + + listSnapshots + false + + + volumeid + rootvolumeid + + + + + + + deleteSnapshot + 24 + + + id + snapshotid1 + + + + + + + listSnapshots + 26 + true + + + volumeid + rootvolumeid + + + + + + + createSnapshot + + + volumeid + rootvolumeid + + + + + id + snapshotid1 + + + + + + createTemplate + 958 + + + snapshotid + snapshotid1 + + + name + privatetemplatename + + + displaytext + newtext + + + osTypeId + 1 + + + + + id + privatetemplateid + + + name + privatetemplatename + + + ispublic + false + + + isready + true + + + created + + + passwordenabled + false + + + + + + + listTemplates + 27 + + + name + privatetemplatename + + + templatefilter + self + + + + + id + privatetemplateid + + + name + privatetemplatename + + + ispublic + false + + + isready + true + + + created + + + passwordenabled + false + + + + + + + updateTemplate + Update template + + + id + privatetemplateid + + + displaytext + lalala + + + name + blah + + + + + + listTemplates + List updated template + + + id + privatetemplateid + + + templatefilter + self + + + + + displaytext + lalala + + + + + + + + listTemplatePermissions + list template permissions command + + + id + privatetemplateid + + + templatefilter + self + + + + + ispublic + false + + + + + + + + updateTemplatePermissions + update template permissions + + + id + privatetemplateid + + + ispublic + true + + + + + + listTemplates + List template with updated permission + + + id + privatetemplateid + + + templatefilter + self + + + + + ispublic + true + + + + + + + + deleteTemplate + 959 + + + id + privatetemplateid + + + + + + listTemplates + true + + + name + privatetemplatename + + + templatefilter + self + + + + + + + + + changeServiceForVirtualMachine + 20 + + + id + vmid + + + serviceofferingid + mediumglobalserviceofferingid + + + + + + listVirtualMachines + + + account + accountname + + + name + vmname + + + + + state + Stopped + + + serviceofferingid + 2 + + + + + + + + resetPasswordForVirtualMachine + 19 + + + id + vmid + + + + + id + vmid + + + password + + + + + + listVirtualMachines + + + account + accountname + + + name + vmname + + + + + state + Stopped + + + + + + + listVirtualMachines + + + account + accountname + + + name + vmname + + + + + state + Stopped + + + + + + startVirtualMachine + 18 + + + id + vmid + + + + + id + vmid + + + name + vmname + + + ipaddress + vmipaddress + + + created + + + zoneid + globalzoneid + + + zonename + globalzonename + + + haenable + false + + + state + Running + + + account + accountname + + + templateid + globaltemplateid + + + serviceofferingid + 2 + + + + + + listVirtualMachines + + + account + accountname + + + name + vmname + + + + + state + Running + + + + + + + updateVirtualMachine + + + id + vmid + + + haenable + true + + + + + + listVirtualMachines + 21 + + + account + accountname + + + name + vmname + + + + + haenable + true + + + + + + updateVirtualMachine + + + id + vmid + + + haenable + false + + + + + + listVirtualMachines + 21 + + + account + accountname + + + name + vmname + + + + + haenable + false + + + + + + + + + listPublicIpAddresses + 547 + + + account + accountname + + + + + + + + + + disassociateIpAddress + 548 + + + ipaddress + nonsourcenatpublicip + + + account + accountname + + + + + + + rebootRouter + 36 + + + id + routerid + + + + + + + stopRouter + 37 + + + id + routerid + + + + + + + startRouter + 38 + + + id + routerid + + + + + id + routerid + + + publicip + sourcenatpublicip + + + zoneid + globalzoneid + + + zonename + globalzonename + + + dns1 + dns1 + + + networkdomain + + + name + routername + + + podid + + + privateip + + + privatemacaddress + + + privatenetmask + + + publicmacaddress + routerpublicmacaddress + + + guestipaddress + routeripaddress + + + guestmacaddress + routermacaddress + + + created + + + hostid + + + state + Running + + + + + + + listEvents + 40 + + + account + accountname + + + + + + + destroyVirtualMachine + 14 + + + id + vmid + + + + + + listVirtualMachines + + + id + vmid + + + + + state + Destroyed + + + + + + + recoverVirtualMachine + 22 + + + id + vmid + + + + + + listVirtualMachines + + + account + accountname + + + name + vmname + + + + + state + Stopped + + + + + + + listConfigurations + 549 + false + + + + + listConfigurations + 878 + false + + + category + advanced + + + + + + + + updateConfiguration + 550 + + + name + update.wait + + + value + 35 + + + + + + listConfigurations + + + name + update.wait + + + + + value + 35 + + + + + + + + listPods + 552 + + + + + + + + + + createAccount + [Create the Account and a User for the account] + + + account + accountname1 + + + accounttype + 1 + + + domainid + 1 + + + email + admin@gmail.com + + + firstname + admin + + + lastname + adminlastname + + + username + usernameparam + + + password + password + + + + + + listAccounts + + + name + accountname1 + + + + + id + accountid1 + + + + + + updateAccount + 951 + + + account + accountname1 + + + domainid + 1 + + + newname + updatedname + + + + + + listAccounts + + + name + updatedname + + + + + id + accountid1 + + + name + updatedname + + + + + + + disableAccount + 7 + + + account + updatedname + + + domainid + 1 + + + lock + true + + + + + + + + + enableAccount + 8 + + + account + updatedname + + + domainid + 1 + + + + + + + + updateResourceLimit + 953 + + + resourcetype + 1 + + + max + 300 + + + domainid + 1 + + + + + domainid + 1 + + + domain + ROOT + + + resourcetype + 1 + + + max + 300 + + + + + + + listResourceLimits + true + 956 + + + domainid + 1 + + + resourcetype + 1 + + + + + max + 300 + + + + + + + updateResourceLimit + 954 + + + domainid + 1 + + + resourcetype + 1 + + + max + 65 + + + + + + listResourceLimits + + + domainid + 1 + + + resourcetype + 1 + + + + + max + 65 + + + + + + + + createDiskOffering + 932 + + + name + newdiskname + + + description + newdiskdesc + + + disksize + 1024 + + + displaytext + volumedisplay + + + + + id + diskid + + + domainid + 1 + + + name + newdiskname + + + displaytext + volumedisplay + + + disksize + 1099511627776 + + + + + + + + + listDiskOfferings + 934 + false + + + domainid + 1 + + + name + newdisk + + + + + + + + updateDiskOffering + + + id + diskid + + + name + newdiskname + + + + + + listDiskOfferings + + + domainid + 1 + + + name + newdiskname + + + + + name + newdiskname + + + + + + + + deleteDiskOffering + 933 + + + id + diskid + + + + + + listDiskOfferings + true + + + domainid + 1 + + + id + diskid + + + + + + + listAlerts + 750 + false + + + + + listCapacity + 974 + false + + + + + listHosts + false + 975 + + + + + + listIsos + 960 + true + + + + + createServiceOffering + 962 + + + name + + + displaytext + newoff + + + cpunumber + 1 + + + cpuspeed + 200 + + + memory + 256 + + + + + id + soid + + + + + + listServiceOfferings + + + id + soid + + + + + id + newofferingid + + + displaytext + newoff + + + cpunumber + 1 + + + cpuspeed + 200 + + + memory + 256 + + + created + + + + + + + + updateServiceOffering + 964 + + + id + newofferingid + + + name + + + displaytext + display + + + + + + + listServiceOfferings + + + id + newofferingid + + + + + id + newofferingid + + + displaytext + display + + + cpunumber + 1 + + + cpuspeed + 200 + + + memory + 256 + + + created + + + + + + + + deleteServiceOffering + 963-1 + + + id + newofferingid + + + + + + listServiceOfferings + 963-2 + true + + + id + newofferingid + + + + + + + + registerIso + Register iso + + + name + isoname + + + displaytext + isodisplay + + + url + http://172.16.0.220/images/sumita/iso/ubuntu-9.04-server-amd64.iso + + + ostypeid + 53 + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + + id + privateisoid + + + created + + + ispublic + false + + + bootable + true + + + isready + false + + + isfeatured + false + + + name + registername + + + displaytext + registerdisplay + + + + + + + listIsos + List isos + false + + + id + privateisoid + + + + + + + registerTemplate + Register template + + + name + registername + + + displaytext + registerdisplay + + + url + globaltemplateurl + + + ostypeid + 1 + + + format + vhd + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + hypervisor + globalhypervisortype + + + + + id + systemtemplateid + + + created + + + ispublic + false + + + isfeatured + false + + + passwordenabled + false + + + format + VHD + + + isready + false + + + name + registername + + + displaytext + registerdisplay + + + + + + + + listSystemVms + List system vms + + + domainid + 1 + + + + systemvm + 0 + + id + consoleid + + + publicip + + + zoneid + + + zonename + + + dns1 + dns1 + + + dns2 + dns2 + + + networkdomain + + + gateway + + + name + + + podid + + + privateip + + + privatemacaddress + + + privatenetmask + + + publicmacaddress + + + privatemacaddress + + + created + + + hostid + + + state + Running + + + activeviewersessions + 0 + + + + + + + rebootSystemVm + Reboot system vm + + + id + consoleid + + + + + + + stopSystemVm + Stop system vm + + + id + consoleid + + + + + + + startSystemVm + Start system vm + + + id + consoleid + + + + + + + + deleteIso + Delete iso + + + id + privateisoid + + + + + + listIsos + List isos + true + + + id + privateisoid + + + + + + + deleteTemplate + Delete template + + + id + systemtemplateid + + + + + + listTemplates + List templates + true + + + id + systemtemplateid + + + templatefilter + self + + + + + + + deleteAccount + Deleting account + + + id + accountid + + + + + + \ No newline at end of file diff --git a/test/metadata/func/regression_events.properties b/test/metadata/func/regression_events.properties new file mode 100644 index 00000000000..b1f3eacc4cb --- /dev/null +++ b/test/metadata/func/regression_events.properties @@ -0,0 +1,26 @@ +# All the events that need to be created as a result of execution of Regression test +VM.CREATE=2 +VM.DESTROY=2 +VM.START=2 +VM.STOP=2 +VM.REBOOT=1 +VM.UPGRADE=1 +VM.RESETPASSWORD=1 +ROUTER.CREATE=1 +ROUTER.DESTROY=1 +ROUTER.START=2 +ROUTER.STOP=2 +ROUTER.REBOOT=1 +NET.IPASSIGN=2 +NET.IPRELEASE=2 +SNAPSHOT.CREATE=1 +SNAPSHOT.DELETE=1 +PF.SERVICE.APPLY=1 +PF.SERVICE.REMOVE=1 +TEMPLATE.CREATE=2 +NET.RULEADD=4 +NET.RULEDELETE=4 +VOLUME.CREATE=6 +VOLUME.DELETE=6 +VOLUME.ATTACH=1 +VOLUME.DETACH=1 \ No newline at end of file diff --git a/test/metadata/func/regression_new.xml b/test/metadata/func/regression_new.xml new file mode 100644 index 00000000000..55270b65927 --- /dev/null +++ b/test/metadata/func/regression_new.xml @@ -0,0 +1,7654 @@ + + + + + + + + + createUser + 3 [Create User Command] + + + username + usernameparam + + + password + password + + + firstname + admin + + + lastname + adminlastname + + + email + admin@gmail.com + + + accounttype + 0 + + + + + id + userid + + + username + usernameparam + + + firstname + admin + + + lastname + adminlastname + + + email + admin@gmail.com + + + account + accountname + + + + account + usernameparam + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + created + createtimestamp + + + state + enabled + + + + + + + listAccounts + 950 [List the Account of the User created in (3)] + + + name + accountname + + + + + id + accountid + + + name + accountname + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + ipavailable + Unlimited + + + iptotal + 0 + + + iplimit + Unlimited + + + vmavailable + Unlimited + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmstopped + 0 + + + vmrunning + 0 + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + state + enabled + + + + + + + updateUser + 6 [Update the User created in (3)] + + + id + userid + + + username + newuser + + + password + password + + + firstname + updatedadmin + + + lastname + updatedadminlastname + + + email + updatedadmin@gmail.com + + + timezone + PST + + + apikey + userapikey + + + secretkey + usersecretkey + + + + + id + userid + + + username + newuser + + + firstname + updatedadmin + + + lastname + updatedadminlastname + + + email + updatedadmin@gmail.com + + + created + createtimestamp + + + state + enabled + + + account + accountname + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + timezone + PST + + + apikey + userapikey + + + secretkey + usersecretkey + + + + + + + listUsers + 5 [List the Updated User updated in (6)] + + + id + userid + + + + + id + userid + + + username + newuser + + + firstname + updatedadmin + + + lastname + updatedadminlastname + + + email + updatedadmin@gmail.com + + + account + accountname + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + state + enabled + + + created + createtimestamp + + + timezone + PST + + + apikey + userapikey + + + secretkey + usersecretkey + + + + + + + lockUser + [Lock the User created in (3)] + + + id + userid + + + + + id + userid + + + username + newuser + + + firstname + updatedadmin + + + lastname + updatedadminlastname + + + email + updatedadmin@gmail.com + + + account + accountname + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + state + locked + + + created + createtimestamp + + + timezone + PST + + + apikey + userapikey + + + secretkey + usersecretkey + + + + + + + disableUser + 428 [Disable the User created in (3)] + + + id + userid + + + + + id + userid + + + username + newuser + + + firstname + updatedadmin + + + lastname + updatedadminlastname + + + email + updatedadmin@gmail.com + + + account + accountname + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + state + disabled + + + created + createtimestamp + + + timezone + PST + + + apikey + userapikey + + + secretkey + usersecretkey + + + + + + + enableUser + 9 [Enable the User created in (3)] + + + id + userid + + + + + id + userid + + + username + newuser + + + firstname + updatedadmin + + + lastname + updatedadminlastname + + + email + updatedadmin@gmail.com + + + account + accountname + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + state + enabled + + + created + createtimestamp + + + timezone + PST + + + apikey + userapikey + + + secretkey + usersecretkey + + + + + + + createDomain + 10 [Create Domain] + + + name + domainname + + + + + name + domainname + + + id + newdomainid + + + level + 1 + + + parentdomainid + 1 + + + parentdomainname + ROOT + + + haschild + false + + + + + + + + listDomains + 11 [List Domains] + + + name + domainname + + + + + id + newdomainid + + + name + domainname + + + level + 1 + + + parentdomainid + 1 + + + parentdomainname + ROOT + + + haschild + false + + + + + + + updateDomain + 952 [Update the Domain created in (10)] + + + id + newdomainid + + + name + newdomainname + + + + + id + newdomainid + + + name + newdomainname + + + level + 1 + + + parentdomainid + 1 + + + parentdomainname + ROOT + + + haschild + false + + + + + + listDomains + - Check the Existence of the Updated Domain - + false + + + name + newdomainname + + + + + + + deleteDomain + 654 [Delete Domain created in (10)] + + + id + newdomainid + + + cleanup + true + + + + + success + true + + + + + + + listTemplates + 27 [List Templates - List System Template] + + + templatefilter + self + + + id + 1 + + + + template + 0 + + id + debian50templateid + + + name + debian50templatename + + + displaytext + debian50templatedisplaytext + + + ispublic + debian50templateispublic + + + created + debian50templatecreated + + + isready + true + + + passwordenabled + debian50templatepasswordenabled + + + format + VHD + + + bootable + false + + + isfeatured + false + + + crossZones + true + + + ostypeid + debian50templateostypeid + + + ostypename + debian50templateostypename + + + size + debian50templatesize + + + account + system + + + zoneid + globalzoneid + + + zonename + globalzonename + + + status + Download Complete + + + templatetype + SYSTEM + + + hypervisor + XenServer + + + domain + ROOT + + + domainid + 1 + + + + + + listTemplates + - Verify All the Parameters of the Listed Template - + + + name + debian50templatename + + + templatefilter + self + + + + template + 0 + + id + debian50templateid + + + name + debian50templatename + + + displaytext + debian50templatedisplaytext + + + ispublic + debian50templateispublic + + + created + debian50templatecreated + + + isready + true + + + isfeatured + false + + + passwordenabled + debian50templatepasswordenabled + + + crossZones + true + + + format + VHD + + + bootable + false + + + ostypeid + debian50templateostypeid + + + ostypename + debian50templateostypename + + + account + system + + + domainid + 1 + + + domain + ROOT + + + zoneid + globalzoneid + + + zonename + globalzonename + + + status + Download Complete + + + size + debian50templatesize + + + templatetype + SYSTEM + + + hypervisor + XenServer + + + + + + + listServiceOfferings + 28 [List the Small Instance Service Offering] + + + id + globalserviceofferingid + + + + + id + smallofferingid + + + name + smallofferingname + + + displaytext + smallofferingdisplaytext + + + cpunumber + smallofferingcpunumber + + + cpuspeed + smallofferingcpuspeed + + + memory + smallofferingmemory + + + created + smallofferingcreatetime + + + storagetype + shared + + + offerha + false + + + usevirtualnetwork + smallofferingusenetwork + + + + + + listServiceOfferings + 876 [Verify the First Service Offering] + + + name + smallofferingname + + + + serviceoffering + 0 + + id + smallofferingid + + + name + smallofferingname + + + displaytext + smallofferingdisplaytext + + + cpunumber + smallofferingcpunumber + + + cpuspeed + smallofferingcpuspeed + + + memory + smallofferingmemory + + + created + smallofferingcreatetime + + + storagetype + shared + + + offerha + false + + + usevirtualnetwork + smallofferingusenetwork + + + + + + + + listZones + 39 [List the Global Zone with id-2] + + + zone + 0 + + id + globalzoneid + + + name + globalzonename + + + dns1 + dns1 + + + dns2 + dns2 + + + internaldns1 + internaldns1 + + + vlan + + + guestcidraddress + 10.1.1.0/24 + + + networktype + Advanced + + + + + + + deployVirtualMachine + 13 [Deploy Virtual Machine] + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + accountname + + + domainid + 1 + + + displayname + Testcase13-VM + + + group + Testcase13 + + + + + id + vmid + + + name + vmname + + + created + vmcreated + + + zoneid + globalzoneid + + + zonename + globalzonename + + + ipaddress + vmipaddress + + + serviceofferingid + globalserviceofferingid + + + haenable + false + + + state + Running + + + templateid + globaltemplateid + + + templatename + + + templatedisplaytext + + + passwordenabled + false + + + serviceofferingname + smallofferingname + + + cpunumber + smallofferingcpunumber + + + cpuspeed + smallofferingcpuspeed + + + memory + smallofferingmemory + + + displayname + Testcase13-VM + + + group + Testcase13 + + + domainid + 1 + + + domain + ROOT + + + account + accountname + + + hostname + + + hostid + + + networkgrouplist + + + + + + + sleep.sh + + ** Sleep for a minute + + + s + 60 + + + + + + + listVirtualMachines + 957 [List Virtual Machines Command] + false + + + name + vmname + + + + + id + vmid + + + name + vmname + + + created + vmcreated + + + ipaddress + vmipaddress + + + state + Running + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + haenable + false + + + displayname + Testcase13-VM + + + group + Testcase13 + + + zoneid + globalzoneid + + + zonename + globalzonename + + + hostid + + + hostname + + + templateid + globaltemplateid + + + templatename + + + templatedisplaytext + + + passwordenabled + false + + + serviceofferingid + smallofferingid + + + serviceofferingname + smallofferingname + + + cpunumber + smallofferingcpunumber + + + cpuspeed + smallofferingcpuspeed + + + memory + smallofferingmemory + + + cpuused + + + networkkbsread + + + networkkbswrite + + + guestosid + + + networkgrouplist + + + rootdeviceid + 0 + + + rootdevicetype + NetworkFilesystem + + + + + + + + listRouters + 35 [List Routers] + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + router + 0 + + id + routerid + + + zoneid + globalzoneid + + + zonename + globalzonename + + + dns1 + dns1 + + + dns2 + dns2 + + + networkdomain + routernetworkdomain + + + gateway + + + name + routername + + + podid + + + privateip + + + privatemacaddress + + + privatenetmask + + + publicip + sourcenatpublicip + + + publicmacaddress + routerpublicmacaddress + + + publicnetmask + + + guestipaddress + routeripaddress + + + guestmacaddress + routermacaddress + + + guestnetmask + + + templateid + + + created + + + hostid + + + hostname + + + state + Running + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + + + + + associateIpAddress + 546 [Associate IP Address] + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + + ipaddress + nonsourcenatpublicip + + + allocated + + + zoneid + globalzoneid + + + zonename + globalzonename + + + issourcenat + false + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + forvirtualnetwork + + + vlanname + + + vlanid + + + + + + + + + createLoadBalancerRule + 986 [Create Load Balancer Rule] + + + name + lbname + + + publicip + sourcenatpublicip + + + privateport + privateport + + + publicport + publicport + + + algorithm + roundrobin + + + account + accountname + + + domainid + 1 + + + description + FirstLoadBalancingRuleCreated + + + + + id + lbid + + + name + lbname + + + description + FirstLoadBalancingRuleCreated + + + publicip + sourcenatpublicip + + + privateport + privateport + + + publicport + publicport + + + algorithm + roundrobin + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + + + + + listLoadBalancerRules + 988 [List Load Balancer Rules] + false + + + account + accountname + + + id + lbid + + + + + + + assignToLoadBalancerRule + 989 [Assign VM the Load Balancer Rule] + + + id + lbid + + + virtualmachineid + vmid + + + account + accountname + + + + + + + deleteLoadBalancerRule + 987 [Load Balancer Rule] + + + id + lbid + + + + + + listLoadBalancerRules + true + + + + createLoadBalancerRule + + Create a Second Load Balancer Rule + + + + name + lbname + + + description + SecondLoadBalancerRuleCreated + + + publicip + sourcenatpublicip + + + privateport + privateport + + + publicport + publicport + + + algorithm + roundrobin + + + account + accountname + + + domainid + 1 + + + + + id + lbid + + + name + lbname + + + description + SecondLoadBalancerRuleCreated + + + publicip + sourcenatpublicip + + + publicport + publicport + + + privateport + privateport + + + algorithm + roundrobin + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + + + + assignToLoadBalancerRule + + Assign the Second Load Balancer Rule to a VM + + + + id + lbid + + + virtualmachineid + vmid + + + account + accountname + + + + + + + listLoadBalancerRuleInstances + 991 [List LoadBalancer Rule Instances] + false + + + id + lbid + + + + + id + vmid + + + name + vmname + + + displayname + + + ipaddress + vmipaddress + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + + + + + removeFromLoadBalancerRule + 990 [Remove From Load Balancer Rule] + + + id + lbid + + + virtualmachineid + vmid + + + account + accountname + + + + + + listLoadBalancerRuleInstances + true + + + id + lbid + + + + + + + + + + + + + + + + + + + + + + + + + + + + + listVirtualMachines + 15 [List Virtual Machines] + + + account + accountname + + + name + vmname + + + + + id + vmid + + + name + vmname + + + created + + + ipaddress + vmipaddress + + + state + Running + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + haenable + false + + + displayname + Testcase13-VM + + + group + Testcase13 + + + zoneid + globalzoneid + + + zonename + globalzonename + + + hostid + + + hostname + + + templateid + globaltemplateid + + + templatename + + + templatedisplaytext + + + passwordenabled + false + + + serviceofferingid + smallofferingid + + + serviceofferingname + smallofferingname + + + cpunumber + smallofferingcpunumber + + + cpuspeed + smallofferingcpuspeed + + + memory + smallofferingmemory + + + cpuused + + + networkkbsread + + + networkkbswrite + + + guestosid + + + guestosid + rootostypeid + + + networkgrouplist + + + rootdeviceid + 0 + + + rootdevicetype + NetworkFilesystem + + + + + + + rebootVirtualMachine + 16 [Reboot Virtual Machine] + + + id + vmid + + + + + id + vmid + + + name + vmname + + + created + vmcreated + + + zoneid + globalzoneid + + + zonename + globalzonename + + + ipaddress + vmipaddress + + + serviceofferingid + globalserviceofferingid + + + haenable + false + + + state + Running + + + templateid + globaltemplateid + + + templatename + + + templatedisplaytext + + + passwordenabled + false + + + serviceofferingname + smallofferingname + + + cpunumber + smallofferingcpunumber + + + cpuspeed + smallofferingcpuspeed + + + memory + smallofferingmemory + + + displayname + Testcase13-VM + + + group + Testcase13 + + + domainid + 1 + + + domain + ROOT + + + account + accountname + + + hostname + + + hostid + + + networkgrouplist + + + + + + + + stopVirtualMachine + 17 [Stop Virtual Machine] + + + id + vmid + + + + + id + vmid + + + name + vmname + + + created + vmcreated + + + zoneid + globalzoneid + + + zonename + globalzonename + + + ipaddress + vmipaddress + + + serviceofferingid + globalserviceofferingid + + + haenable + false + + + state + Stopped + + + templateid + globaltemplateid + + + templatename + + + templatedisplaytext + + + passwordenabled + false + + + serviceofferingname + smallofferingname + + + cpunumber + smallofferingcpunumber + + + cpuspeed + smallofferingcpuspeed + + + memory + smallofferingmemory + + + displayname + Testcase13-VM + + + group + Testcase13 + + + domainid + 1 + + + domain + ROOT + + + account + accountname + + + networkgrouplist + + + + + + + + + + listVolumes + [List the ROOT Volume of VM created in (13)] + + + virtualmachineid + vmid + + + type + ROOT + + + + + id + rootvolumeid + + + name + rootvolumename + + + zoneid + globalzoneid + + + zonename + globalzonename + + + type + ROOT + + + deviceid + + + virtualmachineid + vmid + + + vmname + vmname + + + vmdisplayname + + + vmstate + Stopped + + + size + + + created + + + attached + + + state + Created + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + storagetype + shared + + + sourceid + + + sourcetype + Template + + + hypervisor + XenServer + + + storage + primary storage + + + serviceofferingid + globalserviceofferingid + + + serviceofferingname + + + serviceofferingdisplaytext + + + + + + + listVolumes + [List the DATA Volume of VM created in (13)] + + + virtualmachineid + vmid + + + type + DATADISK + + + + + id + datavolumeid + + + name + datavolumename + + + zoneid + globalzoneid + + + zonename + globalzonename + + + type + DATADISK + + + deviceid + + + virtualmachineid + vmid + + + vmname + vmname + + + vmdisplayname + + + vmstate + Stopped + + + size + + + created + + + state + Created + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + storagetype + shared + + + sourceid + + + sourcetype + DiskOffering + + + hypervisor + XenServer + + + diskofferingid + globaldiskofferingid + + + diskofferingname + + + diskofferingdisplaytext + + + storage + primary storage + + + attached + + + destroyed + false + + + + + + + detachVolume + [Detach the DATA Volume of VM created in (13)] + + + id + datavolumeid + + + + + + listVolumes + [Empty List after Detaching the Volume of VM created in (13)] + true + + + virtualmachineid + vmid + + + type + DATADISK + + + + + + + + createVolume + 1026 [Create Volume] + + + account + accountname + + + domainid + 1 + + + name + newseconddiskvolume + + + zoneid + globalzoneid + + + diskofferingid + globaldiskofferingid + + + + + id + datavolumeid + + + name + newseconddiskvolume + + + zoneid + globalzoneid + + + zonename + globalzonename + + + type + DATADISK + + + size + + + created + + + state + Created + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + storagetype + shared + + + hypervisor + None + + + sourceid + + + sourcetype + DiskOffering + + + diskofferingid + globaldiskofferingid + + + diskofferingname + + + diskofferingdisplaytext + + + storage + primary storage + + + destroyed + false + + + + + + + + attachVolume + [Attach The Created Volume in (1026) to the VM created in (13)] + + + id + datavolumeid + + + virtualmachineid + vmid + + + + + id + datavolumeid + + + name + newseconddiskvolume + + + zoneid + globalzoneid + + + zonename + globalzonename + + + type + DATADISK + + + deviceid + + + virtualmachineid + vmid + + + vmname + vmname + + + vmdisplayname + Testcase13-VM + + + vmstate + Stopped + + + size + + + created + + + state + Created + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + storagetype + shared + + + hypervisor + XenServer + + + sourceid + + + sourcetype + DiskOffering + + + diskofferingid + globaldiskofferingid + + + diskofferingname + + + diskofferingdisplaytext + + + storage + primary storage + + + attached + + + destroyed + false + + + + + + listVolumes + - Check that Data Disk Volume list is not Empty - + false + + + virtualmachineid + vmid + + + type + DATADISK + + + + + + + + createVolume + [Create the Volume, Used for Deletion Test] + + + account + accountname + + + domainid + 1 + + + name + newthirddiskvolume + + + zoneid + globalzoneid + + + diskofferingid + globaldiskofferingid + + + + + id + datavolumeid1 + + + + + + deleteVolume + - Delete the Created Volume - + + + id + datavolumeid1 + + + + + success + true + + + + + + listVolumes + - Check the Emptiness of the Volumes List - + true + + + id + datavolumeid1 + + + + + + + + + createSnapshot + [Create Snapshot from Data Volume created in (1026)] + + + volumeid + datavolumeid + + + + + id + snapshotid1 + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + snapshottype + MANUAL + + + volumeid + datavolumeid + + + volumename + newseconddiskvolume + + + volumetype + DATADISK + + + created + + + name + + + intervaltype + MANUAL + + + + + + + listSnapshots + 26 [List Snapshots] + + + volumeid + datavolumeid + + + + + id + snapshotid1 + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + snapshottype + MANUAL + + + volumeid + datavolumeid + + + volumename + newseconddiskvolume + + + volumetype + DATADISK + + + created + + + name + + + intervaltype + MANUAL + + + + + + + deleteSnapshot + 24 [Delete the Created Snapshot] + + + id + snapshotid1 + + + + + success + true + + + + + + listSnapshots + - Check the Emptiness of the Snapshots list - + true + + + volumeid + datavolumeid + + + + + + + createSnapshot + + Create Snapshot to assist Template creation + + + + volumeid + rootvolumeid + + + + + id + snapshotid1 + + + + + + createTemplate + 958 [Create Template from Snapshot] + + + snapshotid + snapshotid1 + + + name + privatetemplatename + + + displaytext + newtext + + + osTypeId + rootostypeid + + + isfeatured + true + + + ispublic + true + + + + + id + privatetemplateid + + + name + privatetemplatename + + + displaytext + privatetemplatedisplaytext + + + ispublic + true + + + created + + + isready + true + + + passwordenabled + false + + + isfeatured + true + + + crossZones + false + + + ostypeid + rootostypeid + + + ostypename + + + account + + + zoneid + globalzoneid + + + zonename + globalzonename + + + domain + ROOT + + + domainid + 1 + + + + + + + + + + registerTemplate + [Register template] + + + name + privatetemplatename + + + displaytext + privatetemplatedisplay + + + url + http://nfs1.lab.vmops.com/templates/centos53-x86_64/latest/f59f18fb-ae94-4f97-afd2-f84755767aca.vhd.bz2 + + + ostypeid + 12 + + + format + vhd + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + hypervisor + XenServer + + + + + id + privatetemplateid + + + name + privatetemplatename + + + displaytext + privatetemplatedisplay + + + ispublic + false + + + created + + + isready + false + + + passwordenabled + false + + + format + VHD + + + isfeatured + false + + + crossZones + false + + + ostypeid + 12 + + + ostypename + CentOS 5.3 (64-bit) + + + accountid + accountid + + + account + accountname + + + zoneid + globalzoneid + + + zonename + globalzonename + + + status + Processing + + + hypervisor + XenServer + + + domainid + 1 + + + isextractable + true + + + + + + + sleep.sh + + ** Sleep for five minutes + + + s + 300 + + + + + + + listTemplates + 27 [List the Registered Template] + + + name + privatetemplatename + + + templatefilter + self + + + + + id + privatetemplateid + + + name + privatetemplatename + + + displaytext + privatetemplatedisplay + + + ispublic + false + + + created + + + isready + true + + + passwordenabled + false + + + format + VHD + + + isfeatured + false + + + crossZones + false + + + ostypeid + 12 + + + ostypename + CentOS 5.3 (64-bit) + + + account + accountname + + + zoneid + globalzoneid + + + zonename + globalzonename + + + status + Download Complete + + + size + + + hypervisor + XenServer + + + domainid + 1 + + + domain + ROOT + + + + + + + updateTemplate + [Update Template registered in (958)] + + + id + privatetemplateid + + + displaytext + UpdatedTemplate + + + name + TemplateUpdated + + + + + id + privatetemplateid + + + name + TemplateUpdated + + + displaytext + UpdatedTemplate + + + ispublic + false + + + created + + + isready + false + + + passwordenabled + false + + + format + VHD + + + isfeatured + false + + + crossZones + false + + + ostypeid + 12 + + + ostypename + CentOS 5.3 (64-bit) + + + account + accountname + + + zoneid + globalzoneid + + + zonename + globalzonename + + + status + Download Complete + + + size + + + hypervisor + XenServer + + + domainid + 1 + + + domain + ROOT + + + + + + sleep.sh + + ** Sleep for four minutes + + + s + 240 + + + + + + listTemplates + [List updated template] + + + id + privatetemplateid + + + templatefilter + self + + + + + id + privatetemplateid + + + name + TemplateUpdated + + + displaytext + UpdatedTemplate + + + ispublic + false + + + created + + + isready + false + + + passwordenabled + false + + + format + VHD + + + isfeatured + false + + + crossZones + false + + + ostypeid + 12 + + + ostypename + CentOS 5.3 (64-bit) + + + account + accountname + + + zoneid + globalzoneid + + + zonename + globalzonename + + + status + Download Complete + + + size + + + hypervisor + XenServer + + + domainid + 1 + + + domain + ROOT + + + + + + + listTemplatePermissions + [List Template Permissions command] + + + id + privatetemplateid + + + templatefilter + self + + + + + id + privatetemplateid + + + ispublic + false + + + domainid + 1 + + + + + + + updateTemplatePermissions + [Update Template Permissions] + + + id + privatetemplateid + + + ispublic + true + + + + + success + true + + + + + + listTemplates + [List Template with Updated Permission] + + + id + privatetemplateid + + + templatefilter + self + + + + + ispublic + true + + + + + + + deleteTemplate + 959 [Delete Template created in (958)] + + + id + privatetemplateid + + + + + success + true + + + + + + listTemplates + - Check the Emptiness of the Template List - + true + + + name + privatetemplatename + + + templatefilter + self + + + + + + + + changeServiceForVirtualMachine + 20 [Change Service Offering for Virtual Machine] + + + id + vmid + + + serviceofferingid + mediumglobalserviceofferingid + + + + + id + vmid + + + name + vmname + + + displayname + Testcase13-VM + + + ipaddress + vmipaddress + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + created + + + state + Stopped + + + haenable + false + + + groupid + + + group + + + zoneid + globalzoneid + + + zonename + globalzonename + + + templateid + globaltemplateid + + + templatename + + + templatedisplaytext + + + passwordenabled + false + + + serviceofferingid + mediumglobalserviceofferingid + + + serviceofferingname + Medium Instance, Virtual Networking + + + forvirtualnetwork + true + + + cpunumber + 1 + + + cpuspeed + 1000 + + + memory + 1024 + + + cpuused + + + networkkbsread + + + networkkbswrite + + + guestosid + + + rootdeviceid + + + rootdevicetype + + + + + + listVirtualMachines + - Check the change in the Service Offering - + + + account + accountname + + + name + vmname + + + + + state + Stopped + + + serviceofferingid + mediumglobalserviceofferingid + + + serviceofferingname + Medium Instance, Virtual Networking + + + + + + + + + + + listVirtualMachines + + Check the Stopped status of VM that needs to be started + + + + account + accountname + + + name + vmname + + + + + state + Stopped + + + + + + startVirtualMachine + 18 [Start the Stopped VM] + + + id + vmid + + + + + id + vmid + + + name + vmname + + + displayname + Testcase13-VM + + + ipaddress + vmipaddress + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + created + + + state + Running + + + haenable + false + + + groupid + + + group + Testcase13 + + + zoneid + globalzoneid + + + zonename + globalzonename + + + hostid + + + hostname + + + templateid + globaltemplateid + + + templatename + + + templatedisplaytext + + + passwordenabled + false + + + serviceofferingid + mediumglobalserviceofferingid + + + serviceofferingname + Medium Instance, Virtual Networking + + + forvirtualnetwork + + + cpunumber + 1 + + + cpuspeed + 1000 + + + memory + 1024 + + + cpuused + + + networkkbsread + + + networkkbswrite + + + guestosid + + + rootdeviceid + + + rootdevicetype + NetworkFilesystem + + + networkgrouplist + + + + + + listVirtualMachines + + + account + accountname + + + name + vmname + + + + + id + vmid + + + name + vmname + + + displayname + Testcase13-VM + + + ipaddress + vmipaddress + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + created + + + state + Running + + + haenable + false + + + groupid + + + group + Testcase13 + + + zoneid + globalzoneid + + + zonename + globalzonename + + + hostid + + + hostname + + + templateid + globaltemplateid + + + templatename + + + templatedisplaytext + + + passwordenabled + false + + + serviceofferingid + mediumglobalserviceofferingid + + + serviceofferingname + Medium Instance, Virtual Networking + + + forvirtualnetwork + + + cpunumber + 1 + + + cpuspeed + 1000 + + + memory + 1024 + + + cpuused + + + networkkbsread + + + networkkbswrite + + + guestosid + + + rootdeviceid + + + rootdevicetype + NetworkFilesystem + + + networkgrouplist + + + + + + + updateVirtualMachine + + HA Enable on Virtual Machine + + + + id + vmid + + + haenable + true + + + + + success + true + + + + + + listVirtualMachines + 21 [Verify the Update using List VMs] + + + account + accountname + + + name + vmname + + + + + id + vmid + + + haenable + true + + + + + + updateVirtualMachine + + HA Disable on Virtual Machine + + + + id + vmid + + + haenable + false + + + + + id + vmid + + + name + vmname + + + displayname + Testcase13-VM + + + ipaddress + vmipaddress + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + created + + + state + Running + + + haenable + false + + + groupid + + + group + Testcase13 + + + zoneid + globalzoneid + + + zonename + globalzonename + + + hostid + + + hostname + + + templateid + globaltemplateid + + + templatename + + + templatedisplaytext + + + passwordenabled + false + + + serviceofferingid + mediumglobalserviceofferingid + + + serviceofferingname + Medium Instance, Virtual Networking + + + forvirtualnetwork + + + cpunumber + 1 + + + cpuspeed + 1000 + + + memory + 1024 + + + cpuused + + + networkkbsread + + + networkkbswrite + + + guestosid + + + rootdeviceid + + + rootdevicetype + NetworkFilesystem + + + networkgrouplist + + + + + + listVirtualMachines + 21 [Verify the Update using List VMs] + + + account + accountname + + + name + vmname + + + + + id + vmid + + + haenable + false + + + + + + + listPublicIpAddresses + 547 [List Public IP Addresses] + + + account + accountname + + + domainid + 1 + + + + publicipaddress + 0 + + ipaddress + + + allocated + + + zoneid + globalzoneid + + + zonename + globalzonename + + + issourcenat + true + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + forvirtualnetwork + true + + + vlanid + + + vlanname + + + isstaticnat + + + + + + + disassociateIpAddress + 548 [Disassociate IP Address] + + + ipaddress + nonsourcenatpublicip + + + account + accountname + + + + + success + true + + + + + + + rebootRouter + 36 [Reboot Router] + + + id + routerid + + + + + id + routerid + + + zoneid + globalzoneid + + + zonename + globalzonename + + + dns1 + dns1 + + + dns2 + dns2 + + + networkdomain + routernetworkdomain + + + gateway + + + name + routername + + + podid + + + hostid + + + hostname + + + privateip + + + privatemacaddress + + + privatenetmask + + + publicip + sourcenatpublicip + + + publicmacaddress + routerpublicmacaddress + + + publicnetmask + + + guestipaddress + routeripaddress + + + guestmacaddress + routermacaddress + + + guestnetmask + + + templateid + + + created + + + state + Running + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + + + + + + stopRouter + 37 [Stop Router] + + + id + routerid + + + + + id + routerid + + + zoneid + globalzoneid + + + zonename + globalzonename + + + dns1 + dns1 + + + dns2 + dns2 + + + networkdomain + routernetworkdomain + + + gateway + + + name + routername + + + podid + + + privateip + + + privatemacaddress + + + privatenetmask + + + publicip + sourcenatpublicip + + + publicmacaddress + routerpublicmacaddress + + + publicnetmask + + + guestipaddress + routeripaddress + + + guestmacaddress + routermacaddress + + + guestnetmask + + + templateid + + + created + + + state + Stopped + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + + + + + startRouter + 38 [Start Router] + + + id + routerid + + + + + id + routerid + + + zoneid + globalzoneid + + + zonename + globalzonename + + + dns1 + dns1 + + + dns2 + dns2 + + + networkdomain + routernetworkdomain + + + gateway + + + name + routername + + + podid + + + hostid + + + hostname + + + privateip + + + privatemacaddress + + + privatenetmask + + + publicip + sourcenatpublicip + + + publicmacaddress + routerpublicmacaddress + + + publicnetmask + + + guestipaddress + routeripaddress + + + guestmacaddress + routermacaddress + + + guestnetmask + + + templateid + + + created + + + state + Running + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + + + + + + listEvents + 40 [List Events] + + + account + accountname + + + + event + 0 + + id + + + username + + + type + + + level + + + description + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + created + + + state + + + parentid + + + + + + + destroyVirtualMachine + 14 [Destroy Virtual Machine] + + + id + vmid + + + + + + listVirtualMachines + - Verify the Destroyed Status of the Virtual Machine - + + + id + vmid + + + + + name + vmname + + + state + Destroyed + + + + + + + recoverVirtualMachine + 22 [ Recover Virtual Machine ] + + + id + vmid + + + + + success + true + + + + + + listVirtualMachines + - Verify the Stopped Status of the Recovered VM - + + + account + accountname + + + name + vmname + + + + + id + vmid + + + state + Stopped + + + + + + + listConfigurations + 549 [List Configurations] + + configuration + 0 + + category + + + name + + + value + + + description + + + + + + + listConfigurations + 878 [List Configurations with category parameter] + + + category + advanced + + + + configuration + 0 + + category + Advanced + + + name + + + value + + + description + + + + + + + + updateConfiguration + 550 [Update Configuration] + + + name + update.wait + + + value + 35 + + + + + success + true + + + displaytext + Successfully updated configuration value. + + + + + + listConfigurations + - Verify the Updated Configuration - + + + name + update.wait + + + + + category + Advanced + + + name + update.wait + + + value + 35 + + + description + Time to wait before alerting on a updating agent + + + + + + + + listPods + 552 [List Pods] + + + id + 2 + + + name + POD1 + + + + + id + 2 + + + name + POD1 + + + zoneid + globalzoneid + + + zonename + globalzonename + + + cidr + + + startip + + + endip + + + gateway + + + + + + + createUser + 3 [Create User] + + + username + usernamejack + + + password + jack12 + + + firstname + jack12 + + + lastname + jacklastname + + + email + jack@gmail.com + + + accounttype + 0 + + + + + id + accountid1 + + + username + usernamejack + + + firstname + jack12 + + + lastname + jacklastname + + + email + jack@gmail.com + + + created + + + state + enabled + + + account + accountname1 + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + + + + listAccounts + - List Accounts - + + + name + accountname1 + + + + + id + accountid1 + + + name + accountname1 + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + iplimit + Unlimited + + + iptotal + 0 + + + ipavailable + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + enabled + + + + + + + updateAccount + 951 [Update Account] + + + account + accountname1 + + + domainid + 1 + + + newname + updatedname + + + + + id + accountid1 + + + name + updatedname + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + iplimit + Unlimited + + + iptotal + 0 + + + ipavailable + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + enabled + + + + + + listAccounts + - Check the Presence of the Updated Account + false + + + name + updatedname + + + + + id + accountid1 + + + name + updatedname + + + + + + + lockAccount + [Lock Account] + + + account + updatedname + + + domainid + 1 + + + + + id + accountid1 + + + name + updatedname + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + iplimit + Unlimited + + + iptotal + 0 + + + ipavailable + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + locked + + + + + + + disableAccount + 7 [Disable Account] + + + account + updatedname + + + domainid + 1 + + + + + id + accountid1 + + + name + updatedname + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + iplimit + Unlimited + + + iptotal + 0 + + + ipavailable + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + disabled + + + + + + + + enableAccount + 8 [Enable Account] + + + account + updatedname + + + domainid + 1 + + + + + id + accountid1 + + + name + updatedname + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + iplimit + Unlimited + + + iptotal + 0 + + + ipavailable + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + enabled + + + + + + + + updateResourceLimit + 953 [Create using Update Resource Limit] + + + resourcetype + 1 + + + max + 300 + + + domainid + 1 + + + + + domainid + 1 + + + domain + ROOT + + + resourcetype + 1 + + + max + 300 + + + + + + + listResourceLimits + true + 956 [Verify the creation using List Resource Limits] + + + domainid + 1 + + + resourcetype + 1 + + + + + domainid + 1 + + + domain + ROOT + + + resourcetype + 1 + + + max + 300 + + + + + + + updateResourceLimit + 954 [Update Resource Limit] + + + domainid + 1 + + + resourcetype + 1 + + + max + 65 + + + + + domainid + 1 + + + domain + ROOT + + + resourcetype + 1 + + + max + 65 + + + + + + listResourceLimits + - Verify the update using List Resource Limits - + + + domainid + 1 + + + resourcetype + 1 + + + + + domainid + 1 + + + domain + ROOT + + + resourcetype + 1 + + + max + 65 + + + + + + + + createDiskOffering + 932 [Create Disk Offering] + + + name + newdiskname + + + description + newdiskdesc + + + disksize + 1 + + + displaytext + volumedisplay + + + + + id + diskid + + + domainid + 1 + + + domain + ROOT + + + name + newdiskname + + + displaytext + volumedisplay + + + disksize + 1024 + + + created + + + isCustomized + false + + + + + + + listDiskOfferings + 934 [List the Created Disk Offering] + + + name + newdiskname + + + + + id + diskid + + + domainid + 1 + + + domain + ROOT + + + name + newdiskname + + + displaytext + volumedisplay + + + disksize + 1024 + + + created + + + isCustomized + false + + + + + + + updateDiskOffering + Update the Created Disk Offering + + + id + diskid + + + name + newdiskname + + + + + id + diskid + + + domainid + 1 + + + domain + ROOT + + + name + newdiskname + + + displaytext + volumedisplay + + + disksize + 1024 + + + created + + + isCustomized + false + + + + + + listDiskOfferings + - Verify the Update using List Disk Offering - + + + name + newdiskname + + + + + id + diskid + + + domainid + 1 + + + domain + ROOT + + + name + newdiskname + + + displaytext + volumedisplay + + + disksize + 1024 + + + created + + + isCustomized + false + + + + + + + + deleteDiskOffering + 933 [Delete Disk Offering] + + + id + diskid + + + + + success + true + + + + + + listDiskOfferings + - Verify the Deletion of the Disk Offering - + true + + + id + diskid + + + + + + + + deleteUser + 4 [Delete User] + + + id + userid + + + + + success + true + + + + + + + + listAlerts + 750 [List Alerts] + false + + + + + listCapacity + 974 [List Capacity] + + capacity + 0 + + type + + + zoneid + globalzoneid + + + zonename + globalzonename + + + podid + + + podname + + + capacityused + + + capacitytotal + + + percentused + + + + + + + listHosts + 975 [List Hosts] + + + type + Routing + + + + host + 0 + + id + + + name + + + state + + + disconnected + + + type + Routing + + + ipaddress + + + zoneid + globalzoneid + + + zonename + globalzonename + + + podid + + + podname + + + version + + + hypervisor + XenServer + + + cpunumber + + + cpuspeed + + + cpuallocated + + + cpuused + + + averageload + + + networkkbsread + + + networkkbswrite + + + memorytotal + + + memoryallocated + + + memoryused + + + capabilities + + + lastpinged + + + managementserverid + + + clusterid + + + clustername + + + islocalstorageactive + + + created + + + events + + + + + + + + listIsos + 960 [List ISOs] + + iso + 0 + + id + + + name + xs-tools.iso + + + displaytext + xen-pv-drv-iso + + + ispublic + true + + + isready + true + + + created + + + bootable + false + + + isfeatured + true + + + crossZones + false + + + ostypeid + + + ostypename + + + account + system + + + domainid + 1 + + + domain + ROOT + + + zoneid + globalzoneid + + + zonename + globalzonename + + + isostatus + Successfully Installed + + + size + + + + + + + createServiceOffering + 962 [Create Service Offering] + + + name + servofferingname + + + displaytext + newoff + + + cpunumber + 1 + + + cpuspeed + 200 + + + memory + 256 + + + + + id + servofferingid + + + name + servofferingname + + + displaytext + newoff + + + cpunumber + 1 + + + cpuspeed + 200 + + + memory + 256 + + + created + + + storagetype + shared + + + offerha + false + + + usevirtualnetwork + true + + + + + + listServiceOfferings + + + id + servofferingid + + + + + id + servofferingid + + + name + servofferingname + + + displaytext + newoff + + + cpunumber + 1 + + + cpuspeed + 200 + + + memory + 256 + + + created + + + storagetype + shared + + + offerha + false + + + usevirtualnetwork + true + + + + + + + updateServiceOffering + 964 [Update Service Offering] + + + id + servofferingid + + + name + servofferingname + + + displaytext + display + + + + + id + servofferingid + + + name + servofferingname + + + displaytext + display + + + cpunumber + 1 + + + cpuspeed + 200 + + + memory + 256 + + + created + + + storagetype + shared + + + offerha + false + + + usevirtualnetwork + true + + + + + + listServiceOfferings + - Verify the update of the Service Offering - + + + id + servofferingid + + + + + id + servofferingid + + + name + servofferingname + + + displaytext + display + + + cpunumber + 1 + + + cpuspeed + 200 + + + memory + 256 + + + created + + + storagetype + shared + + + offerha + false + + + usevirtualnetwork + true + + + + + + + + deleteServiceOffering + 963-1 [Delete Service Offering] + + + id + servofferingid + + + + + success + true + + + + + + listServiceOfferings + 963-2 [List Service Offering] + true + + + id + servofferingid + + + + + + + + registerIso + [Register ISO] + + + name + isoname + + + displaytext + isodisplay + + + url + http://172.16.0.220/images/sumita/iso/ubuntu-9.04-server-amd64.iso + + + ostypeid + 59 + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + + id + privateisoid + + + name + isoname + + + displaytext + isodisplay + + + ispublic + false + + + created + + + isready + false + + + isfeatured + false + + + bootable + true + + + ostypeid + 59 + + + ostypename + Other install media + + + accountid + 1 + + + account + system + + + domainid + 1 + + + zoneid + globalzoneid + + + zonename + globalzonename + + + + + + sleep.sh + + ** Sleep for five minutes + + + s + 300 + + + + + + + listIsos + [List ISOs] + + + id + privateisoid + + + + + id + privateisoid + + + name + isoname + + + displaytext + isodisplay + + + ispublic + false + + + created + + + isready + true + + + bootable + true + + + isfeatured + false + + + crossZones + false + + + ostypeid + 59 + + + ostypename + Ubuntu + + + account + system + + + domainid + 1 + + + domain + ROOT + + + zoneid + globalzoneid + + + zonename + globalzonename + + + isostatus + Successfully Installed + + + size + + + + + + + registerTemplate + [Register Template] + + + name + registername + + + displaytext + registerdisplay + + + url + globaltemplateurl + + + ostypeid + 1 + + + format + vhd + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + hypervisor + XenServer + + + + + id + systemtemplateid + + + name + registername + + + displaytext + registerdisplay + + + ispublic + false + + + + created + + isready + false + + + passwordenabled + false + + + format + VHD + + + isfeatured + false + + + crossZones + false + + + ostypeid + 1 + + + ostypename + CentOS 4.5 (32-bit) + + + accountid + 1 + + + account + system + + + zoneid + globalzoneid + + + zonename + globalzonename + + + status + Processing + + + hypervisor + XenServer + + + domainid + 1 + + + isextractable + true + + + + + + + listSystemVms + [List system VM (Console Proxy VM)] + + + domainid + 1 + + + + systemvm + 0 + + id + consoleid + + + systemvmtype + consoleproxy + + + zoneid + globalzoneid + + + zonename + globalzonename + + + dns1 + dns1 + + + dns2 + dns2 + + + networkdomain + + + gateway + + + name + + + podid + + + hostid + + + hostname + + + privateip + + + privatemacaddress + + + privatenetmask + + + publicip + + + publicmacaddress + + + publicnetmask + + + templateid + 1 + + + created + + + activeviewersessions + 0 + + + state + Running + + + + + + + rebootSystemVm + [Reboot System VM] + + + id + consoleid + + + + + id + consoleid + + + systemvmtype + consoleproxy + + + zoneid + globalzoneid + + + zonename + globalzonename + + + dns1 + dns1 + + + dns2 + dns2 + + + networkdomain + + + gateway + + + name + + + podid + + + hostid + + + hostname + + + privateip + + + privatemacaddress + + + privatenetmask + + + publicip + + + publicmacaddress + + + publicnetmask + + + templateid + 1 + + + created + + + activeviewersessions + 0 + + + state + Running + + + + + + + stopSystemVm + [Stop System VM] + + + id + consoleid + + + + + id + consoleid + + + systemvmtype + consoleproxy + + + zoneid + globalzoneid + + + zonename + globalzonename + + + dns1 + dns1 + + + dns2 + dns2 + + + networkdomain + + + name + + + gateway + + + podid + + + privatemacaddress + + + privatenetmask + + + publicip + + + publicmacaddress + + + publicnetmask + + + templateid + 1 + + + created + + + activeviewersessions + 0 + + + state + Stopped + + + + + + + startSystemVm + [Start System VM] + + + id + consoleid + + + + + id + consoleid + + + systemvmtype + + + zoneid + globalzoneid + + + zonename + globalzonename + + + dns1 + dns1 + + + dns2 + dns2 + + + networkdomain + + + gateway + + + name + + + podid + + + hostid + + + hostname + + + privateip + + + privatemacaddress + + + privatenetmask + + + publicip + + + publicmacaddress + + + publicnetmask + + + templateid + 1 + + + created + + + activeviewersessions + 0 + + + state + Running + + + + + + + deleteIso + [Delete ISO] + + + id + privateisoid + + + + + + listIsos + [List ISOs] + true + + + id + privateisoid + + + + + + + + deleteTemplate + [Delete template] + + + id + systemtemplateid + + + + + + listTemplates + [List templates] + true + + + id + systemtemplateid + + + templatefilter + self + + + + + \ No newline at end of file diff --git a/test/metadata/func/regression_test.xml b/test/metadata/func/regression_test.xml new file mode 100644 index 00000000000..ced68067cc1 --- /dev/null +++ b/test/metadata/func/regression_test.xml @@ -0,0 +1,3465 @@ + + + + createUser + 3 + + + username + usernameparam + + + password + alena123 + + + firstname + admin + + + lastname + adminlastname + + + email + admin@gmail.com + + + accounttype + 0 + + + + + id + userid + + + username + usernameparam + + + firstname + admin + + + lastname + adminlastname + + + email + admin@gmail.com + + + account + accountname + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + created + + + state + enabled + + + + + + + listAccounts + 950 + + + name + accountname + + + + + id + accountid + + + name + accountname + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + ipavailable + + + iptotal + 0 + + + iplimit + + + vmavailable + + + vmlimit + + + vmtotal + 0 + + + vmstopped + 0 + + + vmrunning + 0 + + + volumelimit + + + volumetotal + 0 + + + volumeavailable + + + snapshotlimit + + + snapshottotal + 0 + + + snapshotavailable + + + templatelimit + + + templatetotal + 0 + + + templateavailable + + + state + enabled + + + iscleanuprequired + false + + + + + + + updateUser + 6 + + + id + userid + + + username + newuser + + + + + + + listUsers + 5 + + + id + userid + + + + + id + userid + + + username + newuser + + + firstname + admin + + + lastname + adminlastname + + + email + admin@gmail.com + + + account + accountname + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + state + enabled + + + created + + + + + + + lockUser + Lock user + + + id + userid + + + + + + + disableUser + 428 + + + id + userid + + + + + + + + + enableUser + 9 + + + id + userid + + + + + + + createDomain + 10 + + + name + domainname + + + + + name + domainname + + + id + newdomainid + + + + + + + + listDomains + 11 + + + name + domainname + + + + + id + newdomainid + + + name + domainname + + + + + + + updateDomain + 952 + + + id + newdomainid + + + name + newdomainname + + + + + + listDomains + false + + + name + newdomainname + + + + + + + deleteDomain + 654 + + + id + newdomainid + + + + + + + listTemplates + 27 + + + templatefilter + self + + + + template + 0 + + id + centos52templateid + + + name + centos52templatename + + + displaytext + centos52templatedisplaytext + + + ispublic + centos52templateispublic + + + created + centos52templatecreated + + + isready + true + + + passwordenabled + centos52templatepasswordenabled + + + + + + listTemplates + + + name + centos52templatename + + + templatefilter + self + + + + + id + centos52templateid + + + name + centos52templatename + + + displaytext + centos52templatedisplaytext + + + ispublic + centos52templateispublic + + + created + centos52templatecreated + + + isready + true + + + passwordenabled + centos52templatepasswordenabled + + + + + + + listServiceOfferings + 28 + + + id + globalserviceofferingid + + + + serviceoffering + 0 + + id + smallofferingid + + + name + smallofferingname + + + + + + listServiceOfferings + 876 + + + id + globalserviceofferingid + + + + serviceoffering + 0 + + id + smallofferingid + + + name + smallofferingname + + + displaytext + + + cpunumber + smallofferingcpunumber + 1 + + + cpuspeed + smallofferingcpuspeed + 500 + + + memory + smallofferingmemory + 512 + + + created + + + + + + + + listZones + 39 + + 0 + zone + + id + globalzoneid + + + name + ZONE1 + + + + + + + deployVirtualMachine + 13 + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + 5 + + + templateid + globaltemplateid + + + account + accountname + + + domainid + 1 + + + displayname + namefordisplay + + + group + group1 + + + + + id + vmid + + + name + vmname + + + ipaddress + vmipaddress + + + created + + + zoneid + globalzoneid + + + zonename + globalzonename + + + haenable + false + + + state + Running + + + account + accountname + + + templateid + globaltemplateid + + + serviceofferingid + globalserviceofferingid + + + cpunumber + smallofferingcpunumber + + + cpuspeed + smallofferingcpuspeed + + + memory + smallofferingmemory + + + displayname + namefordisplay + + + group + group1 + + + + + + + + listVirtualMachines + 957 + false + + + name + vmname + + + + + id + vmid + + + name + vmname + + + ipaddress + vmipaddress + + + created + + + zoneid + globalzoneid + + + zonename + globalzonename + + + haenable + false + + + state + Running + + + account + accountname + + + templateid + globaltemplateid + + + serviceofferingid + smallofferingid + + + serviceofferingname + smallofferingname + + + cpunumber + smallofferingcpunumber + + + cpuspeed + smallofferingcpuspeed + + + memory + smallofferingmemory + + + displayname + namefordisplay + + + group + group1 + + + + + + + listRouters + 35 + + + zoneid + globalzoneid + + + account + system + + + domainid + 1 + + + + router + 0 + + id + routerid + + + publicip + sourcenatpublicip + + + zoneid + globalzoneid + + + zonename + globalzonename + + + dns1 + dns1 + + + dns2 + dns2 + + + networkdomain + routernetworkdomain + + + gateway + + + name + routername + + + podid + + + privateip + + + privatemacaddress + + + privatenetmask + + + publicmacaddress + routerpublicmacaddress + + + guestipaddress + routeripaddress + + + guestmacaddress + routermacaddress + + + created + + + hostid + + + state + Running + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + listVirtualMachines + 15 + + + account + accountname + + + name + vmname + + + + + id + vmid + + + name + vmname + + + ipaddress + vmipaddress + + + created + + + zoneid + globalzoneid + + + zonename + globalzonename + + + haenable + false + + + state + Running + + + account + accountname + + + templateid + globaltemplateid + + + serviceofferingid + smallofferingid + + + serviceofferingname + smallofferingname + + + cpunumber + smallofferingcpunumber + + + cpuspeed + smallofferingcpuspeed + + + memory + smallofferingmemory + + + displayname + namefordisplay + + + group + group1 + + + + + + + + rebootVirtualMachine + 16 + + + id + vmid + + + + + + listVirtualMachines + + + account + accountname + + + name + vmname + + + + + state + Running + + + + + + + + stopVirtualMachine + 17 + + + id + vmid + + + + + + listVirtualMachines + + + account + accountname + + + name + vmname + + + + + state + Stopped + + + + + + + + + + listVolumes + + + virtualmachineid + vmid + + + type + ROOT + + + + + id + rootvolumeid + + + + + + listVolumes + + + virtualmachineid + vmid + + + type + DATADISK + + + + + id + datavolumeid + + + + + + + detachVolume + + + id + datavolumeid + + + + + + listVolumes + true + + + virtualmachineid + vmid + + + type + DATADISK + + + + + + + + createVolume + 1026 + + + account + accountname + + + domainid + 1 + + + name + + + zoneid + globalzoneid + + + diskofferingid + 5 + + + + + id + datavolumeid + + + + + + + + attachVolume + + + id + datavolumeid + + + virtualmachineid + vmid + + + + + + listVolumes + false + + + virtualmachineid + vmid + + + type + DATADISK + + + + + + + + createVolume + + + account + accountname + + + domainid + 1 + + + name + + + zoneid + globalzoneid + + + diskofferingid + 1 + + + + + id + datavolumeid1 + + + + + + deleteVolume + + + id + datavolumeid1 + + + + + + listVolumes + true + + + id + datavolumeid1 + + + + + + + + + createSnapshot + + + volumeid + datavolumeid + + + + + id + snapshotid1 + + + volumeid + datavolumeid + + + created + + + name + + + account + accountname + + + + + + listSnapshots + false + + + volumeid + datavolumeid + + + + + + + deleteSnapshot + 24 + + + id + snapshotid1 + + + + + + + listSnapshots + 26 + true + + + volumeid + datavolumeid + + + + + + + createTemplate + 958 + + + volumeid + datavolumeid + + + name + privatetemplatename + + + displaytext + newtext + + + osTypeId + 1 + + + + + id + privatetemplateid + + + name + privatetemplatename + + + ispublic + false + + + isready + true + + + created + + + passwordenabled + false + + + + + + + listTemplates + 27 + + + name + privatetemplatename + + + templatefilter + self + + + + + id + privatetemplateid + + + name + privatetemplatename + + + ispublic + false + + + isready + true + + + created + + + passwordenabled + false + + + + + + + updateTemplate + Update template + + + id + privatetemplateid + + + displaytext + lalala + + + name + blah + + + + + + listTemplates + List updated template + + + id + privatetemplateid + + + templatefilter + self + + + + + displaytext + lalala + + + + + + + + listTemplatePermissions + list template permissions command + + + id + privatetemplateid + + + templatefilter + self + + + + + ispublic + false + + + + + + + + updateTemplatePermissions + update template permissions + + + id + privatetemplateid + + + ispublic + true + + + + + + listTemplates + List template with updated permission + + + id + privatetemplateid + + + templatefilter + self + + + + + ispublic + true + + + + + + + + deleteTemplate + 959 + + + id + privatetemplateid + + + + + + listTemplates + true + + + name + privatetemplatename + + + templatefilter + self + + + + + + + + + changeServiceForVirtualMachine + 20 + + + id + vmid + + + serviceofferingid + 2 + + + + + + listVirtualMachines + + + account + accountname + + + name + vmname + + + + + state + Stopped + + + serviceofferingid + 2 + + + + + + + + + + listVirtualMachines + + + account + accountname + + + name + vmname + + + + + state + Stopped + + + + + + startVirtualMachine + 18 + + + id + vmid + + + + + id + vmid + + + name + vmname + + + ipaddress + vmipaddress + + + created + + + zoneid + globalzoneid + + + zonename + globalzonename + + + haenable + false + + + state + Running + + + account + accountname + + + templateid + globaltemplateid + + + serviceofferingid + 2 + + + + + + listVirtualMachines + + + account + accountname + + + name + vmname + + + + + state + Running + + + + + + + updateVirtualMachine + + + id + vmid + + + haenable + true + + + + + + listVirtualMachines + 21 + + + account + accountname + + + name + vmname + + + + + haenable + true + + + + + + updateVirtualMachine + + + id + vmid + + + haenable + false + + + + + + listVirtualMachines + 21 + + + account + accountname + + + name + vmname + + + + + haenable + false + + + + + + + + + + + + + + rebootRouter + 36 + + + id + routerid + + + + + + + stopRouter + 37 + + + id + routerid + + + + + + + startRouter + 38 + + + id + routerid + + + + + id + routerid + + + publicip + sourcenatpublicip + + + zoneid + globalzoneid + + + zonename + globalzonename + + + dns1 + dns1 + + + networkdomain + routernetworkdomain + + + name + routername + + + podid + + + privateip + + + privatemacaddress + + + privatenetmask + + + publicmacaddress + routerpublicmacaddress + + + ipaddress + routeripaddress + + + macaddress + routermacaddress + + + created + + + hostid + + + state + Running + + + + + + + listEvents + 40 + + + account + accountname + + + + + + + destroyVirtualMachine + 14 + + + id + vmid + + + + + + listVirtualMachines + + + id + vmid + + + + + state + Destroyed + + + + + + + recoverVirtualMachine + 22 + + + id + vmid + + + + + + listVirtualMachines + + + account + accountname + + + name + vmname + + + + + state + Stopped + + + + + + + listConfigurations + 549 + false + + + + + listConfigurations + 878 + false + + + category + advanced + + + + + + + + updateConfiguration + 550 + + + name + update.wait + + + value + 35 + + + + + + listConfigurations + + + name + update.wait + + + + + value + 35 + + + + + + + + listPods + 552 + + + + + + + + + + createUser + 3 + + + username + + + password + jack12 + + + firstname + jack12 + + + lastname + jacklastname + + + email + jack@gmail.com + + + accounttype + 0 + + + + + account + accountname1 + + + + + + listAccounts + + + name + accountname1 + + + + + id + accountid1 + + + + + + updateAccount + 951 + + + account + accountname1 + + + domainid + 1 + + + newname + updatedname + + + + + + listAccounts + + + name + updatedname + + + + + id + accountid1 + + + name + updatedname + + + + + + + lockAccount + Lock Account + + + account + updatedname + + + domainid + 1 + + + + + + + disableAccount + 7 + + + account + updatedname + + + domainid + 1 + + + + + + + + enableAccount + 8 + + + account + updatedname + + + domainid + 1 + + + + + + + + updateResourceLimit + 953 + + + resourcetype + 1 + + + max + 300 + + + domainid + 1 + + + + + domainid + 1 + + + domain + ROOT + + + resourcetype + 1 + + + max + 300 + + + + + + + listResourceLimits + true + 956 + + + domainid + 1 + + + resourcetype + 1 + + + + + max + 300 + + + + + + + updateResourceLimit + 954 + + + domainid + 1 + + + resourcetype + 1 + + + max + 65 + + + + + + listResourceLimits + + + domainid + 1 + + + resourcetype + 1 + + + + + max + 65 + + + + + + + + createDiskOffering + 932 + + + name + newdiskname + + + description + newdiskdesc + + + disksize + 1024 + + + displaytext + volumedisplay + + + + + id + diskid + + + domainid + 1 + + + name + newdiskname + + + displaytext + volumedisplay + + + disksize + 1099511627776 + + + ismirrored + false + + + + + + + + + listDiskOfferings + 934 + false + + + domainid + 1 + + + name + newdisk + + + + + + + + updateDiskOffering + + + id + diskid + + + name + newdiskname + + + + + + listDiskOfferings + + + domainid + 1 + + + name + newdiskname + + + + + name + newdiskname + + + + + + + + deleteDiskOffering + 933 + + + id + diskid + + + + + + listDiskOfferings + true + + + domainid + 1 + + + id + diskid + + + + + + + + deleteUser + 4 + + + id + userid + + + + + + + listAlerts + 750 + false + + + + + listCapacity + 974 + false + + + + + listHosts + false + 975 + + + + + + listIsos + 960 + true + + + + + createServiceOffering + 962 + + + name + + + displaytext + newoff + + + cpunumber + 1 + + + cpuspeed + 200 + + + memory + 256 + + + + + id + soid + + + + + + listServiceOfferings + + + id + soid + + + + + id + newofferingid + + + displaytext + newoff + + + cpunumber + 1 + + + cpuspeed + 200 + + + memory + 256 + + + created + + + + + + + + updateServiceOffering + 964 + + + id + newofferingid + + + name + + + displaytext + display + + + + + + + listServiceOfferings + + + id + newofferingid + + + + + id + newofferingid + + + displaytext + display + + + cpunumber + 1 + + + cpuspeed + 200 + + + memory + 256 + + + created + + + + + + + + deleteServiceOffering + 963-1 + + + id + newofferingid + + + + + + listServiceOfferings + 963-2 + true + + + id + newofferingid + + + + + + + + registerIso + Register iso + + + name + isoname + + + displaytext + isodisplay + + + url + http://172.16.0.220/images/sumita/iso/ubuntu-9.04-server-amd64.iso + + + ostypeid + 53 + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + + id + privateisoid + + + created + + + ispublic + false + + + bootable + true + + + isready + false + + + isfeatured + false + + + name + registername + + + displaytext + registerdisplay + + + + + + + listIsos + List isos + false + + + id + privateisoid + + + + + + + registerTemplate + Register template + + + name + registername + + + displaytext + registerdisplay + + + url + globaltemplateurl + + + ostypeid + 1 + + + format + vhd + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + + id + systemtemplateid + + + created + + + ispublic + false + + + isfeatured + false + + + passwordenabled + false + + + format + VHD + + + isready + false + + + name + registername + + + displaytext + registerdisplay + + + + + + + + listSystemVms + List system vms + + + domainid + 1 + + + + systemvm + 0 + + id + consoleid + + + publicip + + + zoneid + + + zonename + + + dns1 + dns1 + + + dns2 + dns2 + + + networkdomain + + + gateway + + + name + + + podid + + + privateip + + + privatemacaddress + + + privatenetmask + + + publicmacaddress + + + privatemacaddress + + + created + + + hostid + + + state + Running + + + activeviewersessions + 0 + + + + + + + rebootSystemVm + Reboot system vm + + + id + consoleid + + + + + + + stopSystemVm + Stop system vm + + + id + consoleid + + + + + + + startSystemVm + Start system vm + + + id + consoleid + + + + + + + + deleteIso + Delete iso + + + id + privateisoid + + + + + + listIsos + List isos + true + + + id + privateisoid + + + + + + + deleteTemplate + Delete template + + + id + systemtemplateid + + + + + + listTemplates + List templates + true + + + id + systemtemplateid + + + templatefilter + self + + + + + + diff --git a/test/metadata/func/regression_user.xml b/test/metadata/func/regression_user.xml new file mode 100644 index 00000000000..e0d4543a2c8 --- /dev/null +++ b/test/metadata/func/regression_user.xml @@ -0,0 +1,2364 @@ + + + + + createAccount + [Create the Account and a User for the account] + + + account + accountname + + + accounttype + 0 + + + domainid + 1 + + + email + user@gmail.com + + + firstname + user + + + lastname + userlastname + + + username + usernameparam + + + password + password + + + + + id + accountid + + + name + accountname + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmavailable + Unlimited + + + vmlimit + Unlimited + + + vmtotal + 0 + + + ipavailable + Unlimited + + + iptotal + 0 + + + iplimit + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + enabled + + + + + + + listUsers + 5 [List the Created User in (3)] + + + account + accountname + + + + + + id + userid + + + username + usernameparam + + + firstname + user + + + lastname + userlastname + + + email + user@gmail.com + + + created + createtimestamp + + + state + enabled + + + account + accountname + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + + + + + + registerUserKeys + + + id + userid + + + + + apikey + apikey + + + secretkey + secretkey + + + + + + createNetwork + [Creating default network] + + + zoneid + globalzoneid + + + networkOfferingId + globalnetworkofferingid + + + account + accountname + + + domainid + 1 + + + name + regression_user_network + + + displaytext + regression_user_network + + + + + id + networkid + + + + + + + listAccounts + true + 950 + + + id + accountid + + + name + accountname + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + ipavailable + + + iptotal + 0 + + + iplimit + + + vmavailable + + + vmlimit + + + vmtotal + 0 + + + vmstopped + 0 + + + vmrunning + 0 + + + volumelimit + + + volumetotal + 0 + + + volumeavailable + + + snapshotlimit + + + snapshottotal + 0 + + + snapshotavailable + + + templatelimit + + + templatetotal + 0 + + + templateavailable + + + + + + + + deployVirtualMachine + true + 13 + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + accountname + + + domainid + 1 + + + displayname + RegularUser-VM + + + group + group1 + + + networkids + networkid + + + + + id + vmid + + + name + vmname + + + ipaddress + vmipaddress + + + created + + + zoneid + globalzoneid + + + zonename + globalzonename + + + haenable + false + + + state + Running + + + account + accountname + + + templateid + globaltemplateid + + + displayname + RegularUser-VM + + + group + group1 + + + + + + + + listVirtualMachines + true + 957 + false + + + name + vmname + + + + + id + vmid + + + name + vmname + + + ipaddress + vmipaddress + + + created + + + zoneid + globalzoneid + + + zonename + globalzonename + + + haenable + false + + + state + Running + + + displayname + RegularUser-VM + + + group + group1 + + + + + + + listRouters + 35 + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + router + 0 + + id + routerid + + + publicip + sourcenatpublicip + + + zoneid + globalzoneid + + + zonename + globalzonename + + + dns1 + dns1 + + + dns2 + dns2 + + + networkdomain + routernetworkdomain + + + gateway + + + name + routername + + + podid + + + privateip + + + privatemacaddress + + + privatenetmask + + + publicmacaddress + routerpublicmacaddress + + + guestipaddress + routeripaddress + + + guestmacaddress + routermacaddress + + + created + + + hostid + + + state + Running + + + + + + + associateIpAddress + true + 546 + + + zoneid + globalzoneid + + + + + id + nonsourcenatpublicipid + + + ipaddress + nonsourcenatpublicip + + + allocated + + + zoneid + globalzoneid + + + zonename + globalzonename + + + issourcenat + false + + + + + + + + + createLoadBalancerRule + true + 986 + + + name + lbname + + + publicipid + sourcenatpublicipid + + + privateport + privateport + + + publicport + publicport + + + algorithm + roundrobin + + + account + accountname + + + domainid + 1 + + + + + id + lbid + + + name + lbname + + + privateport + privateport + + + publicport + publicport + + + algorithm + roundrobin + + + publicip + sourcenatpublicip + + + account + accountname + + + + + + + + listLoadBalancerRules + true + 988 + false + + + + + + assignToLoadBalancerRule + true + 989 + + + id + lbid + + + virtualmachineid + vmid + + + + + + + deleteLoadBalancerRule + true + 987 + + + id + lbid + + + + + + listLoadBalancerRules + true + true + + + + createLoadBalancerRule + true + + + name + lbname + + + publicip + sourcenatpublicip + + + privateport + privateport + + + publicport + publicport + + + algorithm + roundrobin + + + account + accountname + + + domainid + 1 + + + + + id + lbid + + + name + lbname + + + id + nonsourcenatpublicipid + + + privateport + privateport + + + publicport + publicport + + + algorithm + roundrobin + + + publicip + sourcenatpublicip + + + account + accountname + + + + + + assignToLoadBalancerRule + true + + + id + lbid + + + virtualmachineid + vmid + + + + + + + + listLoadBalancerRuleInstances + true + 991 + false + + + id + lbid + + + + + + + removeFromLoadBalancerRule + true + 990 + + + id + lbid + + + virtualmachineid + vmid + + + account + accountname + + + + + + listLoadBalancerRuleInstances + true + true + + + id + lbid + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + listVirtualMachines + true + 15 + + + name + vmname + + + + + id + vmid + + + name + vmname + + + ipaddress + vmipaddress + + + created + + + zoneid + globalzoneid + + + zonename + globalzonename + + + haenable + false + + + state + Running + + + displayname + namefordisplay + + + group + group1 + + + + + + + + rebootVirtualMachine + true + 16 + + + id + vmid + + + + + + listVirtualMachines + true + + + name + vmname + + + + + state + Running + + + + + + + + stopVirtualMachine + true + 17 + + + id + vmid + + + + + + listVirtualMachines + true + + + name + vmname + + + + + state + Stopped + + + + + + + + + + listVolumes + + + virtualmachineid + vmid + + + type + ROOT + + + + + id + rootvolumeid + + + + + + listVolumes + + + virtualmachineid + vmid + + + type + DATADISK + + + + + id + datavolumeid + + + + + + + detachVolume + true + + + id + datavolumeid + + + + + + listVolumes + true + + + virtualmachineid + vmid + + + type + DATADISK + + + + + + + + createVolume + true + 1026 + + + name + + + zoneid + globalzoneid + + + diskofferingid + globaldiskofferingid + + + + + id + datavolumeid + + + + + + + + attachVolume + true + + + id + datavolumeid + + + virtualmachineid + vmid + + + + + + listVolumes + true + false + + + virtualmachineid + vmid + + + type + DATADISK + + + + + + + + createVolume + true + + + name + + + zoneid + globalzoneid + + + diskofferingid + globaldiskofferingid + + + + + id + datavolumeid1 + + + + + + deleteVolume + true + + + id + datavolumeid1 + + + + + + listVolumes + true + + + id + datavolumeid1 + + + + + + + + + createSnapshot + true + + + volumeid + datavolumeid + + + + + id + snapshotid1 + + + volumeid + datavolumeid + + + created + + + name + + + account + accountname + + + + + + listSnapshots + true + false + + + volumeid + datavolumeid + + + + + + + deleteSnapshot + true + 24 + + + id + snapshotid1 + + + + + + + listSnapshots + true + 26 + true + + + volumeid + datavolumeid + + + + + + + createSnapshot + true + + + volumeid + datavolumeid + + + + + id + snapshotid1 + + + + + + createTemplate + true + 958 + + + snapshotid + snapshotid1 + + + name + privatetemplatename + + + displaytext + newtext + + + osTypeId + 1 + + + + + id + privatetemplateid + + + name + privatetemplatename + + + ispublic + false + + + isready + true + + + created + + + passwordenabled + false + + + + + + + listTemplates + true + 27 + + + name + privatetemplatename + + + templatefilter + self + + + + + id + privatetemplateid + + + name + privatetemplatename + + + ispublic + false + + + isready + true + + + created + + + passwordenabled + false + + + + + + + updateTemplate + true + Update template + + + id + privatetemplateid + + + displaytext + blahblahblah + + + name + blah + + + + + + listTemplates + true + List updated template + + + id + privatetemplateid + + + templatefilter + self + + + + + displaytext + blahblahblah + + + + + + + + listTemplatePermissions + true + list template permissions command + + + id + privatetemplateid + + + + + ispublic + false + + + + + + + + updateTemplatePermissions + true + update template permissions + + + id + privatetemplateid + + + ispublic + true + + + + + + listTemplates + true + List template with updated permission + + + id + privatetemplateid + + + templatefilter + self + + + + + ispublic + true + + + + + + + + deleteTemplate + true + 959 + + + id + privatetemplateid + + + + + + listTemplates + true + true + + + name + privatetemplatename + + + templatefilter + self + + + + + + stopVirtualMachine + true + Stop the VM before changing the Service + + + id + vmid + + + + + + + changeServiceForVirtualMachine + true + 20 + + + id + vmid + + + serviceofferingid + 2 + + + + + + listVirtualMachines + true + + + name + vmname + + + + + state + Stopped + + + serviceofferingid + 2 + + + + + + + + resetPasswordForVirtualMachine + true + 19 + + + id + vmid + + + + + id + vmid + + + password + + + + + + listVirtualMachines + true + + + name + vmname + + + + + state + Stopped + + + + + + + listVirtualMachines + true + + + name + vmname + + + + + state + Stopped + + + + + + startVirtualMachine + true + 18 + + + id + vmid + + + + + id + vmid + + + name + vmname + + + ipaddress + vmipaddress + + + created + + + zoneid + globalzoneid + + + zonename + globalzonename + + + haenable + false + + + state + Running + + + templateid + globaltemplateid + + + serviceofferingid + 2 + + + + + + listVirtualMachines + true + + + name + vmname + + + + + state + Running + + + + + + + updateVirtualMachine + true + + + id + vmid + + + haenable + true + + + + + + listVirtualMachines + true + 21 + + + name + vmname + + + + + haenable + true + + + + + + updateVirtualMachine + true + + + id + vmid + + + haenable + false + + + + + + listVirtualMachines + true + 21 + + + name + vmname + + + + + haenable + false + + + + + + + + + listPublicIpAddresses + true + 547 + + + + + + disassociateIpAddress + true + 548 + + + ipaddress + nonsourcenatpublicip + + + + + + + + listEvents + true + 40 + + + + + destroyVirtualMachine + true + 14 + + + id + vmid + + + + + + + + registerIso + true + Register iso + + + id + globalisoid + + + + + name + isoname + + + displaytext + isodisplay + + + url + http://172.16.0.220/images/sumita/iso/ubuntu-9.04-server-amd64.iso + + + ostypeid + 128 + + + zoneid + globalzoneid + + + + + id + privateisoid + + + created + + + ispublic + false + + + bootable + true + + + isready + false + + + isfeatured + false + + + name + registername + + + displaytext + registerdisplay + + + + + + + listIsos + true + List isos + false + + + id + privateisoid + + + + + + + registerTemplate + true + Register template + + + name + registername + + + displaytext + registerdisplay + + + url + http://192.168.10.231/templates/routing/latest/systemvm.vhd.bz2 + + + ostypeid + 132 + + + format + vhd + + + zoneid + globalzoneid + + + + + id + systemtemplateid + + + created + + + ispublic + false + + + isfeatured + false + + + passwordenabled + false + + + format + VHD + + + isready + false + + + name + registername + + + displaytext + registerdisplay + + + + + + + + deleteIso + true + Delete iso + + + id + privateisoid + + + + + + listIsos + true + List isos + true + + + id + privateisoid + + + + + + + deleteTemplate + true + Delete template + + + id + systemtemplateid + + + + + + listTemplates + true + List templates + true + + + id + systemtemplateid + + + templatefilter + self + + + + + + \ No newline at end of file diff --git a/test/metadata/func/regression_works.xml b/test/metadata/func/regression_works.xml new file mode 100644 index 00000000000..c5da1bb00ef --- /dev/null +++ b/test/metadata/func/regression_works.xml @@ -0,0 +1,8400 @@ + + + + + + + + createAccount + [Create the Account and a User for the account] + + + account + accountname + + + accounttype + 1 + + + domainid + 1 + + + email + admin@gmail.com + + + firstname + admin + + + lastname + adminlastname + + + username + usernameparam + + + password + password + + + + + + id + accountid + + + name + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmavailable + Unlimited + + + vmlimit + Unlimited + + + vmtotal + 0 + + + ipavailable + Unlimited + + + iptotal + 0 + + + iplimit + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + enabled + + + + + + + + + + listUsers + 5 [List the Created User in (3)] + + + account + accountname + + + + + + id + userid + + + username + usernameparam + + + firstname + admin + + + lastname + adminlastname + + + email + admin@gmail.com + + + created + createtimestamp + + + state + enabled + + + account + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + + + + + + + + createUser + 3 [Create User Command] + + + account + accountname + + + accounttype + 1 + + + username + secondusernameparam + + + password + password + + + firstname + nimbus-user + + + lastname + nimbus-userlastname + + + email + nimbus-user@gmail.com + + + + + + id + seconduserid + + + username + usernameparam + + + firstname + nimbus-user + + + lastname + nimbus-userlastname + + + email + nimbus-user@gmail.com + + + account + accountname + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + created + createtimestamp + + + state + enabled + + + + + + + + + listAccounts + 950 [List the Account of the User created in (3)] + + + name + accountname + + + + + + id + accountid + + + name + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + ipavailable + Unlimited + + + iptotal + 0 + + + iplimit + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + enabled + + + + + + + + + updateUser + 6 [Update the User created in (3)] + + + id + userid + + + username + newuser + + + password + password + + + firstname + updatednimbus + + + lastname + updatednimbuslastname + + + email + updatednimbus@gmail.com + + + timezone + PST + + + apikey + userapikey + + + secretkey + usersecretkey + + + + + + id + userid + + + username + newuser + + + firstname + updatednimbus + + + lastname + updatednimbuslastname + + + email + updatednimbus@gmail.com + + + created + createtimestamp + + + state + enabled + + + account + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + timezone + PST + + + apikey + userapikey + + + secretkey + usersecretkey + + + + + + + + + listUsers + 5 [List the Updated User updated in (6)] + + + id + userid + + + + + id + userid + + + username + newuser + + + firstname + updatednimbus + + + lastname + updatednimbuslastname + + + email + updatednimbus@gmail.com + + + created + createtimestamp + + + state + enabled + + + account + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + timezone + PST + + + apikey + userapikey + + + secretkey + usersecretkey + + + + + + + + + + + + + + + disableUser + 428 [Disable the User created in (3)] + + + id + userid + + + + + id + userid + + + username + newuser + + + firstname + updatednimbus + + + lastname + updatednimbuslastname + + + email + updatednimbus@gmail.com + + + created + createtimestamp + + + state + disabled + + + account + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + timezone + PST + + + apikey + userapikey + + + secretkey + usersecretkey + + + + + + + + + enableUser + 9 [Enable the User created in (3)] + + + id + userid + + + + + id + userid + + + username + newuser + + + firstname + updatednimbus + + + lastname + updatednimbuslastname + + + email + updatednimbus@gmail.com + + + created + createtimestamp + + + state + enabled + + + account + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + timezone + PST + + + apikey + userapikey + + + secretkey + usersecretkey + + + + + + + + + disableAccount + [Lock the Account] + + + account + accountname + + + domainid + 1 + + + lock + true + + + + + id + accountid + + + name + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + ipavailable + Unlimited + + + iptotal + 0 + + + iplimit + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + locked + + + + + + + + + enableAccount + [Enable the Locked Account] + + + account + accountname + + + domainid + 1 + + + + + id + accountid + + + name + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + ipavailable + Unlimited + + + iptotal + 0 + + + iplimit + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + enabled + + + + + + + + + disableAccount + [Lock the Account] + + + account + accountname + + + domainid + 1 + + + lock + false + + + + + id + accountid + + + name + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + ipavailable + Unlimited + + + iptotal + 0 + + + iplimit + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + disabled + + + + + + + + + enableAccount + [Enable the Locked Account] + + + account + accountname + + + domainid + 1 + + + + + id + accountid + + + name + accountname + + + accounttype + 1 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + ipavailable + Unlimited + + + iptotal + 0 + + + iplimit + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + enabled + + + + + + + + + createDomain + 10 [Create Domain] + + + name + domainname + + + + + + name + domainname + + + id + newdomainid + + + level + 1 + + + parentdomainid + 1 + + + parentdomainname + ROOT + + + haschild + false + + + + + + + + + listDomains + 11 [List Domains] + + + name + domainname + + + + + + id + newdomainid + + + name + domainname + + + level + 1 + + + parentdomainid + 1 + + + parentdomainname + ROOT + + + haschild + false + + + + + + + + + updateDomain + 952 [Update the Domain created in (10)] + + + id + newdomainid + + + name + newdomainname + + + + + + id + newdomainid + + + name + newdomainname + + + level + 1 + + + parentdomainid + 1 + + + parentdomainname + ROOT + + + haschild + false + + + + + + + + + + listDomainChildren + - [List One of the Children of the Parent Domain] + + + id + 1 + + + + + domain + 0 + + id + newdomainid + + + name + newdomainname + + + level + 1 + + + parentdomainid + 1 + + + parentdomainname + ROOT + + + haschild + false + + + + + + + + + deleteDomain + 654 [Delete Domain created in (10)] + + + id + newdomainid + + + cleanup + true + + + + + + success + true + + + + + + + + + listTemplates + 27 [List Templates - List System Template] + + + templatefilter + self + + + id + 1 + + + + + template + 0 + + id + debian50templateid + + + name + debian50templatename + + + displaytext + debian50templatedisplaytext + + + ispublic + debian50templateispublic + + + created + debian50templatecreated + + + isready + true + + + passwordenabled + debian50templatepasswordenabled + + + format + VHD + + + + isfeatured + false + + + crossZones + true + + + ostypeid + debian50templateostypeid + + + ostypename + debian50templateostypename + + + size + debian50templatesize + + + account + system + + + zoneid + globalzoneid + + + zonename + globalzonename + + + status + Download Complete + + + templatetype + SYSTEM + + + hypervisor + XenServer + + + domain + ROOT + + + domainid + 1 + + + + + + + + listTemplates + - Verify All the Parameters of the Listed Template - + + + name + debian50templatename + + + templatefilter + self + + + + template + 0 + + id + debian50templateid + + + name + debian50templatename + + + displaytext + debian50templatedisplaytext + + + ispublic + debian50templateispublic + + + created + debian50templatecreated + + + isready + true + + + isfeatured + false + + + passwordenabled + debian50templatepasswordenabled + + + crossZones + true + + + format + VHD + + + ostypeid + debian50templateostypeid + + + ostypename + debian50templateostypename + + + account + system + + + domainid + 1 + + + domain + ROOT + + + zoneid + globalzoneid + + + zonename + globalzonename + + + status + Download Complete + + + size + debian50templatesize + + + templatetype + SYSTEM + + + hypervisor + XenServer + + + + + + + + + listServiceOfferings + 28 [List the Small Instance Service Offering] + + + id + globalserviceofferingid + + + + + id + smallofferingid + + + name + smallofferingname + + + displaytext + smallofferingdisplaytext + + + cpunumber + smallofferingcpunumber + + + cpuspeed + smallofferingcpuspeed + + + memory + smallofferingmemory + + + created + smallofferingcreatetime + + + storagetype + smallofferingstoragetype + + + offerha + false + + + + + + + + listServiceOfferings + 876 [Verify the First Service Offering] + + + name + smallofferingname + + + + serviceoffering + 0 + + id + smallofferingid + + + name + smallofferingname + + + displaytext + smallofferingdisplaytext + + + cpunumber + smallofferingcpunumber + + + cpuspeed + smallofferingcpuspeed + + + memory + smallofferingmemory + + + created + smallofferingcreatetime + + + storagetype + smallofferingstoragetype + + + offerha + false + + + + + + + + + listZones + 39 [List the Global Zone with id-2] + + + zone + 0 + + id + globalzoneid + + + name + globalzonename + + + dns1 + dns1 + + + dns2 + dns2 + + + internaldns1 + internaldns1 + + + vlan + + + guestcidraddress + + + networktype + Advanced + + + + + + + + + deployVirtualMachine + 13 [Deploy Virtual Machine] + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + accountname + + + domainid + 1 + + + displayname + Testcase13-VM + + + group + Testcase13 + + + + + id + vmid + + + name + vmname + + + created + vmcreated + + + zoneid + globalzoneid + + + zonename + globalzonename + + + ipaddress + vmipaddress + + + serviceofferingid + globalserviceofferingid + + + haenable + false + + + state + Running + + + templateid + globaltemplateid + + + templatename + + + templatedisplaytext + + + passwordenabled + false + + + serviceofferingname + smallofferingname + + + cpunumber + smallofferingcpunumber + + + cpuspeed + smallofferingcpuspeed + + + memory + smallofferingmemory + + + displayname + Testcase13-VM + + + group + Testcase13 + + + domainid + 1 + + + domain + ROOT + + + account + accountname + + + hostname + + + hostid + + + networkgrouplist + + + + + + + sleep.sh + + ** Sleep for a minute + + + s + 60 + + + + + + + listVirtualMachines + 957 [List Virtual Machines Command] + false + + + name + vmname + + + + + id + vmid + + + name + vmname + + + created + vmcreated + + + ipaddress + vmipaddress + + + state + Running + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + haenable + false + + + displayname + Testcase13-VM + + + group + Testcase13 + + + zoneid + globalzoneid + + + zonename + globalzonename + + + hostid + + + hostname + + + templateid + globaltemplateid + + + templatename + + + templatedisplaytext + + + passwordenabled + false + + + serviceofferingid + smallofferingid + + + serviceofferingname + smallofferingname + + + cpunumber + smallofferingcpunumber + + + cpuspeed + smallofferingcpuspeed + + + memory + smallofferingmemory + + + cpuused + + + networkkbsread + + + networkkbswrite + + + guestosid + + + networkgrouplist + + + rootdeviceid + 0 + + + rootdevicetype + NetworkFilesystem + + + + + + + + listRouters + 35 [List Routers] + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + router + 0 + + id + routerid + + + zoneid + globalzoneid + + + zonename + globalzonename + + + dns1 + dns1 + + + dns2 + dns2 + + + networkdomain + routernetworkdomain + + + gateway + + + name + routername + + + podid + + + privateip + + + privatemacaddress + + + privatenetmask + + + publicip + sourcenatpublicip + + + publicmacaddress + routerpublicmacaddress + + + publicnetmask + + + guestipaddress + routeripaddress + + + guestmacaddress + routermacaddress + + + guestnetmask + + + templateid + + + created + + + hostid + + + hostname + + + state + Running + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + + + + + associateIpAddress + 546 [Associate IP Address] + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + + ipaddress + nonsourcenatpublicip + + + allocated + + + zoneid + globalzoneid + + + zonename + globalzonename + + + issourcenat + false + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + forvirtualnetwork + + + vlanname + + + vlanid + + + + + + + + + createLoadBalancerRule + 986 [Create Load Balancer Rule] + + + name + lbname + + + publicip + sourcenatpublicip + + + privateport + privateport + + + publicport + publicport + + + algorithm + roundrobin + + + account + accountname + + + domainid + 1 + + + description + FirstLoadBalancingRuleCreated + + + + + id + lbid + + + name + lbname + + + description + FirstLoadBalancingRuleCreated + + + publicip + sourcenatpublicip + + + privateport + privateport + + + publicport + publicport + + + algorithm + roundrobin + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + + + + + listLoadBalancerRules + 988 [List Load Balancer Rules] + false + + + account + accountname + + + id + lbid + + + + + + + assignToLoadBalancerRule + 989 [Assign VM the Load Balancer Rule] + + + id + lbid + + + virtualmachineid + vmid + + + account + accountname + + + + + + + deleteLoadBalancerRule + 987 [Load Balancer Rule] + + + id + lbid + + + + + + listLoadBalancerRules + true + + + + createLoadBalancerRule + + Create a Second Load Balancer Rule + + + + name + lbname + + + description + SecondLoadBalancerRuleCreated + + + publicip + sourcenatpublicip + + + privateport + privateport + + + publicport + publicport + + + algorithm + roundrobin + + + account + accountname + + + domainid + 1 + + + + + id + lbid + + + name + lbname + + + description + SecondLoadBalancerRuleCreated + + + publicip + sourcenatpublicip + + + publicport + publicport + + + privateport + privateport + + + algorithm + roundrobin + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + + + + assignToLoadBalancerRule + + Assign the Second Load Balancer Rule to a VM + + + + id + lbid + + + virtualmachineid + vmid + + + account + accountname + + + + + + + listLoadBalancerRuleInstances + 991 [List LoadBalancer Rule Instances] + false + + + id + lbid + + + + + id + vmid + + + name + vmname + + + displayname + + + ipaddress + vmipaddress + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + + + + + removeFromLoadBalancerRule + 990 [Remove From Load Balancer Rule] + + + id + lbid + + + virtualmachineid + vmid + + + account + accountname + + + + + + listLoadBalancerRuleInstances + true + + + id + lbid + + + + + + + + + + + + + + + + + + + + + + + + + + + + + listVirtualMachines + 15 [List Virtual Machines] + + + account + accountname + + + name + vmname + + + + + id + vmid + + + name + vmname + + + created + + + ipaddress + vmipaddress + + + state + Running + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + haenable + false + + + displayname + Testcase13-VM + + + group + Testcase13 + + + zoneid + globalzoneid + + + zonename + globalzonename + + + hostid + + + hostname + + + templateid + globaltemplateid + + + templatename + + + templatedisplaytext + + + passwordenabled + false + + + serviceofferingid + smallofferingid + + + serviceofferingname + smallofferingname + + + cpunumber + smallofferingcpunumber + + + cpuspeed + smallofferingcpuspeed + + + memory + smallofferingmemory + + + cpuused + + + networkkbsread + + + networkkbswrite + + + guestosid + + + guestosid + rootostypeid + + + networkgrouplist + + + rootdeviceid + 0 + + + rootdevicetype + NetworkFilesystem + + + + + + + rebootVirtualMachine + 16 [Reboot Virtual Machine] + + + id + vmid + + + + + id + vmid + + + name + vmname + + + created + vmcreated + + + zoneid + globalzoneid + + + zonename + globalzonename + + + ipaddress + vmipaddress + + + serviceofferingid + globalserviceofferingid + + + haenable + false + + + state + Running + + + templateid + globaltemplateid + + + templatename + + + templatedisplaytext + + + passwordenabled + false + + + serviceofferingname + smallofferingname + + + cpunumber + smallofferingcpunumber + + + cpuspeed + smallofferingcpuspeed + + + memory + smallofferingmemory + + + displayname + Testcase13-VM + + + group + Testcase13 + + + domainid + 1 + + + domain + ROOT + + + account + accountname + + + hostname + + + hostid + + + networkgrouplist + + + + + + + + stopVirtualMachine + 17 [Stop Virtual Machine] + + + id + vmid + + + + + id + vmid + + + name + vmname + + + created + vmcreated + + + zoneid + globalzoneid + + + zonename + globalzonename + + + ipaddress + vmipaddress + + + serviceofferingid + globalserviceofferingid + + + haenable + false + + + state + Stopped + + + templateid + globaltemplateid + + + templatename + + + templatedisplaytext + + + passwordenabled + false + + + serviceofferingname + smallofferingname + + + cpunumber + smallofferingcpunumber + + + cpuspeed + smallofferingcpuspeed + + + memory + smallofferingmemory + + + displayname + Testcase13-VM + + + group + Testcase13 + + + domainid + 1 + + + domain + ROOT + + + account + accountname + + + networkgrouplist + + + + + + + + + + listVolumes + [List the ROOT Volume of VM created in (13)] + + + virtualmachineid + vmid + + + type + ROOT + + + + + id + rootvolumeid + + + name + rootvolumename + + + zoneid + globalzoneid + + + zonename + globalzonename + + + type + ROOT + + + deviceid + + + virtualmachineid + vmid + + + vmname + vmname + + + vmdisplayname + + + vmstate + Stopped + + + size + + + created + + + attached + + + state + Created + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + storagetype + shared + + + sourceid + + + sourcetype + Template + + + hypervisor + XenServer + + + storage + primary storage + + + serviceofferingid + globalserviceofferingid + + + serviceofferingname + + + serviceofferingdisplaytext + + + + + + + listVolumes + [List the DATA Volume of VM created in (13)] + + + virtualmachineid + vmid + + + type + DATADISK + + + + + id + datavolumeid + + + name + datavolumename + + + zoneid + globalzoneid + + + zonename + globalzonename + + + type + DATADISK + + + deviceid + + + virtualmachineid + vmid + + + vmname + vmname + + + vmdisplayname + + + vmstate + Stopped + + + size + + + created + + + state + Created + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + storagetype + shared + + + sourceid + + + sourcetype + DiskOffering + + + hypervisor + XenServer + + + diskofferingid + globaldiskofferingid + + + diskofferingname + + + diskofferingdisplaytext + + + storage + primary storage + + + attached + + + destroyed + false + + + + + + + detachVolume + [Detach the DATA Volume of VM created in (13)] + + + id + datavolumeid + + + + + + listVolumes + [Empty List after Detaching the Volume of VM created in (13)] + true + + + virtualmachineid + vmid + + + type + DATADISK + + + + + + + + createVolume + 1026 [Create Volume] + + + account + accountname + + + domainid + 1 + + + name + newseconddiskvolume + + + zoneid + globalzoneid + + + diskofferingid + globaldiskofferingid + + + + + id + datavolumeid + + + name + newseconddiskvolume + + + zoneid + globalzoneid + + + zonename + globalzonename + + + type + DATADISK + + + size + + + created + + + state + Created + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + storagetype + shared + + + hypervisor + None + + + sourceid + + + sourcetype + DiskOffering + + + diskofferingid + globaldiskofferingid + + + diskofferingname + + + diskofferingdisplaytext + + + storage + primary storage + + + destroyed + false + + + + + + + + attachVolume + [Attach The Created Volume in (1026) to the VM created in (13)] + + + id + datavolumeid + + + virtualmachineid + vmid + + + + + id + datavolumeid + + + name + newseconddiskvolume + + + zoneid + globalzoneid + + + zonename + globalzonename + + + type + DATADISK + + + deviceid + + + virtualmachineid + vmid + + + vmname + vmname + + + vmdisplayname + Testcase13-VM + + + vmstate + Stopped + + + size + + + created + + + state + Created + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + storagetype + shared + + + hypervisor + XenServer + + + sourceid + + + sourcetype + DiskOffering + + + diskofferingid + globaldiskofferingid + + + diskofferingname + + + diskofferingdisplaytext + + + storage + primary storage + + + attached + + + destroyed + false + + + + + + listVolumes + - Check that Data Disk Volume list is not Empty - + false + + + virtualmachineid + vmid + + + type + DATADISK + + + + + + + + createVolume + [Create the Volume, Used for Deletion Test] + + + account + accountname + + + domainid + 1 + + + name + newthirddiskvolume + + + zoneid + globalzoneid + + + diskofferingid + globaldiskofferingid + + + + + id + datavolumeid1 + + + + + + deleteVolume + - Delete the Created Volume - + + + id + datavolumeid1 + + + + + success + true + + + + + + listVolumes + - Check the Emptiness of the Volumes List - + true + + + id + datavolumeid1 + + + + + + + + + createSnapshot + [Create Snapshot from Data Volume created in (1026)] + + + volumeid + datavolumeid + + + + + id + snapshotid1 + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + snapshottype + MANUAL + + + volumeid + datavolumeid + + + volumename + newseconddiskvolume + + + volumetype + DATADISK + + + created + + + name + + + intervaltype + MANUAL + + + + + + + listSnapshots + 26 [List Snapshots] + + + volumeid + datavolumeid + + + + + id + snapshotid1 + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + snapshottype + MANUAL + + + volumeid + datavolumeid + + + volumename + newseconddiskvolume + + + volumetype + DATADISK + + + created + + + name + + + intervaltype + MANUAL + + + + + + + deleteSnapshot + 24 [Delete the Created Snapshot] + + + id + snapshotid1 + + + + + success + true + + + + + + listSnapshots + - Check the Emptiness of the Snapshots list - + true + + + volumeid + datavolumeid + + + + + + + createSnapshot + + Create Snapshot to assist Template creation + + + + volumeid + rootvolumeid + + + + + id + snapshotid1 + + + + + + createTemplate + 958 [Create Template from Snapshot] + + + snapshotid + snapshotid1 + + + name + privatetemplatename + + + displaytext + newtext + + + osTypeId + rootostypeid + + + isfeatured + true + + + ispublic + true + + + + + id + privatetemplateid + + + name + privatetemplatename + + + displaytext + privatetemplatedisplaytext + + + ispublic + true + + + created + + + isready + true + + + passwordenabled + false + + + isfeatured + true + + + crossZones + false + + + ostypeid + rootostypeid + + + ostypename + + + account + + + zoneid + globalzoneid + + + zonename + globalzonename + + + domain + ROOT + + + domainid + 1 + + + + + + + + + + registerTemplate + [Register template] + + + name + privatetemplatename + + + displaytext + privatetemplatedisplay + + + url + http://nfs1.lab.vmops.com/templates/centos53-x86_64/latest/f59f18fb-ae94-4f97-afd2-f84755767aca.vhd.bz2 + + + ostypeid + 12 + + + format + vhd + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + hypervisor + XenServer + + + + + id + privatetemplateid + + + name + privatetemplatename + + + displaytext + privatetemplatedisplay + + + ispublic + false + + + created + + + isready + false + + + passwordenabled + false + + + format + VHD + + + isfeatured + false + + + crossZones + false + + + ostypeid + 12 + + + ostypename + CentOS 5.3 (64-bit) + + + accountid + accountid + + + account + accountname + + + zoneid + globalzoneid + + + zonename + globalzonename + + + status + Processing + + + hypervisor + XenServer + + + domainid + 1 + + + isextractable + true + + + + + + + sleep.sh + + ** Sleep for five minutes + + + s + 300 + + + + + + + listTemplates + 27 [List the Registered Template] + + + name + privatetemplatename + + + templatefilter + self + + + + + id + privatetemplateid + + + name + privatetemplatename + + + displaytext + privatetemplatedisplay + + + ispublic + false + + + created + + + isready + true + + + passwordenabled + false + + + format + VHD + + + isfeatured + false + + + crossZones + false + + + ostypeid + 12 + + + ostypename + CentOS 5.3 (64-bit) + + + account + accountname + + + zoneid + globalzoneid + + + zonename + globalzonename + + + status + Download Complete + + + size + + + hypervisor + XenServer + + + domainid + 1 + + + domain + ROOT + + + + + + + updateTemplate + [Update Template registered in (958)] + + + id + privatetemplateid + + + displaytext + UpdatedTemplate + + + name + TemplateUpdated + + + + + id + privatetemplateid + + + name + TemplateUpdated + + + displaytext + UpdatedTemplate + + + ispublic + false + + + created + + + isready + false + + + passwordenabled + false + + + format + VHD + + + isfeatured + false + + + crossZones + false + + + ostypeid + 12 + + + ostypename + CentOS 5.3 (64-bit) + + + account + accountname + + + zoneid + globalzoneid + + + zonename + globalzonename + + + status + Download Complete + + + size + + + hypervisor + XenServer + + + domainid + 1 + + + domain + ROOT + + + + + + sleep.sh + + ** Sleep for four minutes + + + s + 240 + + + + + + listTemplates + [List updated template] + + + id + privatetemplateid + + + templatefilter + self + + + + + id + privatetemplateid + + + name + TemplateUpdated + + + displaytext + UpdatedTemplate + + + ispublic + false + + + created + + + isready + false + + + passwordenabled + false + + + format + VHD + + + isfeatured + false + + + crossZones + false + + + ostypeid + 12 + + + ostypename + CentOS 5.3 (64-bit) + + + account + accountname + + + zoneid + globalzoneid + + + zonename + globalzonename + + + status + Download Complete + + + size + + + hypervisor + XenServer + + + domainid + 1 + + + domain + ROOT + + + + + + + listTemplatePermissions + [List Template Permissions command] + + + id + privatetemplateid + + + templatefilter + self + + + + + id + privatetemplateid + + + ispublic + false + + + domainid + 1 + + + + + + + updateTemplatePermissions + [Update Template Permissions] + + + id + privatetemplateid + + + ispublic + true + + + + + success + true + + + + + + listTemplates + [List Template with Updated Permission] + + + id + privatetemplateid + + + templatefilter + self + + + + + ispublic + true + + + + + + + deleteTemplate + 959 [Delete Template created in (958)] + + + id + privatetemplateid + + + + + success + true + + + + + + listTemplates + - Check the Emptiness of the Template List - + true + + + name + privatetemplatename + + + templatefilter + self + + + + + + + + changeServiceForVirtualMachine + 20 [Change Service Offering for Virtual Machine] + + + id + vmid + + + serviceofferingid + mediumglobalserviceofferingid + + + + + id + vmid + + + name + vmname + + + displayname + Testcase13-VM + + + ipaddress + vmipaddress + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + created + + + state + Stopped + + + haenable + false + + + groupid + + + group + + + zoneid + globalzoneid + + + zonename + globalzonename + + + templateid + globaltemplateid + + + templatename + + + templatedisplaytext + + + passwordenabled + false + + + serviceofferingid + mediumglobalserviceofferingid + + + serviceofferingname + Medium Instance, Virtual Networking + + + forvirtualnetwork + true + + + cpunumber + 1 + + + cpuspeed + 1000 + + + memory + 1024 + + + cpuused + + + networkkbsread + + + networkkbswrite + + + guestosid + + + rootdeviceid + + + rootdevicetype + + + + + + listVirtualMachines + - Check the change in the Service Offering - + + + account + accountname + + + name + vmname + + + + + state + Stopped + + + serviceofferingid + mediumglobalserviceofferingid + + + serviceofferingname + Medium Instance, Virtual Networking + + + + + + + + + + + listVirtualMachines + + Check the Stopped status of VM that needs to be started + + + + account + accountname + + + name + vmname + + + + + state + Stopped + + + + + + startVirtualMachine + 18 [Start the Stopped VM] + + + id + vmid + + + + + id + vmid + + + name + vmname + + + displayname + Testcase13-VM + + + ipaddress + vmipaddress + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + created + + + state + Running + + + haenable + false + + + groupid + + + group + Testcase13 + + + zoneid + globalzoneid + + + zonename + globalzonename + + + hostid + + + hostname + + + templateid + globaltemplateid + + + templatename + + + templatedisplaytext + + + passwordenabled + false + + + serviceofferingid + mediumglobalserviceofferingid + + + serviceofferingname + Medium Instance, Virtual Networking + + + forvirtualnetwork + + + cpunumber + 1 + + + cpuspeed + 1000 + + + memory + 1024 + + + cpuused + + + networkkbsread + + + networkkbswrite + + + guestosid + + + rootdeviceid + + + rootdevicetype + NetworkFilesystem + + + networkgrouplist + + + + + + listVirtualMachines + + + account + accountname + + + name + vmname + + + + + id + vmid + + + name + vmname + + + displayname + Testcase13-VM + + + ipaddress + vmipaddress + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + created + + + state + Running + + + haenable + false + + + groupid + + + group + Testcase13 + + + zoneid + globalzoneid + + + zonename + globalzonename + + + hostid + + + hostname + + + templateid + globaltemplateid + + + templatename + + + templatedisplaytext + + + passwordenabled + false + + + serviceofferingid + mediumglobalserviceofferingid + + + serviceofferingname + Medium Instance, Virtual Networking + + + forvirtualnetwork + + + cpunumber + 1 + + + cpuspeed + 1000 + + + memory + 1024 + + + cpuused + + + networkkbsread + + + networkkbswrite + + + guestosid + + + rootdeviceid + + + rootdevicetype + NetworkFilesystem + + + networkgrouplist + + + + + + + updateVirtualMachine + + HA Enable on Virtual Machine + + + + id + vmid + + + haenable + true + + + + + success + true + + + + + + listVirtualMachines + 21 [Verify the Update using List VMs] + + + account + accountname + + + name + vmname + + + + + id + vmid + + + haenable + true + + + + + + updateVirtualMachine + + HA Disable on Virtual Machine + + + + id + vmid + + + haenable + false + + + + + id + vmid + + + name + vmname + + + displayname + Testcase13-VM + + + ipaddress + vmipaddress + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + created + + + state + Running + + + haenable + false + + + groupid + + + group + Testcase13 + + + zoneid + globalzoneid + + + zonename + globalzonename + + + hostid + + + hostname + + + templateid + globaltemplateid + + + templatename + + + templatedisplaytext + + + passwordenabled + false + + + serviceofferingid + mediumglobalserviceofferingid + + + serviceofferingname + Medium Instance, Virtual Networking + + + forvirtualnetwork + + + cpunumber + 1 + + + cpuspeed + 1000 + + + memory + 1024 + + + cpuused + + + networkkbsread + + + networkkbswrite + + + guestosid + + + rootdeviceid + + + rootdevicetype + NetworkFilesystem + + + networkgrouplist + + + + + + listVirtualMachines + 21 [Verify the Update using List VMs] + + + account + accountname + + + name + vmname + + + + + id + vmid + + + haenable + false + + + + + + + listPublicIpAddresses + 547 [List Public IP Addresses] + + + account + accountname + + + domainid + 1 + + + + publicipaddress + 0 + + ipaddress + + + allocated + + + zoneid + globalzoneid + + + zonename + globalzonename + + + issourcenat + true + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + forvirtualnetwork + true + + + vlanid + + + vlanname + + + isstaticnat + + + + + + + disassociateIpAddress + 548 [Disassociate IP Address] + + + ipaddress + nonsourcenatpublicip + + + account + accountname + + + + + success + true + + + + + + + rebootRouter + 36 [Reboot Router] + + + id + routerid + + + + + id + routerid + + + zoneid + globalzoneid + + + zonename + globalzonename + + + dns1 + dns1 + + + dns2 + dns2 + + + networkdomain + routernetworkdomain + + + gateway + + + name + routername + + + podid + + + hostid + + + hostname + + + privateip + + + privatemacaddress + + + privatenetmask + + + publicip + sourcenatpublicip + + + publicmacaddress + routerpublicmacaddress + + + publicnetmask + + + guestipaddress + routeripaddress + + + guestmacaddress + routermacaddress + + + guestnetmask + + + templateid + + + created + + + state + Running + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + + + + + + stopRouter + 37 [Stop Router] + + + id + routerid + + + + + id + routerid + + + zoneid + globalzoneid + + + zonename + globalzonename + + + dns1 + dns1 + + + dns2 + dns2 + + + networkdomain + routernetworkdomain + + + gateway + + + name + routername + + + podid + + + privateip + + + privatemacaddress + + + privatenetmask + + + publicip + sourcenatpublicip + + + publicmacaddress + routerpublicmacaddress + + + publicnetmask + + + guestipaddress + routeripaddress + + + guestmacaddress + routermacaddress + + + guestnetmask + + + templateid + + + created + + + state + Stopped + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + + + + + startRouter + 38 [Start Router] + + + id + routerid + + + + + id + routerid + + + zoneid + globalzoneid + + + zonename + globalzonename + + + dns1 + dns1 + + + dns2 + dns2 + + + networkdomain + routernetworkdomain + + + gateway + + + name + routername + + + podid + + + hostid + + + hostname + + + privateip + + + privatemacaddress + + + privatenetmask + + + publicip + sourcenatpublicip + + + publicmacaddress + routerpublicmacaddress + + + publicnetmask + + + guestipaddress + routeripaddress + + + guestmacaddress + routermacaddress + + + guestnetmask + + + templateid + + + created + + + state + Running + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + + + + + + listEvents + 40 [List Events] + + + account + accountname + + + + event + 0 + + id + + + username + + + type + + + level + + + description + + + account + accountname + + + domainid + 1 + + + domain + ROOT + + + created + + + state + + + parentid + + + + + + + destroyVirtualMachine + 14 [Destroy Virtual Machine] + + + id + vmid + + + + + + listVirtualMachines + - Verify the Destroyed Status of the Virtual Machine - + + + id + vmid + + + + + name + vmname + + + state + Destroyed + + + + + + + recoverVirtualMachine + 22 [ Recover Virtual Machine ] + + + id + vmid + + + + + success + true + + + + + + listVirtualMachines + - Verify the Stopped Status of the Recovered VM - + + + account + accountname + + + name + vmname + + + + + id + vmid + + + state + Stopped + + + + + + + listConfigurations + 549 [List Configurations] + + configuration + 0 + + category + + + name + + + value + + + description + + + + + + + listConfigurations + 878 [List Configurations with category parameter] + + + category + advanced + + + + configuration + 0 + + category + Advanced + + + name + + + value + + + description + + + + + + + + updateConfiguration + 550 [Update Configuration] + + + name + update.wait + + + value + 35 + + + + + success + true + + + displaytext + Successfully updated configuration value. + + + + + + listConfigurations + - Verify the Updated Configuration - + + + name + update.wait + + + + + category + Advanced + + + name + update.wait + + + value + 35 + + + description + Time to wait before alerting on a updating agent + + + + + + + + listPods + 552 [List Pods] + + + id + 2 + + + name + POD1 + + + + + id + 2 + + + name + POD1 + + + zoneid + globalzoneid + + + zonename + globalzonename + + + cidr + + + startip + + + endip + + + gateway + + + + + + + createUser + 3 [Create User] + + + username + usernamejack + + + password + jack12 + + + firstname + jack12 + + + lastname + jacklastname + + + email + jack@gmail.com + + + accounttype + 0 + + + + + id + accountid1 + + + username + usernamejack + + + firstname + jack12 + + + lastname + jacklastname + + + email + jack@gmail.com + + + created + + + state + enabled + + + account + accountname1 + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + + + + listAccounts + - List Accounts - + + + name + accountname1 + + + + + id + accountid1 + + + name + accountname1 + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + iplimit + Unlimited + + + iptotal + 0 + + + ipavailable + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + enabled + + + + + + + updateAccount + 951 [Update Account] + + + account + accountname1 + + + domainid + 1 + + + newname + updatedname + + + + + id + accountid1 + + + name + updatedname + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + iplimit + Unlimited + + + iptotal + 0 + + + ipavailable + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + enabled + + + + + + listAccounts + - Check the Presence of the Updated Account + false + + + name + updatedname + + + + + id + accountid1 + + + name + updatedname + + + + + + + lockAccount + [Lock Account] + + + account + updatedname + + + domainid + 1 + + + + + id + accountid1 + + + name + updatedname + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + iplimit + Unlimited + + + iptotal + 0 + + + ipavailable + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + locked + + + + + + + disableAccount + 7 [Disable Account] + + + account + updatedname + + + domainid + 1 + + + + + id + accountid1 + + + name + updatedname + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + iplimit + Unlimited + + + iptotal + 0 + + + ipavailable + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + disabled + + + + + + + + enableAccount + 8 [Enable Account] + + + account + updatedname + + + domainid + 1 + + + + + id + accountid1 + + + name + updatedname + + + accounttype + 0 + + + domainid + 1 + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + iplimit + Unlimited + + + iptotal + 0 + + + ipavailable + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + enabled + + + + + + + + updateResourceLimit + 953 [Create using Update Resource Limit] + + + resourcetype + 1 + + + max + 300 + + + domainid + 1 + + + + + domainid + 1 + + + domain + ROOT + + + resourcetype + 1 + + + max + 300 + + + + + + + listResourceLimits + true + 956 [Verify the creation using List Resource Limits] + + + domainid + 1 + + + resourcetype + 1 + + + + + domainid + 1 + + + domain + ROOT + + + resourcetype + 1 + + + max + 300 + + + + + + + updateResourceLimit + 954 [Update Resource Limit] + + + domainid + 1 + + + resourcetype + 1 + + + max + 65 + + + + + domainid + 1 + + + domain + ROOT + + + resourcetype + 1 + + + max + 65 + + + + + + listResourceLimits + - Verify the update using List Resource Limits - + + + domainid + 1 + + + resourcetype + 1 + + + + + domainid + 1 + + + domain + ROOT + + + resourcetype + 1 + + + max + 65 + + + + + + + + createDiskOffering + 932 [Create Disk Offering] + + + name + newdiskname + + + description + newdiskdesc + + + disksize + 1 + + + displaytext + volumedisplay + + + + + id + diskid + + + domainid + 1 + + + domain + ROOT + + + name + newdiskname + + + displaytext + volumedisplay + + + disksize + 1024 + + + created + + + isCustomized + false + + + + + + + listDiskOfferings + 934 [List the Created Disk Offering] + + + name + newdiskname + + + + + id + diskid + + + domainid + 1 + + + domain + ROOT + + + name + newdiskname + + + displaytext + volumedisplay + + + disksize + 1024 + + + created + + + isCustomized + false + + + + + + + updateDiskOffering + Update the Created Disk Offering + + + id + diskid + + + name + newdiskname + + + + + id + diskid + + + domainid + 1 + + + domain + ROOT + + + name + newdiskname + + + displaytext + volumedisplay + + + disksize + 1024 + + + created + + + isCustomized + false + + + + + + listDiskOfferings + - Verify the Update using List Disk Offering - + + + name + newdiskname + + + + + id + diskid + + + domainid + 1 + + + domain + ROOT + + + name + newdiskname + + + displaytext + volumedisplay + + + disksize + 1024 + + + created + + + isCustomized + false + + + + + + + + deleteDiskOffering + 933 [Delete Disk Offering] + + + id + diskid + + + + + success + true + + + + + + listDiskOfferings + - Verify the Deletion of the Disk Offering - + true + + + id + diskid + + + + + + + + deleteUser + 4 [Delete User] + + + id + userid + + + + + success + true + + + + + + + + listAlerts + 750 [List Alerts] + false + + + + + listCapacity + 974 [List Capacity] + + capacity + 0 + + type + + + zoneid + globalzoneid + + + zonename + globalzonename + + + podid + + + podname + + + capacityused + + + capacitytotal + + + percentused + + + + + + + listHosts + 975 [List Hosts] + + + type + Routing + + + + host + 0 + + id + + + name + + + state + + + disconnected + + + type + Routing + + + ipaddress + + + zoneid + globalzoneid + + + zonename + globalzonename + + + podid + + + podname + + + version + + + hypervisor + XenServer + + + cpunumber + + + cpuspeed + + + cpuallocated + + + cpuused + + + averageload + + + networkkbsread + + + networkkbswrite + + + memorytotal + + + memoryallocated + + + memoryused + + + capabilities + + + lastpinged + + + managementserverid + + + clusterid + + + clustername + + + islocalstorageactive + + + created + + + events + + + + + + + + listIsos + 960 [List ISOs] + + iso + 0 + + id + + + name + xs-tools.iso + + + displaytext + xen-pv-drv-iso + + + ispublic + true + + + isready + true + + + created + + + bootable + false + + + isfeatured + true + + + crossZones + false + + + ostypeid + + + ostypename + + + account + system + + + domainid + 1 + + + domain + ROOT + + + zoneid + globalzoneid + + + zonename + globalzonename + + + isostatus + Successfully Installed + + + size + + + + + + + createServiceOffering + 962 [Create Service Offering] + + + name + servofferingname + + + displaytext + newoff + + + cpunumber + 1 + + + cpuspeed + 200 + + + memory + 256 + + + + + id + servofferingid + + + name + servofferingname + + + displaytext + newoff + + + cpunumber + 1 + + + cpuspeed + 200 + + + memory + 256 + + + created + + + storagetype + shared + + + offerha + false + + + usevirtualnetwork + true + + + + + + listServiceOfferings + + + id + servofferingid + + + + + id + servofferingid + + + name + servofferingname + + + displaytext + newoff + + + cpunumber + 1 + + + cpuspeed + 200 + + + memory + 256 + + + created + + + storagetype + shared + + + offerha + false + + + usevirtualnetwork + true + + + + + + + updateServiceOffering + 964 [Update Service Offering] + + + id + servofferingid + + + name + servofferingname + + + displaytext + display + + + + + id + servofferingid + + + name + servofferingname + + + displaytext + display + + + cpunumber + 1 + + + cpuspeed + 200 + + + memory + 256 + + + created + + + storagetype + shared + + + offerha + false + + + usevirtualnetwork + true + + + + + + listServiceOfferings + - Verify the update of the Service Offering - + + + id + servofferingid + + + + + id + servofferingid + + + name + servofferingname + + + displaytext + display + + + cpunumber + 1 + + + cpuspeed + 200 + + + memory + 256 + + + created + + + storagetype + shared + + + offerha + false + + + usevirtualnetwork + true + + + + + + + + deleteServiceOffering + 963-1 [Delete Service Offering] + + + id + servofferingid + + + + + success + true + + + + + + listServiceOfferings + 963-2 [List Service Offering] + true + + + id + servofferingid + + + + + + + + registerIso + [Register ISO] + + + name + isoname + + + displaytext + isodisplay + + + url + http://172.16.0.220/images/sumita/iso/ubuntu-9.04-server-amd64.iso + + + ostypeid + 59 + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + + id + privateisoid + + + name + isoname + + + displaytext + isodisplay + + + ispublic + false + + + created + + + isready + false + + + isfeatured + false + + + bootable + true + + + ostypeid + 59 + + + ostypename + Other install media + + + accountid + 1 + + + account + system + + + domainid + 1 + + + zoneid + globalzoneid + + + zonename + globalzonename + + + + + + sleep.sh + + ** Sleep for five minutes + + + s + 300 + + + + + + + listIsos + [List ISOs] + + + id + privateisoid + + + + + id + privateisoid + + + name + isoname + + + displaytext + isodisplay + + + ispublic + false + + + created + + + isready + true + + + bootable + true + + + isfeatured + false + + + crossZones + false + + + ostypeid + 59 + + + ostypename + Ubuntu + + + account + system + + + domainid + 1 + + + domain + ROOT + + + zoneid + globalzoneid + + + zonename + globalzonename + + + isostatus + Successfully Installed + + + size + + + + + + + registerTemplate + [Register Template] + + + name + registername + + + displaytext + registerdisplay + + + url + globaltemplateurl + + + ostypeid + 1 + + + format + vhd + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + hypervisor + XenServer + + + + + id + systemtemplateid + + + name + registername + + + displaytext + registerdisplay + + + ispublic + false + + + + created + + isready + false + + + passwordenabled + false + + + format + VHD + + + isfeatured + false + + + crossZones + false + + + ostypeid + 1 + + + ostypename + CentOS 4.5 (32-bit) + + + accountid + 1 + + + account + system + + + zoneid + globalzoneid + + + zonename + globalzonename + + + status + Processing + + + hypervisor + XenServer + + + domainid + 1 + + + isextractable + true + + + + + + + listSystemVms + [List system VM (Console Proxy VM)] + + + domainid + 1 + + + + systemvm + 0 + + id + consoleid + + + systemvmtype + consoleproxy + + + zoneid + globalzoneid + + + zonename + globalzonename + + + dns1 + dns1 + + + dns2 + dns2 + + + networkdomain + + + gateway + + + name + + + podid + + + hostid + + + hostname + + + privateip + + + privatemacaddress + + + privatenetmask + + + publicip + + + publicmacaddress + + + publicnetmask + + + templateid + 1 + + + created + + + activeviewersessions + 0 + + + state + Running + + + + + + + rebootSystemVm + [Reboot System VM] + + + id + consoleid + + + + + id + consoleid + + + systemvmtype + consoleproxy + + + zoneid + globalzoneid + + + zonename + globalzonename + + + dns1 + dns1 + + + dns2 + dns2 + + + networkdomain + + + gateway + + + name + + + podid + + + hostid + + + hostname + + + privateip + + + privatemacaddress + + + privatenetmask + + + publicip + + + publicmacaddress + + + publicnetmask + + + templateid + 1 + + + created + + + activeviewersessions + 0 + + + state + Running + + + + + + + stopSystemVm + [Stop System VM] + + + id + consoleid + + + + + id + consoleid + + + systemvmtype + consoleproxy + + + zoneid + globalzoneid + + + zonename + globalzonename + + + dns1 + dns1 + + + dns2 + dns2 + + + networkdomain + + + name + + + gateway + + + podid + + + privatemacaddress + + + privatenetmask + + + publicip + + + publicmacaddress + + + publicnetmask + + + templateid + 1 + + + created + + + activeviewersessions + 0 + + + state + Stopped + + + + + + + startSystemVm + [Start System VM] + + + id + consoleid + + + + + id + consoleid + + + systemvmtype + + + zoneid + globalzoneid + + + zonename + globalzonename + + + dns1 + dns1 + + + dns2 + dns2 + + + networkdomain + + + gateway + + + name + + + podid + + + hostid + + + hostname + + + privateip + + + privatemacaddress + + + privatenetmask + + + publicip + + + publicmacaddress + + + publicnetmask + + + templateid + 1 + + + created + + + activeviewersessions + 0 + + + state + Running + + + + + + + deleteIso + [Delete ISO] + + + id + privateisoid + + + + + + listIsos + [List ISOs] + true + + + id + privateisoid + + + + + + + + deleteTemplate + [Delete template] + + + id + systemtemplateid + + + + + + listTemplates + [List templates] + true + + + id + systemtemplateid + + + templatefilter + self + + + + + diff --git a/test/metadata/func/resource_limits.xml b/test/metadata/func/resource_limits.xml new file mode 100644 index 00000000000..b7d4c5865a9 --- /dev/null +++ b/test/metadata/func/resource_limits.xml @@ -0,0 +1,1876 @@ + + + + + + createAccount + [Create the Account and a User for the account] + + + account + accountname + + + accounttype + 0 + + + domainid + 1 + + + email + user@gmail.com + + + firstname + user + + + lastname + userlastname + + + username + usernameparam + + + password + password + + + + + id + accountid + + + name + accountname + + + + + + + + listUsers + 5 [List the Created User in (3)] + + + account + accountname + + + + + id + userid + + + + + + + + + + + updateResourceLimit + Setup VMs Limit for Account Test Case + + + resourcetype + 0 + + + max + 2 + + + account + accountname + + + domainid + 1 + + + + + resourcetype + 0 + + + max + 2 + + + + + + + updateResourceLimit + Setup Public-Ips Limit for Account Test Case + + + resourcetype + 1 + + + max + 2 + + + account + accountname + + + domainid + 1 + + + + + resourcetype + 1 + + + max + 1 + + + + + + + updateResourceLimit + Setup Volumes Limit for Account Test Case + + + resourcetype + 2 + + + max + 6 + + + account + accountname + + + domainid + 1 + + + + + resourcetype + 2 + + + max + 6 + + + + + + + updateResourceLimit + Setup Snapshots Limit for Account Test Case + + + resourcetype + 3 + + + max + 2 + + + account + accountname + + + domainid + 1 + + + + + resourcetype + 3 + + + max + 2 + + + + + + + updateResourceLimit + Setup Templates Limit for Account Test Case + + + resourcetype + 4 + + + max + 2 + + + account + accountname + + + domainid + 1 + + + + + resourcetype + 4 + + + max + 2 + + + + + + + + registerUserKeys + Register User Keys Test Case + + + id + userid + + + + + apikey + apikey + + + secretkey + secretkey + + + + + + createNetwork + [Creating default network] + + + zoneid + globalzoneid + + + networkOfferingId + globalnetworkofferingid + + + account + accountname + + + domainid + 1 + + + name + defaultregressionnetwork + + + displaytext + defaultregressionnetwork + + + + + id + networkid + + + + + + + + deployVirtualMachine + deploy vm1 test case + true + + + diskofferingid + globaldiskofferingid + + + serviceofferingid + globalserviceofferingid + + + templateid + globaltemplateid + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + displayname + ResourceLimits-VM-1 + + + group + group1 + + + networkids + networkid + + + + + id + vmid1 + + + + + + deployVirtualMachine + deploy vm2 test case + true + + + diskofferingid + globaldiskofferingid + + + serviceofferingid + globalserviceofferingid + + + templateid + globaltemplateid + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + displayname + ResourceLimits-VM-2 + + + group + group1 + + + networkids + networkid + + + + + id + vmid2 + + + + + + + + associateIpAddress + Associate second IP Test Case + true + + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + + + ipaddress + ipid + + + + + + + + + + createVolume + Create Fifth Volume Test Case + true + + + + name + FifthVolume + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + diskofferingid + globaldiskofferingid + + + + + + id + volid1 + + + + + + + attachVolume + + + id + volid1 + + + virtualmachineid + vmid1 + + + + + + createVolume + Create Sixth Volume Test Case + true + + + name + SixthVolume + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + diskofferingid + globaldiskofferingid + + + + + id + volid2 + + + + + + + attachVolume + + + id + volid2 + + + virtualmachineid + vmid2 + + + + + + + createSnapshot + Create First Snapshot Test Case + true + + + volumeid + volid1 + + + + + id + snpid + + + + + + createSnapshot + Create Second Snapshot Test Case + true + + + volumeid + volid2 + + + + + id + snpid + + + + + + + registerTemplate + Create First Template Test Case + true + + + name + FirstTemplate + + + displaytext + Firsttemplate + + + url + http://192.168.10.231/templates/routing/latest/systemvm.vhd.bz2 + + + format + vhd + + + ostypeid + 41 + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + hypervisor + globalhypervisortype + + + + + id + templid1 + + + + + + registerTemplate + Create Second Template Test Case + true + + + name + SecondTemplate + + + displaytext + Secondtemplate + + + url + http://192.168.10.231/templates/routing/latest/systemvm.vhd.bz2 + + + format + vhd + + + ostypeid + 41 + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + hypervisor + globalhypervisortype + + + + + id + templid2 + + + + + + + + deployVirtualMachine + Deploy VM3 Failure test case + true + true + + + diskofferingid + globaldiskofferingid + + + serviceofferingid + globalserviceofferingid + + + templateid + 2 + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + networkids + network + + + + + id + vmid3 + + + + + + + + associateIpAddress + Associate Second IP Failure Test Case + true + true + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + + + ipaddress + ipid + + + + + + + + + createVolume + Create Seventh Volume Failure Test Case + true + true + + + name + SeventhVolume + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + diskofferingid + globaldiskofferingid + + + + + + id + volid3 + + + + + + + listVolumes + + + virtualmachineid + vmid1 + + + type + ROOT + + + + + id + rootvolumeid + + + + + + + createSnapshot + Create Third Snapshot Failure Test Case + true + true + + + volumeid + rootvolumeid + + + + + id + snpid + + + + + + + + registerTemplate + Create Third Template Failure Test Case + true + true + + + name + ThirdTemplate + + + displaytext + Thirdtemplate + + + url + http://192.168.10.231/templates/routing/latest/systemvm.vhd.bz2 + + + format + vhd + + + ostypeid + 41 + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + hypervisor + globalhypervisortype + + + + + id + templid3 + + + + + + + deleteAccount + Clean up account test case + + + + id + accountname + + + + + + + + + + + createAccount + [Create the Account and a User for the account] + + + account + accountname + + + accounttype + 1 + + + domainid + 1 + + + email + newadmin@gmail.com + + + firstname + newadmin + + + lastname + newadminlastname + + + username + usernameparam + + + password + password + + + + + id + accountid + + + name + accountname + + + + + + + + listUsers + 5 [List the Created User in (3)] + + + account + accountname + + + + + id + userid + + + + + + + + updateResourceLimit + Failure in Setting Up VMs Limit for Admin Account Test Case + true + + + resourcetype + 0 + + + max + 2 + + + account + accountname + + + domainid + 1 + + + + + resourcetype + 0 + + + max + 2 + + + + + + + updateResourceLimit + Failure in Setting Up Public-Ips Limit for Admin Account Test Case + true + + + resourcetype + 1 + + + max + 1 + + + account + accountname + + + domainid + 1 + + + + + resourcetype + 1 + + + max + 1 + + + + + + + updateResourceLimit + Failure in Setting Up Volumes Limit for Admin Account Test Case + true + + + resourcetype + 2 + + + max + 6 + + + account + accountname + + + domainid + 1 + + + + + resourcetype + 2 + + + max + 6 + + + + + + + updateResourceLimit + Failure in Setting up Snapshots Limit for Admin Account Test Case + true + + + resourcetype + 3 + + + max + 2 + + + account + accountname + + + domainid + 1 + + + + + resourcetype + 3 + + + max + 2 + + + + + + + updateResourceLimit + Failure in Seting Up Templates Limit for Admin Account Test Case + true + + + resourcetype + 4 + + + max + 2 + + + account + accountname + + + domainid + 1 + + + + + resourcetype + 4 + + + max + 2 + + + + + + + + registerUserKeys + Register User Keys Test Case + + + id + userid + + + + + apikey + apikey + + + secretkey + secretkey + + + + + + createNetwork + [Creating default network] + + + zoneid + globalzoneid + + + networkOfferingId + globalnetworkofferingid + + + account + accountname + + + domainid + 1 + + + name + defaultregressionnetwork + + + displaytext + defaultregressionnetwork + + + + + id + networkid + + + + + + + + deployVirtualMachine + deploy vm1 test case + true + + + diskofferingid + globaldiskofferingid + + + serviceofferingid + globalserviceofferingid + + + templateid + globaltemplateid + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + displayname + SnapshotTest-Admin-VM-1 + + + group + group1 + + + networkids + networkid + + + + + id + vmid1 + + + + + + deployVirtualMachine + deploy vm2 test case + true + + + diskofferingid + globaldiskofferingid + + + serviceofferingid + globalserviceofferingid + + + templateid + globaltemplateid + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + displayname + SnapshotTest-Admin-VM-2 + + + group + group1 + + + networkids + networkid + + + + + id + vmid2 + + + + + + + + associateIpAddress + Associate second IP Test Case + true + + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + + + ipaddress + ipid + + + + + + + createVolume + Create Fifth Volume Test Case + true + + + + name + AdminsFifthVolume + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + diskofferingid + globaldiskofferingid + + + + + + id + volid1 + + + + + + + attachVolume + + + id + volid1 + + + virtualmachineid + vmid1 + + + + + + createVolume + Create Sixth Volume Test Case + true + + + name + AdminsSixthVolume + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + diskofferingid + globaldiskofferingid + + + + + id + volid2 + + + + + + + attachVolume + + + id + volid2 + + + virtualmachineid + vmid2 + + + + + + + createSnapshot + Create First Snapshot Test Case + true + + + volumeid + volid1 + + + + + id + snpid + + + + + + createSnapshot + Create Second Snapshot Test Case + true + + + volumeid + volid2 + + + + + id + snpid + + + + + + + registerTemplate + Create First Template Test Case + true + + + name + AdminsFirstTemplate + + + displaytext + AdminsFirsttemplate + + + url + http://192.168.10.231/templates/routing/latest/systemvm.vhd.bz2 + + + format + vhd + + + ostypeid + 41 + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + hypervisor + globalhypervisortype + + + + + id + templid1 + + + + + + registerTemplate + Create Second Template Test Case + true + + + name + AdminsSecondTemplate + + + displaytext + AdminsSecondtemplate + + + url + http://192.168.10.231/templates/routing/latest/systemvm.vhd.bz2 + + + format + + + + ostypeid + 41 + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + hypervisor + globalhypervisortype + + + + + id + templid2 + + + + + + + + deployVirtualMachine + Deploy VM3 Failure Avoidance test case + true + + + + diskofferingid + globaldiskofferingid + + + serviceofferingid + globalserviceofferingid + + + templateid + globaltemplateid + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + displayname + SnapshotTest-Admin-VM-3 + + + group + group1 + + + networkids + networkid + + + + + id + vmid3 + + + + + + + + associateIpAddress + Associate Second IP Failure Avoidance Test Case + true + + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + + + ipaddress + ipid + + + + + + + + + createVolume + Create Seventh Volume Failure Avoidance Test Case + true + + + + name + AdminsSeventhVolume + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + diskofferingid + globaldiskofferingid + + + + + + id + volid3 + + + + + + + + createSnapshot + Create Third Snapshot Failure Test Case + true + true + + + volumeid + volid1 + + + + + id + snpid + + + + + + + + registerTemplate + Create Third Template Failure Avoidance Test Case + true + + + + name + AdminsThirdTemplate + + + displaytext + AdminsThirdtemplate + + + url + http://192.168.10.231/templates/routing/latest/systemvm.vhd.bz2 + + + format + vhd + + + ostypeid + 41 + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + hypervisor + globalhypervisortype + + + + + + id + templid3 + + + + + + + deleteAccount + Clean up admin account test case + + + + id + accountid + + + + + \ No newline at end of file diff --git a/test/metadata/func/roughflatstress.xml b/test/metadata/func/roughflatstress.xml new file mode 100644 index 00000000000..7dc0a947405 --- /dev/null +++ b/test/metadata/func/roughflatstress.xml @@ -0,0 +1,673 @@ + + + + createAccount + [Create the Account and a User for the account] + + + account + accountname + + + accounttype + globalaccttype + + + domainid + globaldomainid + + + email + firstuser@gmail.com + + + firstname + firstuser + + + lastname + firstuserlastname + + + username + getusernameparam1 + + + password + password + + + + + id + getaccountid + + + state + enabled + + + + + + listUsers + [List the User of the account] + + + account + accountname + + + accounttype + globalaccttype + + + domainid + globaldomainid + + + username + getusernameparam1 + + + + + id + getuserid1 + + + state + enabled + + + + + + registerUserKeys + Registering the First User + + + id + getuserid1 + + + + + apikey + apikey + + + secretkey + secretkey + + + + + + createSecurityGroup + true + Creating First Security group for the Account + + + name + getsecuritygroupname1 + + + description + + + + + id + getsecuritygroupid1 + + + + + + authorizeSecurityGroupIngress + true + Authorizing First network group ingress rule for the First Security Group + + + securitygroupid + getsecuritygroupid1 + + + cidrlist + globalcidrlist + + + endport + 22 + + + startport + 22 + + + protocol + tcp + + + + + + listSecurityGroups + true + List the Security group and get the ingress rule ID + + + securitygroupid + getsecuritygroupid1 + + + + + ruleid + getingressruleid1 + + + + + + deployVirtualMachine + true + Deploying VM for the First Account + + + zoneId + globalzoneid + + + hypervisor + globalhypervisortype + + + templateId + globaltemplateid + + + serviceOfferingId + globalserviceofferingid + + + securitygroupids + getsecuritygroupid1 + + + + + id + getvmid1 + + + ipaddress + getvmip1 + + + + + + sleep.sh + + Sleep for 2 min + + + s + 120 + + + + + + ssh.sh + + Ssh test for the vm + + + h + getvmip1 + + + p + password + + + + + + sleep.sh + + Sleep for 1 min + + + s + 60 + + + + + + revokeSecurityGroupIngress + true + Revoking network group igress + + + id + getingressruleid1 + + + + + + + + + createSecurityGroup + true + Creating a Second Security group for the Account + + + name + getsecuritygroupname2 + + + description + + + + + id + getsecuritygroupid2 + + + + + + authorizeSecurityGroupIngress + true + Authorizing network group ingress for the second Security group + + + securitygroupid + getsecuritygroupid2 + + + usersecuritygrouplist[0].account + accountname + + + usersecuritygrouplist[0].group + getsecuritygroupname1 + + + endport + 22 + + + startport + 22 + + + protocol + tcp + + + + + + + authorizeSecurityGroupIngress + true + Authorizing one more network group ingress rule for the Second Security Group + + + securitygroupid + getsecuritygroupid2 + + + cidrlist + globalcidrlist + + + endport + 22 + + + startport + 22 + + + protocol + tcp + + + + + + listSecurityGroups + true + List the Security group and get the first ingress rule ID + + + securitygroupid + getsecuritygroupid2 + + + + + ruleid + getingressruleid2 + + + + + + deployVirtualMachine + true + Deploying Second VM for the First Account + + + zoneId + globalzoneid + + + hypervisor + globalhypervisortype + + + templateId + globaltemplateid + + + serviceOfferingId + flatnetworkserviceofferingid + + + securitygroupids + getsecuritygroupid2 + + + + + id + getvmid2 + + + ipaddress + getvmip2 + + + + + + sleep.sh + + Sleep for 2 min + + + s + 120 + + + + + + ssh.sh + + Ssh test for the vm + + + h + getvmip2 + + + p + password + + + + + + sleep.sh + + Sleep for 1 min + + + s + 60 + + + + + + revokeSecurityGroupIngress + true + Revoking Second Network group's First ingress rule + + + id + getingressruleid2 + + + + + + listSecurityGroups + true + List the Security group and get the second ingress rule ID + + + securitygroupid + getsecuritygroupid2 + + + + + ruleid + getingressruleid2 + + + + + + revokeSecurityGroupIngress + true + Revoking Second network group's second ingress rule + + + id + getingressruleid2 + + + + + + + destroyVirtualMachine + true + Destroying virutal machine + + + id + getvmid1 + + + + + + sleep.sh + + Sleep for 1 min + + + s + 60 + + + + + + destroyVirtualMachine + true + Destroying virutal machine + + + id + getvmid2 + + + + + + sleep.sh + + Sleep for 1 min + + + s + 60 + + + + + + + + deleteUser + Deleting the user + + + id + getuserid1 + + + + + + deleteAccount + Delete Account + + + id + getaccountid + + + + + \ No newline at end of file diff --git a/test/metadata/func/roughregression.xml b/test/metadata/func/roughregression.xml new file mode 100644 index 00000000000..c7cc9ec32a8 --- /dev/null +++ b/test/metadata/func/roughregression.xml @@ -0,0 +1,5994 @@ + + + listDomains + [List Domains] + + + id + globaldomainid + + + + + name + getdomainname1 + + + + + + + createAccount + [Create the Account and a User for the account] + + + account + accountname + + + accounttype + globalaccttype + + + domainid + globaldomainid + + + email + firstuser@gmail.com + + + firstname + firstuser + + + lastname + firstuserlastname + + + username + getusernameparam1 + + + password + password + + + + + id + getaccountid + + + state + enabled + + + + + + registerIso + [] registerIsotestcase + + + name + CentOS-5-5-ISO + + + displayText + CentOS-5-5-ISO + + + url + http://nfs1.lab.vmops.com/isos_64bit/CentOS-5.5-x86_64-bin-DVDs/CentOS-5.5-x86_64-bin-DVD-1of2.iso + + + zoneId + -1 + + + isPublic + true + + + bootable + true + + + osTypeId + 112 + + + isfeatured + true + + + account + accountname + + + domainid + globaldomainid + + + + + id + getisoid1 + + + + + + listIsos + [] listIsosTestCase + + + isofilter + self + + + id + getisoid1 + + + zoneid + 1 + + + + + id + getisoid1 + + + name + CentOS-5-5-ISO + + + displayText + CentOS-5-5-ISO + + + zoneId + 1 + + + isPublic + true + + + bootable + true + + + osTypeId + 112 + + + isfeatured + true + + + account + accountname + + + domainid + globaldomainid + + + domain + getdomainname1 + + + + + + + + + + + createNetwork + [Creating default network] + + + zoneid + globalzoneid + + + networkOfferingId + globalnetworkofferingid + + + account + accountname + + + domainid + globaldomainid + + + name + defaultregressionnetwork + + + displaytext + defaultregressionnetwork + + + + + id + getnetworkid1 + + + + + + + + listAccounts + 950 [List the Account of the User created in (3)] + + + name + accountname + + + + + id + getaccountid + + + name + accountname + + + accounttype + globalaccttype + + + domainid + globaldomainid + + + domain + getdomainname1 + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + ipavailable + Unlimited + + + iptotal + 0 + + + iplimit + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + enabled + + + + + + + listUsers + 5 [List the Created User in (3)] + + + account + accountname + + + + + id + getuserid1 + + + username + getusernameparam1 + + + + + + + createUser + 3 [Create User Command] + + + account + accountname + + + accounttype + globalaccttype + + + username + getusernameparam2 + + + password + password + + + firstname + seconduser + + + lastname + seconduserlastname + + + email + seconduser@gmail.com + + + domainid + globaldomainid + + + + + id + getuserid2 + + + + + + + + updateUser + 6 [Update the User created in (3)] + + + id + getuserid1 + + + username + getusernameparam3 + + + password + password + + + firstname + updatedfirstuser + + + lastname + updatedfirstuserlastname + + + email + updatedfirstuser@gmail.com + + + timezone + PST + + + + + id + getuserid1 + + + username + getusernameparam3 + + + + + + + listUsers + 5 [List the Updated User updated in (6)] + + + id + getuserid1 + + + + + id + getuserid1 + + + username + getusernameparam3 + + + account + accountname + + + accounttype + globalaccttype + + + domainid + globaldomainid + + + domain + getdomainname1 + + + timezone + PST + + + + + + + disableUser + 428 [Disable the User created in (3)] + + + id + getuserid1 + + + + + id + getuserid1 + + + username + getusernameparam3 + + + firstname + updatedfirstuser + + + lastname + updatedfirstuserlastname + + + email + updatedfirstuser@gmail.com + + + state + disabled + + + account + accountname + + + accounttype + globalaccttype + + + domainid + globaldomainid + + + domain + getdomainname1 + + + timezone + PST + + + + + + + enableUser + 9 [Enable the User created in (3)] + + + id + getuserid1 + + + + + id + getuserid1 + + + username + getusernameparam3 + + + firstname + updatednimbus + + + lastname + updatednimbuslastname + + + email + updatednimbus@gmail.com + + + created + createtimestamp + + + state + enabled + + + account + accountname + + + accounttype + globalaccttype + + + domainid + globaldomainid + + + domain + getdomainname1 + + + timezone + PST + + + + + + + disableAccount + [Disable the Account] + + + account + accountname + + + domainid + globaldomainid + + + lock + true + + + + + id + getaccountid + + + name + accountname + + + accounttype + globalaccttype + + + domainid + globaldomainid + + + domain + getdomainname1 + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + ipavailable + Unlimited + + + iptotal + 0 + + + iplimit + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + locked + + + + + + + enableAccount + [Enable the Locked Account] + + + account + accountname + + + domainid + globaldomainid + + + + + id + getaccountid + + + name + accountname + + + accounttype + globalaccttype + + + domainid + globaldomainid + + + domain + getdomainname1 + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + ipavailable + Unlimited + + + iptotal + 0 + + + iplimit + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + enabled + + + + + + + disableAccount + [Lock the Account] + + + account + accountname + + + domainid + globaldomainid + + + lock + false + + + + + id + getaccountid + + + name + accountname + + + accounttype + globalaccttype + + + domainid + globaldomainid + + + domain + getdomainname1 + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + ipavailable + Unlimited + + + iptotal + 0 + + + iplimit + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + disabled + + + + + + + enableAccount + [Enable the Locked Account] + + + account + accountname + + + domainid + globaldomainid + + + + + id + getaccountid + + + name + accountname + + + accounttype + globalaccttype + + + domainid + globaldomainid + + + domain + ROOT + + + receivedbytes + 0 + + + sentbytes + 0 + + + vmlimit + Unlimited + + + vmtotal + 0 + + + vmavailable + Unlimited + + + ipavailable + Unlimited + + + iptotal + 0 + + + iplimit + Unlimited + + + volumelimit + Unlimited + + + volumetotal + 0 + + + volumeavailable + Unlimited + + + snapshotlimit + Unlimited + + + snapshottotal + 0 + + + snapshotavailable + Unlimited + + + templatelimit + Unlimited + + + templatetotal + 0 + + + templateavailable + Unlimited + + + vmstopped + 0 + + + vmrunning + 0 + + + state + enabled + + + + + + + + createDomain + [Create Domain] + + + name + getdomainname2 + + + parentdomainid + globaldomainid + + + + + id + getdomainid1 + + + + + + + listDomains + 11 [List Domains] + + + name + getdomainname2 + + + + + + id + getdomainid1 + + + name + getdomainname2 + + + level + getcurrentlevel1 + + + parentdomainid + globaldomainid + + + parentdomainname + getdomainname1 + + + haschild + false + + + + + + + updateDomain + 952 [Update the Domain created in (10)] + + + id + getdomainid1 + + + name + getdomainname2 + + + + + id + getdomainid1 + + + name + getdomainname2 + + + level + getcurrentlevel1 + + + parentdomainid + globaldomainid + + + parentdomainname + getdomainname1 + + + haschild + false + + + + + + + + listDomainChildren + - [List One of the Children of the Parent Domain] + + + id + globaldomainid + + + + + domain + 0 + + id + getdomainid1 + + + name + getdomainname2 + + + level + getcurrentlevel1 + + + parentdomainid + globaldomainid + + + parentdomainname + getdomainname1 + + + haschild + false + + + + + + + deleteDomain + 654 [Delete Domain created in (10)] + + + id + getdomainid1 + + + cleanup + true + + + + + + success + true + + + + + + + listTemplates + 27 [List Templates - List System Template] + + + templatefilter + self + + + id + 1 + + + + + template + 0 + + id + debian50templateid + + + name + debian50templatename + + + displaytext + debian50templatedisplaytext + + + ispublic + debian50templateispublic + + + created + debian50templatecreated + + + isready + true + + + passwordenabled + debian50templatepasswordenabled + + + format + VHD + + + isfeatured + false + + + crossZones + true + + + ostypeid + debian50templateostypeid + + + ostypename + debian50templateostypename + + + size + debian50templatesize + + + account + system + + + zoneid + globalzoneid + + + zonename + globalzonename + + + status + Download Complete + + + templatetype + SYSTEM + + + hypervisor + XenServer + + + domain + ROOT + + + domainid + 1 + + + + + + + + + listServiceOfferings + 28 [List the Small Instance Service Offering] + + + id + globalserviceofferingid + + + + + id + smallofferingid + + + name + smallofferingname + + + displaytext + smallofferingdisplaytext + + + cpunumber + smallofferingcpunumber + + + cpuspeed + smallofferingcpuspeed + + + memory + smallofferingmemory + + + storagetype + smallofferingstoragetype + + + offerha + false + + + + + + listServiceOfferings + 876 [Verify the First Service Offering] + + + name + smallofferingname + + + + serviceoffering + 0 + + id + smallofferingid + + + name + smallofferingname + + + displaytext + smallofferingdisplaytext + + + cpunumber + smallofferingcpunumber + + + cpuspeed + smallofferingcpuspeed + + + memory + smallofferingmemory + + + storagetype + smallofferingstoragetype + + + offerha + false + + + + + + + + listZones + 39 [List the Global Zone with id-2] + + zone + 0 + + id + globalzoneid + + + name + globalzonename + + + dns1 + dns1 + + + dns2 + dns2 + + + internaldns1 + internaldns1 + + + vlan + + + guestcidraddress + + + networktype + Advanced + + + + + + + + + + createServiceOffering + [1] createServiceOffering-TestCase + + + issystem + false + + + name + LittleInstance + + + displaytext + LittleInstance + + + storagetype + shared + + + cpuNumber + 1 + + + cpuSpeed + 100 + + + memory + 128 + + + offerha + false + + + limitcpuuse + false + + + + + id + servofferid + + + + + + + +createDiskOffering + [1] createDiskOffering-TestCase + + + isMirrored + false + + + name + Little + + + displaytext + LittleDisk1GB + + + customized + false + + + disksize + 1 + + + + + id + diskofferid + + + + + + + + deployVirtualMachine + [2] deployVirtualMachine-TestCase + + + zoneId + globalzoneid + + + hypervisor + globalhypervisortype + + + templateId + globaltemplateid + + + serviceOfferingId + servofferid + + + networkIds + getnetworkid1 + + + diskOfferingId + diskofferid + + + displayname + FirstVM + + + group + FirstVM + + + account + accountname + + + domainid + globaldomainid + + + + + id + getvmid1 + + + + + + updateVirtualMachine + [3] updateVirtualMachine-TestCase + + + id + getvmid1 + + + displayName + First-VM + + + group + First-VM + + + haenable + false + + + ostypeid + 12 + + + + + + + + associateIpAddress + [4] associateIpAddress-TestCase + + + zoneid + globalzoneid + + + account + accountname + + + domainid + globaldomainid + + + + + id + getpublicipid1 + + + ipaddress + getipaddress1 + + + + + + enableStaticNat + [5] enableStaticNat-TestCase + + + ipaddressid + getpublicipid1 + + + virtualmachineid + getvmid1 + + + + + + createIpForwardingRule + [6] createIpForwardingRule-TestCase + + + ipaddressid + getpublicipid1 + + + startPort + 1 + + + endPort + 100 + + + protocol + TCP + + + + + id + getipfwdruleid1 + + + + + + sleep.sh + + Sleep for 2 min + + + s + 120 + + + + + + ssh.sh + + Ssh test for the vm + + + h + getipaddress1 + + + p + password + + + + + + deleteIpForwardingRule + [7] deleteIpForwardingRule-TestCase + + + id + getipfwdruleid1 + + + + + + disableStaticNat + [8] disableStaticNat-TestCase + + + ipaddressid + getpublicipid1 + + + + + + disassociateIpAddress + [9] disassociateIpAddress-TestCase + + + id + getpublicipid1 + + + + + + associateIpAddress + [10] associateIpAddress-TestCase + + + zoneid + globalzoneid + + + account + accountname + + + domainid + globaldomainid + + + + + id + getpublicipid1 + + + ipaddress + getipaddress1 + + + + + + createPortForwardingRule + [11] createPortForwardingRule-TestCase + + + ipaddressid + getpublicipid1 + + + cidrlist + 0.0.0.0/0 + + + publicport + 22 + + + publicendport + 30 + + + privateport + 22 + + + privateendport + 30 + + + protocol + TCP + + + virtualmachineid + getvmid1 + + + + + id + getportfwdruleid1 + + + + + + + + sleep.sh + + Sleep for 2 min + + + s + 120 + + + + + + ssh.sh + + Ssh test for the vm + + + h + getipaddress1 + + + p + password + + + + + + deletePortForwardingRule + [12] deletePortForwardingRule-TestCase + + + id + getportfwdruleid1 + + + + + + disassociateIpAddress + [13] disassociateIpAddress-TestCase + + + id + getpublicipid1 + + + + + + associateIpAddress + [14] associateIpAddress-TestCase + + + zoneid + globalzoneid + + + account + accountname + + + domainid + globaldomainid + + + + + id + getpublicipid1 + + + ipaddress + getipaddress1 + + + + + + createLoadBalancerRule + [15] createLoadBalancerRule-TestCase + + + publicipid + getpublicipid1 + + + name + LBRule-1 + + + publicport + 80 + + + privateport + 80 + + + algorithm + roundrobin + + + + + id + getldblcrule1 + + + + + + assignToLoadBalancerRule + [16] assignToLoadBalancerRule-TestCase + + + id + getldblcrule1 + + + virtualmachineids + getvmid1 + + + + + + + removeFromLoadBalancerRule + [18] removeFromLoadBalancerRule-TestCase + + + id + getldblcrule1 + + + virtualmachineids + getvmid1 + + + + + + updateLoadBalancerRule + [19] updateLoadBalancerRule-TestCase + + + id + getldblcrule1 + + + name + LBRuleUpdated-1 + + + algorithm + roundrobin + + + + + + disassociateIpAddress + [20] disassociateIpAddress-TestCase + + + id + getpublicipid1 + + + + + + associateIpAddress + [14] associateIpAddress-TestCase + + + zoneid + globalzoneid + + + account + accountname + + + domainid + globaldomainid + + + + + id + getpublicipid1 + + + + + + createLoadBalancerRule + [21] createLoadBalancerRule-TestCase + + + publicipid + getpublicipid1 + + + name + LBRule-2 + + + publicport + 80 + + + privateport + 80 + + + algorithm + roundrobin + + + + + id + getldblcrule1 + + + + + + assignToLoadBalancerRule + [22] assignToLoadBalancerRule-TestCase + + + id + getldblcrule1 + + + virtualmachineids + getvmid1 + + + + + + + + deleteLoadBalancerRule + [24] deleteLoadBalancerRule-TestCase + + + id + getldblcrule1 + + + + + + disassociateIpAddress + [25] disassociateIpAddress-TestCase + + + id + getpublicipid1 + + + + + + + listVolumes + [26] listROOTVolumes-TestCase + + + virtualmachineid + getvmid1 + + + type + ROOT + + + + + id + getrootvolumeid1 + + + + + + createSnapshot + [26] createSnapshotofROOTVolume-TestCase + + + volumeid + getrootvolumeid1 + + + account + accountname + + + domainid + globaldomainid + + + + + id + getsnapshotid1 + + + + + + listSnapshots + [27] listROOTVolumeSnapshot-TestCase + + + volumeid + getrootvolumeid1 + + + + + + listVolumes + [26] listDATADISKVolumes-TestCase + + + virtualmachineid + getvmid1 + + + type + DATADISK + + + + + id + getdatavolumeid1 + + + + + + createSnapshot + [28] createSnapshotofDATADISKVolume-TestCase + + + volumeid + getdatavolumeid1 + + + account + accountname + + + domainid + globaldomainid + + + + + id + getsnapshotid2 + + + + + + listSnapshots + [29] listDATADISKVolumeSnapshot-TestCase + + + volumeid + getdatavolumeid1 + + + + + + createTemplate + [30] createTemplateFromSnapshotTakenofROOTVolume-TestCase + + + snapshotid + getsnapshotid1 + + + name + TemplateFromSnapshot-1 + + + displaytext + TemplateFromSnapshot-1 + + + ostypeid + 12 + + + isPublic + true + + + passwordEnabled + false + + + isfeatured + true + + + + + id + gettemplateid1 + + + + + + createTemplate + [31] createTemplateFromSnapshotTakenofDATADISKVolume-TestCase + + + snapshotid + getsnapshotid2 + + + name + TemplateFromSnapshot-2 + + + displaytext + TemplateFromSnapshot-2 + + + ostypeid + 12 + + + isPublic + true + + + passwordEnabled + false + + + isfeatured + true + + + + + id + gettemplateid2 + + + + + + createVolume + [32] createVolumeFromSnapshotTakenofROOTVolume-TestCase + + + snapshotid + getsnapshotid1 + + + name + VlmfromSnapshot-1 + + + account + accountname + + + domainid + globaldomainid + + + + + id + getdatavolumeid2 + + + + + + createVolume + [33] createVolumeFromSnapshotTakenofDATADISKVolume-TestCase + + + snapshotid + getsnapshotid2 + + + name + VlmfromSnapshot-2 + + + account + accountname + + + domainid + globaldomainid + + + + + id + getdatavolumeid3 + + + + + + + attachVolume + [34] attachVolume1-TestCase + + + id + getdatavolumeid2 + + + virtualMachineId + getvmid1 + + + + + + attachVolume + [35] attachVolume2-TestCase + + + id + getdatavolumeid3 + + + virtualMachineId + getvmid1 + + + + + + + + detachVolume + [36] detachVolume1-TestCase + + + id + getdatavolumeid2 + + + + + + detachVolume + [37] detachVolume2-TestCase + + + id + getdatavolumeid3 + + + + + + attachVolume + [34] attachVolume1-TestCase + + + id + getdatavolumeid2 + + + virtualMachineId + getvmid1 + + + + + + attachVolume + [35] attachVolume2-TestCase + + + id + getdatavolumeid3 + + + virtualMachineId + getvmid1 + + + + + + stopVirtualMachine + [40] stopVirtualMachine-TestCase + + + id + getvmid1 + + + + + + updateVirtualMachine + [41] updateVirtualMachine-TestCase + + + id + getvmid1 + + + displayName + First-VM-1-1 + + + group + First-VM-1-1 + + + haenable + false + + + ostypeid + 12 + + + + + + detachVolume + [36] detachVolume1-TestCase + + + id + getdatavolumeid2 + + + + + + detachVolume + [37] detachVolume2-TestCase + + + id + getdatavolumeid3 + + + + + + createTemplate + [44] createTemplateFromROOTVolume-TestCase + + + volumeId + getrootvolumeid1 + + + name + TemplateFromRootVolume-3 + + + displayText + TemplateFromRootVolume-3 + + + osTypeId + 12 + + + isPublic + true + + + passwordEnabled + false + + + + + id + gettemplateid3 + + + + + + startVirtualMachine + [45] startVirtualMachine-TestCase + + + id + getvmid1 + + + + + + rebootVirtualMachine + [46] rebootVirtualMachine-TestCase + + + id + getvmid1 + + + + + + createSnapshotPolicy + [47] createHOURLYSnapshotPolicyForRootVolume-TestCase + + + intervaltype + hourly + + + schedule + 11 + + + volumeid + getrootvolumeid1 + + + maxsnaps + 8 + + + timezone + America%2FLos_Angeles + + + + + + createSnapshotPolicy + [48] createDAILYSnapshotPolicy-TestCase + + + intervaltype + daily + + + schedule + 13:07 + + + volumeid + getrootvolumeid1 + + + maxsnaps + 8 + + + timezone + America%2FLos_Angeles + + + + + + createSnapshotPolicy + [49] createWEEKLYSnapshotPolicy-TestCase + + + intervaltype + weekly + + + schedule + 16:07:4 + + + volumeid + getrootvolumeid1 + + + maxsnaps + 8 + + + timezone + America%2FLos_Angeles + + + + + + createSnapshotPolicy + [50] createMONTHLYSnapshotPolicy-TestCase + + + intervaltype + monthly + + + schedule + 18:19:1 + + + volumeid + getrootvolumeid1 + + + maxsnaps + 8 + + + timezone + America%2FLos_Angeles + + + + + id + getmonthlysnapshotpolicyid1 + + + + + + deleteSnapshotPolicies + [51] deleteMONTHLYSnapshotPolicies-TestCase + + + id + getmonthlysnapshotpolicyid1 + + + + + + deleteVolume + [52] deleteVolume1-TestCase + + + id + getdatavolumeid2 + + + + + + deleteVolume + [53] deleteVolume2-TestCase + + + id + getdatavolumeid3 + + + + + + + + destroyVirtualMachine + [54] destroyVirtualMachine-TestCase + + + id + getvmid1 + + + + + + recoverVirtualMachine + [55] recoverVirtualMachine-TestCase + + + id + getvmid1 + + + + + + startVirtualMachine + [56] startVirtualMachine-TestCase + + + id + getvmid1 + + + + + + rebootVirtualMachine + [57] rebootVirtualMachine-TestCase + + + id + getvmid1 + + + + + + stopVirtualMachine + [58] stopVirtualMachine-TestCase + + + id + getvmid1 + + + + + + destroyVirtualMachine + [59] destroyVirtualMachine-TestCase + + + id + getvmid1 + + + + + + recoverVirtualMachine + [60] recoverVirtualMachine-TestCase + + + id + getvmid1 + + + + + + changeServiceForVirtualMachine + [61] changeServiceForVirtualMachine-TestCase + + + id + getvmid1 + + + serviceOfferingId + globalchangeservoff + + + + + + startVirtualMachine + [62] startVirtualMachine-TestCase + + + id + getvmid1 + + + + + + rebootVirtualMachine + [63] rebootVirtualMachine-TestCase + + + id + getvmid1 + + + + + + stopVirtualMachine + [64] stopVirtualMachine-TestCase + + + id + getvmid1 + + + + + + destroyVirtualMachine + [65] destroyVirtualMachine-TestCase + + + id + getvmid1 + + + + + + deployVirtualMachine + [66] deployVirtualMachineFromTemplateCreatedFromSnapshotofROOTVolume-TestCase + + + zoneId + globalzoneid + + + hypervisor + globalhypervisortype + + + templateId + gettemplateid1 + + + serviceOfferingId + servofferid + + + networkIds + getnetworkid1 + + + diskOfferingId + diskofferid + + + account + accountname + + + domainid + globaldomainid + + + + + id + getvmid1 + + + + + + deleteTemplate + [67] deleteTemplateofSnapshotTakenofROOTVolume-TestCase + + + id + gettemplateid1 + + + zoneid + globalzoneid + + + + + + deleteTemplate + [68] deleteTemplateofSnapshotTakenofDATAVolume-TestCase + + + id + gettemplateid2 + + + zoneid + globalzoneid + + + + + + deleteTemplate + [69] deleteTemplateCreatedFromROOTVolume-TestCase + + + id + gettemplateid3 + + + zoneid + globalzoneid + + + + + + deleteSnapshot + [70] deleteSnapshot-TestCase + + + id + getsnapshotid1 + + + + + + deleteSnapshot + [71] deleteSnapshot-TestCase + + + id + getsnapshotid2 + + + + + + + + + updateVirtualMachine + [3] updateVirtualMachine-TestCase + + + id + getvmid1 + + + displayName + First-VM + + + group + First-VM + + + haenable + false + + + ostypeid + 12 + + + + + + + + associateIpAddress + [4] associateIpAddress-TestCase + + + zoneid + globalzoneid + + + account + accountname + + + domainid + globaldomainid + + + + + id + getpublicipid1 + + + ipaddress + getipaddress1 + + + + + + enableStaticNat + [5] enableStaticNat-TestCase + + + ipaddressid + getpublicipid1 + + + virtualmachineid + getvmid1 + + + + + + createIpForwardingRule + [6] createIpForwardingRule-TestCase + + + ipaddressid + getpublicipid1 + + + startPort + 1 + + + endPort + 100 + + + protocol + TCP + + + + + id + getipfwdruleid1 + + + + + + sleep.sh + + Sleep for 2 min + + + s + 120 + + + + + + ssh.sh + + Ssh test for the vm + + + h + getipaddress1 + + + p + password + + + + + + deleteIpForwardingRule + [7] deleteIpForwardingRule-TestCase + + + id + getipfwdruleid1 + + + + + + disableStaticNat + [8] disableStaticNat-TestCase + + + ipaddressid + getpublicipid1 + + + + + + disassociateIpAddress + [9] disassociateIpAddress-TestCase + + + id + getpublicipid1 + + + + + + associateIpAddress + [10] associateIpAddress-TestCase + + + zoneid + globalzoneid + + + account + accountname + + + domainid + globaldomainid + + + + + id + getpublicipid1 + + + ipaddress + getipaddress1 + + + + + + createPortForwardingRule + [11] createPortForwardingRule-TestCase + + + ipaddressid + getpublicipid1 + + + cidrlist + 0.0.0.0/0 + + + publicport + 22 + + + publicendport + 30 + + + privateport + 22 + + + privateendport + 30 + + + protocol + TCP + + + virtualmachineid + getvmid1 + + + + + id + getportfwdruleid1 + + + + + + + + sleep.sh + + Sleep for 2 min + + + s + 120 + + + + + + ssh.sh + + Ssh test for the vm + + + h + getipaddress1 + + + p + password + + + + + + deletePortForwardingRule + [12] deletePortForwardingRule-TestCase + + + id + getportfwdruleid1 + + + + + + disassociateIpAddress + [13] disassociateIpAddress-TestCase + + + id + getpublicipid1 + + + + + + associateIpAddress + [14] associateIpAddress-TestCase + + + zoneid + globalzoneid + + + account + accountname + + + domainid + globaldomainid + + + + + id + getpublicipid1 + + + ipaddress + getipaddress1 + + + + + + createLoadBalancerRule + [15] createLoadBalancerRule-TestCase + + + publicipid + getpublicipid1 + + + name + LBRule-1 + + + publicport + 80 + + + privateport + 80 + + + algorithm + roundrobin + + + + + id + getldblcrule1 + + + + + + assignToLoadBalancerRule + [16] assignToLoadBalancerRule-TestCase + + + id + getldblcrule1 + + + virtualmachineids + getvmid1 + + + + + + + removeFromLoadBalancerRule + [18] removeFromLoadBalancerRule-TestCase + + + id + getldblcrule1 + + + virtualmachineids + getvmid1 + + + + + + updateLoadBalancerRule + [19] updateLoadBalancerRule-TestCase + + + id + getldblcrule1 + + + name + LBRuleUpdated-1 + + + algorithm + roundrobin + + + + + + disassociateIpAddress + [20] disassociateIpAddress-TestCase + + + id + getpublicipid1 + + + + + + associateIpAddress + [14] associateIpAddress-TestCase + + + zoneid + globalzoneid + + + account + accountname + + + domainid + globaldomainid + + + + + id + getpublicipid1 + + + + + + createLoadBalancerRule + [21] createLoadBalancerRule-TestCase + + + publicipid + getpublicipid1 + + + name + LBRule-2 + + + publicport + 80 + + + privateport + 80 + + + algorithm + roundrobin + + + + + id + getldblcrule1 + + + + + + assignToLoadBalancerRule + [22] assignToLoadBalancerRule-TestCase + + + id + getldblcrule1 + + + virtualmachineids + getvmid1 + + + + + + + deleteLoadBalancerRule + [24] deleteLoadBalancerRule-TestCase + + + id + getldblcrule1 + + + + + + disassociateIpAddress + [25] disassociateIpAddress-TestCase + + + id + getpublicipid1 + + + + + + + listVolumes + [26] listROOTVolumes-TestCase + + + virtualmachineid + getvmid1 + + + type + ROOT + + + + + id + getrootvolumeid1 + + + + + + createSnapshot + [26] createSnapshotofROOTVolume-TestCase + + + volumeid + getrootvolumeid1 + + + account + accountname + + + domainid + globaldomainid + + + + + id + getsnapshotid1 + + + + + + listSnapshots + [27] listROOTVolumeSnapshot-TestCase + + + volumeid + getrootvolumeid1 + + + + + + listVolumes + [26] listDATADISKVolumes-TestCase + + + virtualmachineid + getvmid1 + + + type + DATADISK + + + + + id + getdatavolumeid1 + + + + + + createSnapshot + [28] createSnapshotofDATADISKVolume-TestCase + + + volumeid + getdatavolumeid1 + + + account + accountname + + + domainid + globaldomainid + + + + + id + getsnapshotid2 + + + + + + listSnapshots + [29] listDATADISKVolumeSnapshot-TestCase + + + volumeid + getdatavolumeid1 + + + + + + createTemplate + [30] createTemplateFromSnapshotTakenofROOTVolume-TestCase + + + snapshotid + getsnapshotid1 + + + name + TemplateFromSnapshot-4 + + + displaytext + TemplateFromSnapshot-4 + + + ostypeid + 12 + + + isPublic + true + + + passwordEnabled + false + + + isfeatured + true + + + + + id + gettemplateid1 + + + + + + createTemplate + [31] createTemplateFromSnapshotTakenofDATADISKVolume-TestCase + + + snapshotid + getsnapshotid2 + + + name + TemplateFromSnapshot-5 + + + displaytext + TemplateFromSnapshot-5 + + + ostypeid + 12 + + + isPublic + true + + + passwordEnabled + false + + + isfeatured + true + + + + + id + gettemplateid2 + + + + + + createVolume + [32] createVolumeFromSnapshotTakenofROOTVolume-TestCase + + + snapshotid + getsnapshotid1 + + + name + VlmfromSnapshot-1 + + + account + accountname + + + domainid + globaldomainid + + + + + id + getdatavolumeid2 + + + + + + createVolume + [33] createVolumeFromSnapshotTakenofDATADISKVolume-TestCase + + + snapshotid + getsnapshotid2 + + + name + VlmfromSnapshot-2 + + + account + accountname + + + domainid + globaldomainid + + + + + id + getdatavolumeid3 + + + + + + + attachVolume + [34] attachVolume1-TestCase + + + id + getdatavolumeid2 + + + virtualMachineId + getvmid1 + + + + + + attachVolume + [35] attachVolume2-TestCase + + + id + getdatavolumeid3 + + + virtualMachineId + getvmid1 + + + + + + + + detachVolume + [36] detachVolume1-TestCase + + + id + getdatavolumeid2 + + + + + + detachVolume + [37] detachVolume2-TestCase + + + id + getdatavolumeid3 + + + + + + attachVolume + [34] attachVolume1-TestCase + + + id + getdatavolumeid2 + + + virtualMachineId + getvmid1 + + + + + + attachVolume + [35] attachVolume2-TestCase + + + id + getdatavolumeid3 + + + virtualMachineId + getvmid1 + + + + + + stopVirtualMachine + [40] stopVirtualMachine-TestCase + + + id + getvmid1 + + + + + + updateVirtualMachine + [41] updateVirtualMachine-TestCase + + + id + getvmid1 + + + displayName + First-VM-1-1 + + + group + First-VM-1-1 + + + haenable + false + + + ostypeid + 12 + + + + + + detachVolume + [36] detachVolume1-TestCase + + + id + getdatavolumeid2 + + + + + + detachVolume + [37] detachVolume2-TestCase + + + id + getdatavolumeid3 + + + + + + createTemplate + [44] createTemplateFromROOTVolume-TestCase + + + volumeId + getrootvolumeid1 + + + name + TemplateFromRootVolume-6 + + + displayText + TemplateFromRootVolume-6 + + + osTypeId + 12 + + + isPublic + true + + + passwordEnabled + false + + + + + id + gettemplateid3 + + + + + + startVirtualMachine + [45] startVirtualMachine-TestCase + + + id + getvmid1 + + + + + + rebootVirtualMachine + [46] rebootVirtualMachine-TestCase + + + id + getvmid1 + + + + + + createSnapshotPolicy + [47] createHOURLYSnapshotPolicyForRootVolume-TestCase + + + intervaltype + hourly + + + schedule + 11 + + + volumeid + getrootvolumeid1 + + + maxsnaps + 8 + + + timezone + America%2FLos_Angeles + + + + + + createSnapshotPolicy + [48] createDAILYSnapshotPolicy-TestCase + + + intervaltype + daily + + + schedule + 13:07 + + + volumeid + getrootvolumeid1 + + + maxsnaps + 8 + + + timezone + America%2FLos_Angeles + + + + + + createSnapshotPolicy + [49] createWEEKLYSnapshotPolicy-TestCase + + + intervaltype + weekly + + + schedule + 16:07:4 + + + volumeid + getrootvolumeid1 + + + maxsnaps + 8 + + + timezone + America%2FLos_Angeles + + + + + + createSnapshotPolicy + [50] createMONTHLYSnapshotPolicy-TestCase + + + intervaltype + monthly + + + schedule + 18:19:1 + + + volumeid + getrootvolumeid1 + + + maxsnaps + 8 + + + timezone + America%2FLos_Angeles + + + + + id + getmonthlysnapshotpolicyid1 + + + + + + deleteSnapshotPolicies + [51] deleteMONTHLYSnapshotPolicies-TestCase + + + id + getmonthlysnapshotpolicyid1 + + + + + + deleteVolume + [52] deleteVolume1-TestCase + + + id + getdatavolumeid2 + + + + + + deleteVolume + [53] deleteVolume2-TestCase + + + id + getdatavolumeid3 + + + + + + + + destroyVirtualMachine + [54] destroyVirtualMachine-TestCase + + + id + getvmid1 + + + + + + recoverVirtualMachine + [55] recoverVirtualMachine-TestCase + + + id + getvmid1 + + + + + + startVirtualMachine + [56] startVirtualMachine-TestCase + + + id + getvmid1 + + + + + + rebootVirtualMachine + [57] rebootVirtualMachine-TestCase + + + id + getvmid1 + + + + + + stopVirtualMachine + [58] stopVirtualMachine-TestCase + + + id + getvmid1 + + + + + + destroyVirtualMachine + [59] destroyVirtualMachine-TestCase + + + id + getvmid1 + + + + + + recoverVirtualMachine + [60] recoverVirtualMachine-TestCase + + + id + getvmid1 + + + + + + changeServiceForVirtualMachine + [61] changeServiceForVirtualMachine-TestCase + + + id + getvmid1 + + + serviceOfferingId + globalchangeservoff + + + + + + startVirtualMachine + [62] startVirtualMachine-TestCase + + + id + getvmid1 + + + + + + rebootVirtualMachine + [63] rebootVirtualMachine-TestCase + + + id + getvmid1 + + + + + + stopVirtualMachine + [64] stopVirtualMachine-TestCase + + + id + getvmid1 + + + + + + destroyVirtualMachine + [65] destroyVirtualMachine-TestCase + + + id + getvmid1 + + + + + + + + + + + + + + + updateVirtualMachine + [3] updateVirtualMachine-TestCase + + + id + globalisovmid1 + + + displayName + ISO-Third-VM + + + group + ISO-Third-VM + + + haenable + false + + + ostypeid + 112 + + + + + + + + associateIpAddress + [4] associateIpAddress-TestCase + + + zoneid + globalzoneid + + + account + accountname + + + domainid + globaldomainid + + + + + id + getpublicipid1 + + + ipaddress + getipaddress1 + + + + + + enableStaticNat + [5] enableStaticNat-TestCase + + + ipaddressid + getpublicipid1 + + + virtualmachineid + globalisovmid1 + + + + + + createIpForwardingRule + [6] createIpForwardingRule-TestCase + + + ipaddressid + getpublicipid1 + + + startPort + 1 + + + endPort + 100 + + + protocol + TCP + + + + + id + getipfwdruleid1 + + + + + + sleep.sh + + Sleep for 2 min + + + s + 120 + + + + + + ssh.sh + + Ssh test for the vm + + + h + getipaddress1 + + + p + password + + + + + + deleteIpForwardingRule + [7] deleteIpForwardingRule-TestCase + + + id + getipfwdruleid1 + + + + + + disableStaticNat + [8] disableStaticNat-TestCase + + + ipaddressid + getpublicipid1 + + + + + + disassociateIpAddress + [9] disassociateIpAddress-TestCase + + + id + getpublicipid1 + + + + + + associateIpAddress + [10] associateIpAddress-TestCase + + + zoneid + globalzoneid + + + account + accountname + + + domainid + globaldomainid + + + + + id + getpublicipid1 + + + ipaddress + getipaddress1 + + + + + + createPortForwardingRule + [11] createPortForwardingRule-TestCase + + + ipaddressid + getpublicipid1 + + + cidrlist + 0.0.0.0/0 + + + publicport + 22 + + + publicendport + 30 + + + privateport + 22 + + + privateendport + 30 + + + protocol + TCP + + + virtualmachineid + globalisovmid1 + + + + + id + getportfwdruleid1 + + + + + + + + sleep.sh + + Sleep for 2 min + + + s + 120 + + + + + + ssh.sh + + Ssh test for the vm + + + h + getipaddress1 + + + p + password + + + + + + deletePortForwardingRule + [12] deletePortForwardingRule-TestCase + + + id + getportfwdruleid1 + + + + + + disassociateIpAddress + [13] disassociateIpAddress-TestCase + + + id + getpublicipid1 + + + + + + associateIpAddress + [14] associateIpAddress-TestCase + + + zoneid + globalzoneid + + + account + accountname + + + domainid + globaldomainid + + + + + id + getpublicipid1 + + + ipaddress + getipaddress1 + + + + + + createLoadBalancerRule + [15] createLoadBalancerRule-TestCase + + + publicipid + getpublicipid1 + + + name + LBRule-1 + + + publicport + 80 + + + privateport + 80 + + + algorithm + roundrobin + + + + + id + getldblcrule1 + + + + + + assignToLoadBalancerRule + [16] assignToLoadBalancerRule-TestCase + + + id + getldblcrule1 + + + virtualmachineids + globalisovmid1 + + + + + + + removeFromLoadBalancerRule + [18] removeFromLoadBalancerRule-TestCase + + + id + getldblcrule1 + + + virtualmachineids + globalisovmid1 + + + + + + updateLoadBalancerRule + [19] updateLoadBalancerRule-TestCase + + + id + getldblcrule1 + + + name + LBRuleUpdated-1 + + + algorithm + roundrobin + + + + + + disassociateIpAddress + [20] disassociateIpAddress-TestCase + + + id + getpublicipid1 + + + + + + associateIpAddress + [14] associateIpAddress-TestCase + + + zoneid + globalzoneid + + + account + accountname + + + domainid + globaldomainid + + + + + id + getpublicipid1 + + + + + + createLoadBalancerRule + [21] createLoadBalancerRule-TestCase + + + publicipid + getpublicipid1 + + + name + LBRule-2 + + + publicport + 80 + + + privateport + 80 + + + algorithm + roundrobin + + + + + id + getldblcrule1 + + + + + + assignToLoadBalancerRule + [22] assignToLoadBalancerRule-TestCase + + + id + getldblcrule1 + + + virtualmachineids + globalisovmid1 + + + + + + + + deleteLoadBalancerRule + [24] deleteLoadBalancerRule-TestCase + + + id + getldblcrule1 + + + + + + disassociateIpAddress + [25] disassociateIpAddress-TestCase + + + id + getpublicipid1 + + + + + + + listVolumes + [26] listROOTVolumes-TestCase + + + virtualmachineid + globalisovmid1 + + + type + ROOT + + + + + id + getrootvolumeid1 + + + + + + createSnapshot + [26] createSnapshotofROOTVolume-TestCase + + + volumeid + getrootvolumeid1 + + + account + accountname + + + domainid + globaldomainid + + + + + id + getsnapshotid1 + + + + + + listSnapshots + [27] listROOTVolumeSnapshot-TestCase + + + volumeid + getrootvolumeid1 + + + + + + listVolumes + [26] listDATADISKVolumes-TestCase + + + virtualmachineid + globalisovmid1 + + + type + DATADISK + + + + + id + getdatavolumeid1 + + + + + + createSnapshot + [28] createSnapshotofDATADISKVolume-TestCase + + + volumeid + getdatavolumeid1 + + + account + accountname + + + domainid + globaldomainid + + + + + id + getsnapshotid2 + + + + + + listSnapshots + [29] listDATADISKVolumeSnapshot-TestCase + + + volumeid + getdatavolumeid1 + + + + + + createTemplate + [30] createTemplateFromSnapshotTakenofROOTVolume-TestCase + + + snapshotid + getsnapshotid1 + + + name + TemplateFromSnapshot-1 + + + displaytext + TemplateFromSnapshot-1 + + + ostypeid + 12 + + + isPublic + true + + + passwordEnabled + false + + + isfeatured + true + + + + + id + gettemplateid1 + + + + + + createTemplate + [31] createTemplateFromSnapshotTakenofDATADISKVolume-TestCase + + + snapshotid + getsnapshotid2 + + + name + TemplateFromSnapshot-2 + + + displaytext + TemplateFromSnapshot-2 + + + ostypeid + 12 + + + isPublic + true + + + passwordEnabled + false + + + isfeatured + true + + + + + id + gettemplateid2 + + + + + + createVolume + [32] createVolumeFromSnapshotTakenofROOTVolume-TestCase + + + snapshotid + getsnapshotid1 + + + name + VlmfromSnapshot-1 + + + account + accountname + + + domainid + globaldomainid + + + + + id + getdatavolumeid2 + + + + + + createVolume + [33] createVolumeFromSnapshotTakenofDATADISKVolume-TestCase + + + snapshotid + getsnapshotid2 + + + name + VlmfromSnapshot-2 + + + account + accountname + + + domainid + globaldomainid + + + + + id + getdatavolumeid3 + + + + + + + attachVolume + [34] attachVolume1-TestCase + + + id + getdatavolumeid2 + + + virtualMachineId + globalisovmid1 + + + + + + attachVolume + [35] attachVolume2-TestCase + + + id + getdatavolumeid3 + + + virtualMachineId + globalisovmid1 + + + + + + + + detachVolume + [36] detachVolume1-TestCase + + + id + getdatavolumeid2 + + + + + + detachVolume + [37] detachVolume2-TestCase + + + id + getdatavolumeid3 + + + + + + attachVolume + [34] attachVolume1-TestCase + + + id + getdatavolumeid2 + + + virtualMachineId + globalisovmid1 + + + + + + attachVolume + [35] attachVolume2-TestCase + + + id + getdatavolumeid3 + + + virtualMachineId + globalisovmid1 + + + + + + stopVirtualMachine + [40] stopVirtualMachine-TestCase + + + id + globalisovmid1 + + + + + + updateVirtualMachine + [41] updateVirtualMachine-TestCase + + + id + globalisovmid1 + + + displayName + First-VM-1-1 + + + group + First-VM-1-1 + + + haenable + false + + + ostypeid + 12 + + + + + + detachVolume + [36] detachVolume1-TestCase + + + id + getdatavolumeid2 + + + + + + detachVolume + [37] detachVolume2-TestCase + + + id + getdatavolumeid3 + + + + + + createTemplate + [44] createTemplateFromROOTVolume-TestCase + + + volumeId + getrootvolumeid1 + + + name + TemplateFromRootVolume-3 + + + displayText + TemplateFromRootVolume-3 + + + osTypeId + 12 + + + isPublic + true + + + passwordEnabled + false + + + + + id + gettemplateid3 + + + + + + startVirtualMachine + [45] startVirtualMachine-TestCase + + + id + globalisovmid1 + + + + + + rebootVirtualMachine + [46] rebootVirtualMachine-TestCase + + + id + globalisovmid1 + + + + + + createSnapshotPolicy + [47] createHOURLYSnapshotPolicyForRootVolume-TestCase + + + intervaltype + hourly + + + schedule + 11 + + + volumeid + getrootvolumeid1 + + + maxsnaps + 8 + + + timezone + America%2FLos_Angeles + + + + + + createSnapshotPolicy + [48] createDAILYSnapshotPolicy-TestCase + + + intervaltype + daily + + + schedule + 13:07 + + + volumeid + getrootvolumeid1 + + + maxsnaps + 8 + + + timezone + America%2FLos_Angeles + + + + + + createSnapshotPolicy + [49] createWEEKLYSnapshotPolicy-TestCase + + + intervaltype + weekly + + + schedule + 16:07:4 + + + volumeid + getrootvolumeid1 + + + maxsnaps + 8 + + + timezone + America%2FLos_Angeles + + + + + + createSnapshotPolicy + [50] createMONTHLYSnapshotPolicy-TestCase + + + intervaltype + monthly + + + schedule + 18:19:1 + + + volumeid + getrootvolumeid1 + + + maxsnaps + 8 + + + timezone + America%2FLos_Angeles + + + + + id + getmonthlysnapshotpolicyid1 + + + + + + deleteSnapshotPolicies + [51] deleteMONTHLYSnapshotPolicies-TestCase + + + id + getmonthlysnapshotpolicyid1 + + + + + + deleteVolume + [52] deleteVolume1-TestCase + + + id + getdatavolumeid2 + + + + + + deleteVolume + [53] deleteVolume2-TestCase + + + id + getdatavolumeid3 + + + + + + + + destroyVirtualMachine + [54] destroyVirtualMachine-TestCase + + + id + globalisovmid1 + + + + + + recoverVirtualMachine + [55] recoverVirtualMachine-TestCase + + + id + globalisovmid1 + + + + + + startVirtualMachine + [56] startVirtualMachine-TestCase + + + id + globalisovmid1 + + + + + + rebootVirtualMachine + [57] rebootVirtualMachine-TestCase + + + id + globalisovmid1 + + + + + + stopVirtualMachine + [58] stopVirtualMachine-TestCase + + + id + globalisovmid1 + + + + + + destroyVirtualMachine + [59] destroyVirtualMachine-TestCase + + + id + globalisovmid1 + + + + + + recoverVirtualMachine + [60] recoverVirtualMachine-TestCase + + + id + globalisovmid1 + + + + + + changeServiceForVirtualMachine + [61] changeServiceForVirtualMachine-TestCase + + + id + globalisovmid1 + + + serviceOfferingId + globalchangeservoff + + + + + + startVirtualMachine + [62] startVirtualMachine-TestCase + + + id + globalisovmid1 + + + + + + rebootVirtualMachine + [63] rebootVirtualMachine-TestCase + + + id + globalisovmid1 + + + + + + stopVirtualMachine + [64] stopVirtualMachine-TestCase + + + id + globalisovmid1 + + + + + + destroyVirtualMachine + [65] destroyVirtualMachine-TestCase + + + id + globalisovmid1 + + + + + + deployVirtualMachine + [66] deployVirtualMachineFromTemplateCreatedFromSnapshotofROOTVolume-TestCase + + + zoneId + globalzoneid + + + hypervisor + globalhypervisortype + + + templateId + gettemplateid1 + + + serviceOfferingId + servofferid + + + networkIds + getnetworkid1 + + + diskOfferingId + diskofferid + + + account + accountname + + + domainid + globaldomainid + + + + + id + getvmid1 + + + + + + deleteTemplate + [67] deleteTemplateofSnapshotTakenofROOTVolume-TestCase + + + id + gettemplateid1 + + + zoneid + globalzoneid + + + + + + deleteTemplate + [68] deleteTemplateofSnapshotTakenofDATAVolume-TestCase + + + id + gettemplateid2 + + + zoneid + globalzoneid + + + + + + deleteTemplate + [69] deleteTemplateCreatedFromROOTVolume-TestCase + + + id + gettemplateid3 + + + zoneid + globalzoneid + + + + + + deleteSnapshot + [70] deleteSnapshot-TestCase + + + id + getsnapshotid1 + + + + + + deleteSnapshot + [71] deleteSnapshot-TestCase + + + id + getsnapshotid2 + + + + + + + + + + extractIso + [] extractIsoTestCase + + + id + getisoid1 + + + zoneid + 1 + + + mode + HTTP_DOWNLOAD + + + + + + deleteIso + [] deleteIsoTestCase + + + id + getisoid1 + + + zoneid + 1 + + + + + + deleteAccount + [72] deleteAccount-TestCase + + + id + getaccountid + + + + diff --git a/test/metadata/func/sanity.xml b/test/metadata/func/sanity.xml new file mode 100644 index 00000000000..cc86611a44d --- /dev/null +++ b/test/metadata/func/sanity.xml @@ -0,0 +1,360 @@ + + + + + + createAccount + [Create the Account and a User for the account] + + + account + accountname + + + accounttype + 1 + + + domainid + 1 + + + email + admin@gmail.com + + + firstname + admin + + + lastname + adminlastname + + + username + usernameparam + + + password + password + + + + + id + accountid + + + + + + + createNetwork + [Creating default network] + + + zoneid + globalzoneid + + + networkOfferingId + globalnetworkofferingid + + + account + accountname + + + domainid + 1 + + + name + defaultregressionnetwork + + + displaytext + defaultregressionnetwork + + + + + id + networkid + + + + + + deployVirtualMachine + [Deploy a Virtual Machine under the Account] + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + templateid + globaltemplateid + + + account + accountname + + + domainid + 1 + + + networkids + networkid + + + + + id + vmid + + + name + vmname + + + ipaddress + vmipaddress + + + + + + + associateIpAddress + [Acquire an IP Address (Non-Source NAT*)] + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + + id + nonsourcenatpublicipid + + + ipaddress + nonsourcenatpublicip + + + + + + disassociateIpAddress + [Release the IP Address (Non-Source NAT*)] + + + id + nonsourcenatpublicipid + + + + + + rebootVirtualMachine + [Reboot Virtual Machine] + + + id + vmid + + + + + + stopVirtualMachine + [Stop virtual machine] + + + id + vmid + + + + + + startVirtualMachine + [Start virtual machine] + + + id + vmid + + + + + state + Running + + + + + + + listRouters + [List Routers] + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + + id + routerid + + + + + + + stopRouter + [Stop router] + + + id + routerid + + + + + + startRouter + [Start router] + + + id + routerid + + + + + state + Running + + + + + + destroyVirtualMachine + [Destroy virtual machine] + + + id + vmid + + + + + + listVirtualMachines + [Verify that vm was destroyed] + + + id + vmid + + + + + state + Destroyed + + + + + + recoverVirtualMachine + [Recover virtual machine] + + + id + vmid + + + + + + listVirtualMachines + [Verify that machine was recovered] + + + account + accountname + + + id + vmid + + + + + state + Stopped + + + + + + deleteAccount + [Delete account] + + + id + accountid + + + + + + \ No newline at end of file diff --git a/test/metadata/func/securitygroups.xml b/test/metadata/func/securitygroups.xml new file mode 100644 index 00000000000..74e0f8d6a69 --- /dev/null +++ b/test/metadata/func/securitygroups.xml @@ -0,0 +1,752 @@ + + + + + createUser + Create User and Account + + + username + + + password + apiuser + + + firstname + apiuser + + + lastname + apiuser + + + email + apiuser@gmail.com + + + accounttype + 0 + + + + + id + userid + + + account + accountname + + + + + + registerUserKeys + Registering the User + + + id + userid + + + + + apikey + apikey + + + secretkey + secretkey + + + + + + createNetworkGroup + true + Create a Network Group + + + name + networkgrp-1 + + + + + + + + authorizeNetworkGroupIngress + Add the First Ingress Rule + + + networkgroupname + networkgrp-1 + + + cidrlist + 192.168.131.171/32 + + + endport + 22 + + + startport + 22 + + + protocol + tcp + + + account + accountname + + + domainid + 1 + + + + + + deployVirtualMachine + true + Deploy a VM with the Network Group Assigned + + + zoneid + globalzoneid + + + serviceofferingid + flatnetworkserviceofferingid + + + networkgrouplist + networkgrp-1 + + + templateid + globaltemplateid + + + + + id + vmid + + + ipaddress + vmip + + + + + + sleep.sh + + Sleep for 2 min + + + s + 120 + + + + + + ssh.sh + + Ssh access test for the VM + + + h + vmip + + + p + password + + + + + + sleep.sh + + Sleep for 1 min + + + s + 60 + + + + + + stopVirtualMachine + true + Stopping VM + + + id + vmid + + + + + + startVirtualMachine + true + Starting VM + + + id + vmid + + + + + + rebootVirtualMachine + true + Rebooting VM + + + id + vmid + + + + + + revokeNetworkGroupIngress + Revoke The First Ingress Rule + + + networkgroupname + networkgrp-1 + + + cidrlist + 192.168.131.171/32 + + + endport + 22 + + + startport + 22 + + + protocol + tcp + + + account + accountname + + + domainid + 1 + + + + + + ssh.sh + + true + Ssh access test for the vm - should fail as ingress rule is revoked + + + h + vmip + + + p + password + + + + + + + + authorizeNetworkGroupIngress + Add the Second Ingress Rule + + + networkgroupname + networkgrp-1 + + + cidrlist + 192.168.131.172/32 + + + endport + 22 + + + startport + 22 + + + protocol + tcp + + + account + accountname + + + domainid + 1 + + + + + + deployVirtualMachine + true + Deploy a VM with the Network Group Assigned + + + zoneid + globalzoneid + + + serviceofferingid + flatnetworkserviceofferingid + + + networkgrouplist + networkgrp-1 + + + templateid + globaltemplateid + + + + + id + vmid + + + ipaddress + vmip + + + + + + sleep.sh + + Sleep for 2 min + + + s + 120 + + + + + + ssh.sh + + true + Ssh test for the vm - should fail as no access provided by ingress rule + + + h + vmip + + + p + password + + + + + + revokeNetworkGroupIngress + Revoke The Second Ingress Rule + + + networkgroupname + networkgrp-1 + + + cidrlist + 192.168.131.172/32 + + + endport + 22 + + + startport + 22 + + + protocol + tcp + + + account + accountname + + + domainid + 1 + + + + + + + + authorizeNetworkGroupIngress + Add the Third Ingress Rule + + + networkgroupname + networkgrp-1 + + + cidrlist + 192.168.131.0/24 + + + endport + 80 + + + startport + 80 + + + protocol + tcp + + + account + accountname + + + domainid + 1 + + + + + + deployVirtualMachine + true + Deploy a VM with the Network Group Assigned + + + zoneid + globalzoneid + + + serviceofferingid + flatnetworkserviceofferingid + + + networkgrouplist + networkgrp-1 + + + templateid + globaltemplateid + + + + + id + vmid + + + ipaddress + vmip + + + + + + sleep.sh + + Sleep for 2 min + + + s + 120 + + + + + + ssh.sh + + true + Ssh test for the vm - should fail as no access provided by ingress rule + + + h + vmip + + + p + password + + + + + + revokeNetworkGroupIngress + Revoke The Third Ingress Rule + + + networkgroupname + networkgrp-1 + + + cidrlist + 192.168.131.0/24 + + + endport + 80 + + + startport + 80 + + + protocol + tcp + + + account + accountname + + + domainid + 1 + + + + + + + + authorizeNetworkGroupIngress + Add the Fourth Ingress Rule + + + networkgroupname + networkgrp-1 + + + cidrlist + 192.168.130.0/24 + + + endport + 80 + + + startport + 80 + + + protocol + tcp + + + account + accountname + + + domainid + 1 + + + + + + deployVirtualMachine + true + Deploy a VM with the Network Group Assigned + + + zoneid + globalzoneid + + + serviceofferingid + flatnetworkserviceofferingid + + + networkgrouplist + networkgrp-1 + + + templateid + globaltemplateid + + + + + id + vmid + + + ipaddress + vmip + + + + + + sleep.sh + + Sleep for 2 min + + + s + 120 + + + + + + ssh.sh + + true + Ssh test for the vm - should fail as no access provided by ingress rule + + + h + vmip + + + p + password + + + + + + revokeNetworkGroupIngress + Revoke The Fourth Ingress Rule + + + networkgroupname + networkgrp-1 + + + cidrlist + 192.168.130.0/24 + + + endport + 80 + + + startport + 80 + + + protocol + tcp + + + account + accountname + + + domainid + 1 + + + + + + + + deleteNetworkGroup + true + Delete First network group + + + name + networkgrp-1 + + + + + + destroyVirtualMachine + true + Destroying virutal machine + + + id + vmid + + + + + + sleep.sh + + Sleep for 2 min + + + s + 120 + + + + + + + + deleteUser + Deleting the user + + + id + userid + + + + + \ No newline at end of file diff --git a/test/metadata/func/sharedstorage_volume_test.xml b/test/metadata/func/sharedstorage_volume_test.xml new file mode 100644 index 00000000000..287250ebb1f --- /dev/null +++ b/test/metadata/func/sharedstorage_volume_test.xml @@ -0,0 +1,1356 @@ + + + + + createAccount + [Create the Account and a User for the account] + + + account + accountvar + + + accounttype + 0 + + + domainid + 1 + + + email + apiuser@gmail.com + + + firstname + apiuser + + + lastname + apiuserlastname + + + username + usernameparam + + + password + password + + + + + id + accountid + + + name + accountvar + + + + + + + + listUsers + 5 [List the Created User in (3)] + + + account + accountvar + + + + + id + userid + + + + + + + + registerUserKeys + + + id + userid + + + + + apikey + apikey + + + secretkey + secretkey + + + + + + createNetwork + [Creating default network] + + + zoneid + globalzoneid + + + networkOfferingId + globalnetworkofferingid + + + account + accountvar + + + domainid + 1 + + + name + sharedstoragevolumeregressionnetwork + + + displaytext + sharedstoragevolumeregressionnetwork + + + + + id + networkid + + + + + + + deployVirtualMachine + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + accountvar + + + domainid + 1 + + + displayname + SharedStorage-VM-1 + + + group + group1 + + + networkids + networkid + + + + + id + vmid + + + + + + createVolume + true + + + name + + + zoneid + globalzoneid + + + diskofferingid + globaldiskofferingid + + + + + id + volumeid + + + + + + attachVolume + true + 1028 + + + id + volumeid + + + virtualmachineid + vmid + + + + + + + + stopVirtualMachine + true + + + id + vmid + + + + + + createVolume + true + + + name + + + zoneid + globalzoneid + + + diskofferingid + globaldiskofferingid + + + + + id + volumeid + + + + + + attachVolume + true + 1029 + + + id + volumeid + + + virtualmachineid + vmid + + + + + + + + createVolume + true + 1030 + + + name + + + zoneid + globalzoneid + + + diskofferingid + globaldiskofferingid + + + + + type + DATADISK + + + + + + + + deployVirtualMachine + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + accountvar + + + domainid + 1 + + + displayname + SharedStorage-VM-2 + + + group + group1 + + + networkids + networkid + + + + + id + vmid + + + + + + listVolumes + + + virtualmachineid + vmid + + + type + DATADISK + + + + + id + datavolumeid + + + + + + detachVolume + true + 1031 + + + id + datavolumeid + + + + + + + + listVolumes + + + virtualmachineid + vmid + + + type + ROOT + + + + + id + rootvolumeid + + + + + + detachVolume + true + 1033 + true + + + id + datavolumeid + + + + + + + + deployVirtualMachine + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + accountvar + + + domainid + 1 + + + displayname + SharedStorage-VM-3 + + + group + group1 + + + networkids + networkid + + + + + id + vmid + + + + + + createVolume + true + + + name + + + zoneid + globalzoneid + + + diskofferingid + globaldiskofferingid + + + + + id + volume1 + + + + + + createVolume + true + + + name + + + zoneid + globalzoneid + + + diskofferingid + globaldiskofferingid + + + + + id + volume2 + + + + + + createVolume + true + + + name + + + zoneid + globalzoneid + + + diskofferingid + globaldiskofferingid + + + + + id + volume3 + + + + + + createVolume + true + + + name + + + zoneid + globalzoneid + + + diskofferingid + globaldiskofferingid + + + + + id + volume4 + + + + + + createVolume + true + + + name + + + zoneid + globalzoneid + + + diskofferingid + globaldiskofferingid + + + + + id + volume5 + + + + + + attachVolume + true + + + id + volume1 + + + virtualmachineid + vmid + + + + + + attachVolume + true + + + id + volume2 + + + virtualmachineid + vmid + + + + + + attachVolume + true + + + id + volume3 + + + virtualmachineid + vmid + + + + + + attachVolume + true + + + id + volume4 + + + virtualmachineid + vmid + + + + + + attachVolume + true + 1035 + + + id + volume5 + + + virtualmachineid + vmid + + + + + + + + rebootVirtualMachine + true + 1036 + + + id + vmid + + + + + + + stopVirtualMachine + true + 1037 + + + id + vmid + + + + + + startVirtualMachine + true + 1037 + + + id + vmid + + + + + + + + createVolume + true + + + name + + + zoneid + globalzoneid + + + diskofferingid + globaldiskofferingid + + + + + id + volume6 + + + + + + attachVolume + true + true + 1039 + + + id + volume6 + + + virtualmachineid + vmid + + + + + + + + destroyVirtualMachine + true + 1038 + + + id + vmid + + + + + + listVolumes + true + 1038 + + + virtualmachineid + vmid + + + type + DATADISK + + + + + + + + deployVirtualMachine + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + accountvar + + + domainid + 1 + + + displayname + SharedStorage-VM-4 + + + group + group1 + + + networkids + networkid + + + + + id + vmid + + + + + + listVolumes + + + virtualmachineid + vmid + + + type + DATADISK + + + + + id + datavolumeid + + + + + + detachVolume + true + + + id + datavolumeid + + + + + + rebootVirtualMachine + true + 1040 + + + id + vmid + + + + + + + stopVirtualMachine + true + + + id + vmid + + + + + + startVirtualMachine + true + 1041 + + + id + vmid + + + + + + + + + deployVirtualMachine + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + accountvar + + + domainid + 1 + + + displayname + SharedStorage-VM-5 + + + group + group1 + + + networkids + networkid + + + + + id + vmid + + + + + + listVolumes + + + virtualmachineid + vmid + + + type + DATADISK + + + + + id + datavolumeid + + + + + + detachVolume + true + 1044 + + + id + datavolumeid + + + + + + listVolumes + true + 1044 + + + virtualmachineid + vmid + + + type + DATADISK + + + + + + + attachVolume + true + + + id + datavolumeid + + + virtualmachineid + vmid + + + + + + stopVirtualMachine + true + + + id + vmid + + + + + + detachVolume + true + 1045 + + + id + datavolumeid + + + + + + listVolumes + true + 1045 + + + virtualmachineid + vmid + + + type + DATADISK + + + + + + + deployVirtualMachine + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + accountvar + + + domainid + 1 + + + displayname + SharedStorage-VM-6 + + + group + group1 + + + networkids + networkid + + + + + id + vmid1 + + + + + + deployVirtualMachine + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + accountvar + + + domainid + 1 + + + displayname + SharedStorage-VM-7 + + + group + group1 + + + networkids + networkid + + + + + id + vmid2 + + + + + + createVolume + true + + + name + + + zoneid + globalzoneid + + + diskofferingid + globaldiskofferingid + + + + + id + volumeid + + + + + + attachVolume + true + + + id + volumeid + + + virtualmachineid + vmid1 + + + + + + attachVolume + true + true + 1046 + + + id + volumeid + + + virtualmachineid + vmid2 + + + + + + + destroyVirtualMachine + true + + + id + vmid1 + + + + + + createVolume + true + + + name + + + zoneid + globalzoneid + + + diskofferingid + globaldiskofferingid + + + + + id + volumeid + + + + + + attachVolume + true + 1081 + true + + + id + volumeid + + + virtualmachineid + vmid1 + + + + + + + listVolumes + + + virtualmachineid + vmid2 + + + type + DATADISK + + + + + id + datavolumeid + + + + + + destroyVirtualMachine + true + + + id + vmid2 + + + + + + detachVolume + true + 1082 + true + + + id + datavolumeid + + + + + + + + deleteAccount + Deleting Account as a part of cleanup + + + id + accountid + + + + + + \ No newline at end of file diff --git a/test/metadata/func/snapshot_iso.xml b/test/metadata/func/snapshot_iso.xml new file mode 100644 index 00000000000..a15636831ee --- /dev/null +++ b/test/metadata/func/snapshot_iso.xml @@ -0,0 +1,628 @@ + + + + + + + createUser + Create a user + + + + username + + + password + apiuser + + + firstname + apiuser + + + lastname + apiuser + + + email + apiuser@gmail.com + + + accounttype + 0 + + + + + id + userid + + + account + accountvar + + + + + + + registerUserKeys + Registering the user + + + id + userid + + + + + apikey + apikey + + + secretkey + secretkey + + + + + + + registerIso + Register iso + + + name + isoname + + + displaytext + isodisplay + + + url + http://nfs1.lab.vmops.com/isos_64bit/Ubuntu-10.04/ubuntu-10.04-desktop-amd64.iso + + + ostypeid + 59 + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + + id + privateisoid + + + created + + + ispublic + false + + + bootable + true + + + isready + false + + + isfeatured + false + + + name + registername + + + displaytext + registerdisplay + + + + + + + deployVirtualMachine + Deploying VM from small diskOffering + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + 5 + + + templateid + privateisoid + + + account + admin + + + domainid + 1 + + + displayname + namefordisplay + + + group + group1 + + + + + id + smallvmid + + + + + + + listVolumes + + + virtualmachineid + smallvmid + + + type + ROOT + + + + + id + smallrootvolumeid + + + + + + listVolumes + + + virtualmachineid + smallvmid + + + type + datadisk + + + + + id + smalldatavolumeid + + + + + + + sleep.sh + + Sleep for some time + + + s + 200 + + + + + + + createSnapshot + Creating snapshot of ROOT disk of small vm + true + + + volumeid + smallrootvolumeid + + + + + id + smallrootsnapshot + + + + + + + createSnapshot + Creating snapshot of Data disk of small vm + true + + + volumeid + smalldatavolumeid + + + + + id + smalldatasnapshot + + + + + + + createTemplate + Creating template of ROOT snapshot of small vm + true + + + snapshotid + smallrootsnapshot + + + name + + + displaytext + newtext + + + osTypeId + 59 + + + + + id + smalltemplateid + + + + + + + deployVirtualMachine + Deploy a vm from template created from snapshot of ROOT disk of small vm + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + 5 + + + templateid + smalltemplateid + + + account + admin + + + domainid + 1 + + + displayname + smallsnpshtVM + + + group + group1 + + + + + id + smallvmid1 + + + + + + + createVolume + Create a volume from smaller disk snapshot + true + + + snapshotid + smallrootsnapshot + + + name + + + + + id + smallvolumeid + + + + + + + createVolume + Create a volume from smaller disk snapshot + true + + + snapshotid + smalldatasnapshot + + + name + + + + + id + smallvolumeid + + + + + + + attachVolume + Attach small volume to the vm created from small snapshot + true + + + id + smallvolumeid + + + virtualmachineid + smallvmid1 + + + + + + + + attachVolume + Attach small volume to a different VM + true + + + id + smallvolumeid + + + virtualmachineid + smallvmid + + + + + + listConfiguration + Getting value of the expunge.delay configuration parameter + + + name + expunge.delay + + + + + value + expunge.delay + + + + + + + + rebootVirtualMachine + Reboot small vm + + + id + smallvmid1 + + + + + + stopVirtualMachine + stop medium vm + + + id + smallvmid1 + + + + + + startVirtualMachine + stop medium vm + + + id + smallvmid1 + + + + + + + deleteSnapshot + Deleting a snapshot taken of an attached Volume + + + id + smallrootsnapshot + + + + + + + destroyVirtualMachine + Destroy small vm + + + id + smallvmid1 + + + + + + + + + + createSnapshot + Creating snapshot of root disk immediately after destroying VM. + true + + + volumeid + smallrootvolumeid + + + + + id + smallrootsnapshot + + + + + + + sleep.sh + + Sleep for expunge delayed interval + + + s + expunge.delay + + + + + + sleep.sh + + Sleep for another expunge delayed interval + + + s + expunge.delay + + + + + + + + + createSnapshot + Creating snapshot of Destroyed root disk after expunge delay Failure Test Case + true + true + + + volumeid + smallrootvolumeid + + + + + id + smallrootsnapshot + + + + + + + destroyVirtualMachine + Destroy small vm + + + id + smallvmid1 + + + + + + + + deleteUser + Deleting a user + + + id + userid + + + + + \ No newline at end of file diff --git a/test/metadata/func/snapshots.xml b/test/metadata/func/snapshots.xml new file mode 100644 index 00000000000..7dcf76a2585 --- /dev/null +++ b/test/metadata/func/snapshots.xml @@ -0,0 +1,809 @@ + + + + + + createAccount + [Create the Account and a User for the account] + + + account + accountvar + + + accounttype + 0 + + + domainid + 1 + + + email + apiuser@gmail.com + + + firstname + apiuser + + + lastname + apiuserlastname + + + username + usernameparam + + + password + password + + + + + id + accountid + + + name + accountvar + + + + + + + + listUsers + 5 [List the Created User in (3)] + + + account + accountvar + + + + + id + userid + + + + + + + registerUserKeys + Registering the user + + + id + userid + + + + + apikey + apikey + + + secretkey + secretkey + + + + + + createNetwork + [Creating default network] + + + zoneid + globalzoneid + + + networkOfferingId + globalnetworkofferingid + + + account + accountvar + + + domainid + 1 + + + name + defaultregressionnetwork + + + displaytext + defaultregressionnetwork + + + + + id + networkid + + + + + + deployVirtualMachine + Deploying vm from small diskOffering + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + accountvar + + + domainid + 1 + + + displayname + SnapshotsTest-VM-1 + + + group + group1 + + + networkids + networkid + + + + + id + smallvmid + + + + + + deployVirtualMachine + Deploying vm from Medium disk offering + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + mediumglobaldiskofferingid + + + templateid + globaltemplateid + + + account + accountvar + + + domainid + 1 + + + account + accountvar + + + domainid + 1 + + + displayname + SnapshotsTest-VM-2 + + + group + group1 + + + networkids + networkid + + + + + id + largevmid + + + + + + listVolumes + + + virtualmachineid + smallvmid + + + type + ROOT + + + + + id + smallrootvolumeid + + + + + + listVolumes + + + virtualmachineid + smallvmid + + + type + datadisk + + + + + id + smalldatavolumeid + + + + + + listVolumes + + + virtualmachineid + largevmid + + + type + ROOT + + + + + id + largerootvolumeid + + + + + + listVolumes + + + virtualmachineid + largevmid + + + type + datadisk + + + + + id + largedatavolumeid + + + + + + + sleep.sh + + Sleep for some time + + + s + 200 + + + + + + + createSnapshot + Creating snapshot of ROOT disk of small vm + true + + + volumeid + smallrootvolumeid + + + + + id + smallrootsnapshot + + + + + + createSnapshot + Creating snapshot of Data disk of small vm + true + + + volumeid + smalldatavolumeid + + + + + id + smalldatasnapshot + + + + + + createSnapshot + Creating snapshot of ROOT disk of medium vm + true + + + volumeid + largerootvolumeid + + + + + id + largerootsnapshot + + + + + + createSnapshot + Creating snapshot of DATA disk of medium vm + true + + + volumeid + largedatavolumeid + + + + + id + largedatasnapshot + + + + + + + createTemplate + Creating template of ROOT snapshot of small vm + true + + + snapshotid + smallrootsnapshot + + + name + + + displaytext + newtext + + + osTypeId + 12 + + + + + id + smalltemplateid + + + + + + createTemplate + Creating template of ROOT snapshot of large vm + true + + + snapshotid + largerootsnapshot + + + name + + + displaytext + newtext + + + osTypeId + 12 + + + + + id + largetemplateid + + + + + + deployVirtualMachine + Deploy a vm from template created from snapshot of ROOT disk of small vm + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + smalltemplateid + + + account + accountvar + + + domainid + 1 + + + account + accountvar + + + domainid + 1 + + + displayname + SnapshotsTest-VM-3 + + + group + group1 + + + networkids + networkid + + + + + id + smallvmid1 + + + + + + deployVirtualMachine + Deploy a vm from template created from snapshot of ROOT disk of medium vm + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + mediumglobaldiskofferinigid + + + templateid + largetemplateid + + + account + accountvar + + + domainid + 1 + + + account + accountvar + + + domainid + 1 + + + displayname + SnapshotsTest-VM-4 + + + group + group1 + + + networkids + networkid + + + + + id + largevmid1 + + + + + + + + createVolume + Create a volume from smaller disk snapshot + true + + + snapshotid + smallrootsnapshot + + + name + + + + + id + smallvolumeid + + + + + + createVolume + Create a volume from larger disk snapshot + true + + + snapshotid + largerootsnapshot + + + name + + + + + id + largevolumeid + + + + + + attachVolume + Attach small volume to the vm created from small snapshot + true + + + id + smallvolumeid + + + virtualmachineid + smallvmid1 + + + + + + attachVolume + Attach medium volume to the vm created from medium snapshot + true + + + id + largevolumeid + + + virtualmachineid + largevmid1 + + + + + + + + rebootVirtualMachine + Reboot small vm + + + id + smallvmid1 + + + + + + stopVirtualMachine + stop medium vm + + + id + largevmid1 + + + + + + startVirtualMachine + stop medium vm + + + id + largevmid1 + + + + + + + + destroyVirtualMachine + Destroy small vm + + + id + smallvmid1 + + + + + + destroyVirtualMachine + Destroy large vm + + + id + largevmid1 + + + + + + + + + deleteAccount + Deleting a user + + + id + accountid + + + + + + + + diff --git a/test/metadata/func/snapshots_contd.xml b/test/metadata/func/snapshots_contd.xml new file mode 100644 index 00000000000..379cff2d93a --- /dev/null +++ b/test/metadata/func/snapshots_contd.xml @@ -0,0 +1,608 @@ + + + + + + + createUser + Create a user + + + + username + + + password + apiuser + + + firstname + apiuser + + + lastname + apiuser + + + email + apiuser@gmail.com + + + accounttype + 0 + + + + + id + userid + + + account + accountvar + + + + + + + registerUserKeys + Registering the user + + + id + userid + + + + + apikey + apikey + + + secretkey + secretkey + + + + + + + deployVirtualMachine + Deploying VM from small diskOffering + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + 5 + + + templateid + globaltemplateid + + + account + admin + + + domainid + 1 + + + displayname + namefordisplay + + + group + group1 + + + + + id + smallvmid + + + + + + + listVolumes + + + virtualmachineid + smallvmid + + + type + ROOT + + + + + id + smallrootvolumeid + + + + + + listVolumes + + + virtualmachineid + smallvmid + + + type + datadisk + + + + + id + smalldatavolumeid + + + + + + + sleep.sh + + Sleep for some time + + + s + 200 + + + + + + + createSnapshot + Creating snapshot of ROOT disk of small vm + true + + + volumeid + smallrootvolumeid + + + + + id + smallrootsnapshot + + + + + + + createSnapshot + Creating snapshot of Data disk of small vm + true + + + volumeid + smalldatavolumeid + + + + + id + smalldatasnapshot + + + + + + + createTemplate + Creating template of ROOT snapshot of small vm + true + + + snapshotid + smallrootsnapshot + + + name + + + displaytext + newtext + + + osTypeId + 12 + + + + + id + smalltemplateid + + + + + + + deployVirtualMachine + Deploy a vm from template created from snapshot of ROOT disk of small vm + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + 5 + + + templateid + smalltemplateid + + + account + admin + + + domainid + 1 + + + displayname + smallsnpshtVM + + + group + group1 + + + + + id + smallvmid1 + + + + + + + createVolume + Create a volume from smaller disk snapshot + true + + + snapshotid + smallrootsnapshot + + + name + + + + + id + smallvolumeid + + + + + + + createVolume + Create a volume from smaller disk snapshot + true + + + snapshotid + smalldatasnapshot + + + name + + + + + id + smallvolumeid + + + + + + + createSnapshot + Creating snapshot of Detached Volume + true + + + volumeid + smallvolumeid + + + + + id + detachsnapshotid + + + + + + + attachVolume + Attach small volume to the vm created from small snapshot + true + + + id + smallvolumeid + + + virtualmachineid + smallvmid1 + + + + + + + + attachVolume + Attach small volume to a different VM + true + + + id + smallvolumeid + + + virtualmachineid + smallvmid + + + + + + + + + rebootVirtualMachine + Reboot small vm + + + id + smallvmid1 + + + + + + stopVirtualMachine + stop medium vm + + + id + smallvmid1 + + + + + + startVirtualMachine + stop medium vm + + + id + smallvmid1 + + + + + + + deleteSnapshot + Deleting a snapshot taken of an attached Volume + + + id + smallrootsnapshot + + + + + + + deleteSnapshot + Deleting a snapshot taken of a detached Volume + + + id + detachsnapshotid + + + + + + + + destroyVirtualMachine + Destroy small vm + + + id + smallvmid1 + + + + + + + + + + createSnapshot + Creating snapshot of root disk immediately after destroying VM. + true + + + volumeid + smallrootvolumeid + + + + + id + smallrootsnapshot + + + + + + + sleep.sh + + Sleep for expunge delayed interval + + + s + expunge.delay + + + + + + sleep.sh + + Sleep for another expunge delayed interval + + + s + expunge.delay + + + + + + + + + createSnapshot + Creating snapshot of Destroyed root disk after expunge delay Failure Test Case + true + true + + + volumeid + smallrootvolumeid + + + + + id + smallrootsnapshot + + + + + + + destroyVirtualMachine + Destroy small vm + + + id + smallvmid1 + + + + + + listConfiguration + Getting value of the expunge.delay configuration parameter + + + name + expunge.delay + + + + + value + expunge.delay + + + + + + listConfiguration + Getting value of the expunge.delay configuration parameter + + + name + expunge.delay + + + + + value + expunge.delay + + + + + + + deleteUser + Deleting a user + + + id + userid + + + + + \ No newline at end of file diff --git a/test/metadata/func/srxstresswithportfwd.xml b/test/metadata/func/srxstresswithportfwd.xml new file mode 100644 index 00000000000..733ec661e1d --- /dev/null +++ b/test/metadata/func/srxstresswithportfwd.xml @@ -0,0 +1,577 @@ + + + + createAccount + Creating account + + + account + accountname + + + accounttype + 1 + + + domainid + 1 + + + email + srxstress@gmail.com + + + firstname + srxstress + + + lastname + srxstresslastname + + + username + usernameparam + + + password + password + + + + + id + accountid + + + + + + + createNetwork + Creating default network + + + zoneid + globalzoneid + + + networkOfferingId + globalnetworkofferingid + + + account + accountname + + + domainid + 1 + + + name + srxstressnetwork + + + displaytext + srxstressnetwork + + + + + id + networkid + + + + + + deployVirtualMachine + deploying virtual machine + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + templateid + globaltemplateid + + + account + accountname + + + domainid + 1 + + + networkids + networkid + + + + + id + vmid + + + name + vmname + + + ipaddress + vmipaddress + + + + + + deployVirtualMachine + deploying virtual machine + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + templateid + globaltemplateid + + + account + accountname + + + domainid + 1 + + + networkids + networkid + + + + + id + vmid1 + + + name + vmname1 + + + ipaddress1 + vmipaddress + + + + + + associateIpAddress + Associating first public ip address + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + + id + nonsourcenatpublicip1id + + + ipaddress + nonsourcenatpublicip1 + + + + + + associateIpAddress + Associating second public ip address + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + + id + nonsourcenatpublicip2id + + + ipaddress + nonsourcenatpublicip2 + + + + + + enableStaticNat + Enable Static NAT - 1 + + + ipaddressid + nonsourcenatpublicip1id + + + virtualmachineid + vmid + + + + + + enableStaticNat + Enable Static NAT - 2 + + + ipaddressid + nonsourcenatpublicip2id + + + virtualmachineid + vmid1 + + + + + + + createIpForwardingRule + Creating Ip forwarding rule - 1 + + + ipaddressid + nonsourcenatpublicip1id + + + startPort + 22 + + + endPort + 22 + + + protocol + TCP + + + + + id + ipfwdrule1 + + + + + + createIpForwardingRule + Creating Ip forwarding rule - 2 + + + ipaddressid + nonsourcenatpublicip1id + + + startPort + 33 + + + endPort + 35 + + + protocol + TCP + + + + + id + ipfwdrule2 + + + + + + createIpForwardingRule + Creating Ip forwarding rule - 3 + + + ipaddressid + nonsourcenatpublicip1id + + + startPort + 44 + + + endPort + 55 + + + protocol + TCP + + + + + id + ipfwdrule3 + + + + + + sleep.sh + + Sleeping for 2 mins to ensure that vm comes up for ssh test + + + s + 120 + + + + + + ssh.sh + + Ssh test for the vm + + + h + nonsourcenatpublicip1 + + + p + password + + + u + http://yahoo.com + + + + + + deleteIpForwardingRule + Delete Ip forwarding rule - 1 + + + id + ipfwdrule1 + + + + + + deleteIpForwardingRule + Delete Ip forwarding rule - 2 + + + id + ipfwdrule2 + + + + + + + deleteIpForwardingRule + Delete Ip forwarding rule - 3 + + + id + ipfwdrule3 + + + + + + sleep.sh + + Sleeping for 1 min + + + s + 60 + + + + + + createIpForwardingRule + Creating Ip forwarding rule - 4 + + + ipaddressid + nonsourcenatpublicip2id + + + startPort + 22 + + + endPort + 22 + + + protocol + TCP + + + + + id + ipfwdrule1 + + + + + + createIpForwardingRule + Creating Ip forwarding rule - 5 + + + ipaddressid + nonsourcenatpublicip2id + + + startPort + 33 + + + endPort + 35 + + + protocol + TCP + + + + + id + ipfwdrule2 + + + + + + createIpForwardingRule + Creating Ip forwarding rule - 6 + + + ipaddressid + nonsourcenatpublicip3id + + + startPort + 44 + + + endPort + 55 + + + protocol + TCP + + + + + id + ipfwdrule3 + + + + + + disableStaticNat + Disable Static NAT - 2 + + + ipaddressid + nonsourcenatpublicip2id + + + + + + + disassociateIpAddress + Dissociating second public ip address + + + id + nonsourcenatpublicip2id + + + + + + disableStaticNat + Disable Static NAT - 1 + + + ipaddressid + nonsourcenatpublicip1id + + + + + + disassociateIpAddress + Dissociating first public ip address + + + id + nonsourcenatpublicip1id + + + + + + deleteAccount + Delete account + + + id + accountid + + + + + + + + + diff --git a/test/metadata/func/static_nat.xml b/test/metadata/func/static_nat.xml new file mode 100644 index 00000000000..cecce5ca6eb --- /dev/null +++ b/test/metadata/func/static_nat.xml @@ -0,0 +1,898 @@ + + + + createUser + Create a regular user + + + username + + + password + apiuser + + + firstname + apiuser + + + lastname + apiuser + + + email + apiuser@gmail.com + + + accounttype + 0 + + + + + id + userid + + + account + accountname + + + + + + registerUserKeys + Registering the user + + + id + userid + + + + + apikey + apikey + + + secretkey + secretkey + + + + + + deployVirtualMachine + Deploying virtual machine + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + 5 + + + templateid + globaltemplateid + + + account + admin + + + domainid + 1 + + + displayname + namefordisplay + + + group + group1 + + + + + id + vmid + + + ipaddress + vmipaddress + + + + + + + deployVirtualMachine + Deploying virtual machine + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + 5 + + + templateid + globaltemplateid + + + account + admin + + + domainid + 1 + + + displayname + namefordisplay + + + group + group1 + + + + + id + vmid1 + + + ipaddress + vmipaddress1 + + + + + + sleep.sh + + Sleeping for 60 seconds to ensure that vms boot up + + + s + 60 + + + + + + listRouters + 35 + + + zoneid + globalzoneid + + + account + accountname + + + domainid + 1 + + + + + id + routerid + + + publicip + sourcenatpublicip + + + + + + + associateIpAddress + true + + + zoneid + globalzoneid + + + + + ipaddress + nonsourcenatpublicip + + + + + + + + createIpForwardingRule + true + true + Test case 1134 - try to create static NAT for source nat ip - should fail + + + ipaddress + sourcenatpublicip + + + virtualmachineid + vmid + + + + + + + + createIpForwardingRule + true + Test case 1135 - try to create static NAT for non source nat ip + + + ipaddress + nonsourcenatpublicip + + + virtualmachineid + vmid + + + + + id + ruleid + + + + + + ssh.sh + + Ssh test for the vm + + + h + nonsourcenatpublicip + + + p + password + + + + + + + + deleteIpForwardingRule + true + Test case 1136 - delete ip forwarding rule + + + id + ruleid + + + + + + listIpForwardingRules + true + list ip forwarding rules + true + + + id + ruleid + + + + + + ssh.sh + + true + Ssh test for the vm - should fail + + + h + nonsourcenatpublicip + + + p + password + + + + + + + + createIpForwardingRule + true + try to create static NAT for non source nat ip + + + ipaddress + nonsourcenatpublicip + + + virtualmachineid + vmid + + + + + id + ruleid + + + + + + listIpForwardingRules + true + Test case 1137-1: list ip forwarding by ip address + false + + + ipaddress + nonsourcenatpublicip + + + + + + listIpForwardingRules + true + Test case 1137-2: list ip forwarding by id + true + + + id + 1000000 + + + + + + + listIpForwardingRules + true + Test case 1137-3: list ip forwarding by virtualmachineid + true + + + virtualmachineid + 1000000 + + + + + + + disassociateIpAddress + true + + + ipaddress + nonsourcenatpublicip + + + + + + listIpForwardingRules + true + Test case 1138: static NAT rules should be removed once corresponding ip address is dissassociated + false + + + + + + associateIpAddress + true + + + zoneid + globalzoneid + + + + + ipaddress + nonsourcenatpublicip + + + + + + + createIpForwardingRule + true + try to create static NAT for non source nat ip and vm1 + + + ipaddress + nonsourcenatpublicip + + + virtualmachineid + vmid + + + + + id + ruleid + + + + + + createIpForwardingRule + true + 1139 - try to assign static NAT for the same ip and different vms + true + + + ipaddress + nonsourcenatpublicip + + + virtualmachineid + vmid1 + + + + + + + + destroyVirtualMachine + Destroying virtual machine... + + + id + vmid + + + + + + listConfigurations + Getting expunge interval value + + + name + expunge.interval + + + + + value + expunge.interval + + + + + + sleep.sh + + Sleep for expunge interval + + + s + expunge.interval + + + + + + listIpForwardingRules + true + true + Test case 1140: static nat rules should be removed once corresponding vm is expunged + + + + + + associateIpAddress + true + + + zoneid + globalzoneid + + + + + ipaddress + nonsourcenatpublicip1 + + + + + + associateIpAddress + true + + + zoneid + globalzoneid + + + + + ipaddress + nonsourcenatpublicip2 + + + + + + createIpForwardingRule + true + try to create static NAT for non source nat1 + + + ipaddress + nonsourcenatpublicip + + + virtualmachineid + vmid1 + + + + + + createIpForwardingRule + true + try to create static NAT for non source nat ip2 + + + ipaddress + nonsourcenatpublicip + + + virtualmachineid + vmid1 + + + + + + + ssh.sh + + TestCase 1141-2: ssh to ip1 + + + h + nonsourcenatpublicip1 + + + p + password + + + + + + + ssh.sh + + TestCase 1141-2: ssh to ip2 + + + h + nonsourcenatpublicip2 + + + p + password + + + + + + + + rebootRouter + Rebooting router... + + + id + routerid + + + + + + ssh.sh + + TestCase 1142: ssh to the public ip after domR was rebooted + + + h + nonsourcenatpublicip1 + + + p + password + + + + + + + + stopRouter + Stopping router... + + + id + routerid + + + + + + startRouter + Starting router... + + + id + routerid + + + + + + ssh.sh + + TestCase 1143: ssh to the public ip after domR was stopped and started + + + h + nonsourcenatpublicip1 + + + p + password + + + + + + + + deployVirtualMachine + Deploying virtual machine + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + 5 + + + templateid + globaltemplateid + + + account + admin + + + domainid + 1 + + + displayname + namefordisplay + + + group + group1 + + + + + id + vmid + + + ipaddress + vmipaddress1 + + + + + + sleep.sh + + Sleeping for 60 seconds to ensure that vm boots up + + + s + 60 + + + + + + associateIpAddress + true + + + zoneid + globalzoneid + + + + + ipaddress + nonsourcenatpublicip + + + + + + createPortForwardingRule + true + Create port forwarding rule for ports 22/22 + + + privateip + vmipaddress + + + ipaddress + nonsourcenatpublicip + + + privateport + 22 + + + publicport + 22 + + + protocol + tcp + + + virtualmachineid + vmid + + + + + + ssh.sh + + Ssh to the vm after Port forwarding rule was created + + + h + nonsourcenatpublicip + + + p + password + + + + + + createIpForwardingRule + true + try to create static NAT for non source nat ip2 + + + ipaddress + nonsourcenatpublicip + + + virtualmachineid + vmid1 + + + + + id + ruleid + + + + + + ssh.sh + + Ssh to the vm after static NAT rule was created + + + h + nonsourcenatpublicip + + + p + password + + + + + + deleteIpForwardingRule + true + delete ip forwarding rule + + + id + ruleid + + + + + + ssh.sh + + Ssh to the vm after static NAT rule was deleted + + + h + nonsourcenatpublicip + + + p + password + + + + + + + + deleteUser + Deleting the user + + + id + userid + + + + + + \ No newline at end of file diff --git a/test/metadata/func/templatedwnldstress.xml b/test/metadata/func/templatedwnldstress.xml new file mode 100644 index 00000000000..974a52f445c --- /dev/null +++ b/test/metadata/func/templatedwnldstress.xml @@ -0,0 +1,739 @@ + + + + + + createAccount + [Create the Account and a User for the account] + + + account + accountname + + + accounttype + 1 + + + domainid + 1 + + + email + admin@gmail.com + + + firstname + admin + + + lastname + adminlastname + + + username + usernameparam + + + password + password + + + + + id + accountid + + + + + + + createNetwork + [Creating default network] + + + zoneid + globalzoneid + + + networkOfferingId + globalnetworkofferingid + + + account + accountname + + + domainid + 1 + + + name + defaultregressionnetwork + + + displaytext + defaultregressionnetwork + + + + + id + networkid + + + + + + deployVirtualMachine + [Deploy a Virtual Machine under the Account] + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + templateid + globaltemplateid + + + account + accountname + + + domainid + 1 + + + networkids + networkid + + + + + id + vmid + + + name + vmname + + + ipaddress + vmipaddress + + + + + + listVolumes + [List the ROOT Volume of the VM] + + + virtualmachineid + vmid + + + type + ROOT + + + + + id + rootvolumeid + + + + + + stopVirtualMachine + [Stop virtual machine] + + + id + vmid + + + + + + createTemplate + [Create template from root volume] + + + volumeid + rootvolumeid + + + name + + + displaytext + newtext + + + osTypeId + 12 + + + + + id + privatetemplateid + + + + + + deployVirtualMachine + [Deploying virtual machine from the Private Template] + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + privatetemplateid + + + account + accountname + + + domainid + 1 + + + displayname + VMcreatedfrmTemplate + + + group + group1 + + + networkids + networkid + + + + + id + vmid1 + + + hostid + vm_hostid + + + + + + listHosts + List host where vm is running + + + id + vm_hostid + + + + + ipaddress + vmhost_ipaddress + + + + + + select install_path from template_spool_ref + true + Getting private template vdi from the db + + + template_id + privatetemplateid + + + + + install_path + template_uuid + + + + + + listvdi.sh + + List VDI for template on the xen host before vm is destroyed + + + h + vmhost_ipaddress + + + u + template_uuid + + + + + + destroyVirtualMachine + Destroy virtual machine created from the private template + + + id + vmid1 + + + + + + + listConfigurations + Getting expunge interval value + + + name + expunge.interval + + + + + value + expunge.interval + + + + + + updateConfiguration + Updating storage.cleanup.interval + + + name + storage.cleanup.interval + + + value + 60 + + + + + + listConfigurations + Getting expunge interval value + + + name + storage.cleanup.interval + + + + + value + storage.cleanup.interval + + + + + + ms.sh + + Restarting management server + + + h + ms1 + + + o + restart + + + + + + sleep.sh + + Sleep for expunge interval + + + s + expunge.interval + + + + + + + sleep.sh + + Sleep for another expunge interval + + + s + expunge.interval + + + + + + sleep.sh + + Sleep for Storage CleanUp interval + + + s + storage.cleanup.interval + + + + + + sleep.sh + + Sleep for another Storage CleanUp interval + + + s + storage.cleanup.interval + + + + + + + + listvdi.sh + true + + List VDI for template on the xen host after vm using template is destroyed + + + h + vmhost_ipaddress + + + u + template_uuid + + + + + + + + deployVirtualMachine + Deploying virtual machine from the private template + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + privatetemplateid + + + account + accountname + + + domainid + 1 + + + displayname + VMcreatedfrmTemplate + + + group + group1 + + + networkids + networkid + + + + + id + vmid1 + + + hostid + vm_hostid + + + + + + listHosts + List host where vm is running + + + id + vm_hostid + + + + + ipaddress + vmhost_ipaddress + + + + + + select install_path from template_spool_ref + true + Getting private template vdi from the db + + + template_id + privatetemplateid + + + + + install_path + template_uuid + + + + + + listvdi.sh + + List VDI for template on the xen host before vm is destroyed + + + h + vmhost_ipaddress + + + u + template_uuid + + + + + + destroyVirtualMachine + Destroy virtual machine created from the private template + + + id + vmid1 + + + + + + + listConfigurations + Getting expunge interval value + + + name + expunge.interval + + + + + value + expunge.interval + + + + + + sleep.sh + + Sleep for expunge interval + + + s + expunge.interval + + + + + + + sleep.sh + + Sleep for another expunge interval + + + s + expunge.interval + + + + + + sleep.sh + + Sleep for Storage CleanUp interval + + + s + storage.cleanup.interval + + + + + + sleep.sh + + Sleep for another Storage CleanUp interval + + + s + storage.cleanup.interval + + + + + + + + listvdi.sh + true + + List VDI for template on the xen host after vm using template is destroyed + + + h + vmhost_ipaddress + + + u + template_uuid + + + + + + + + + startVirtualMachine + [Start virtual machine] + + + id + vmid + + + + + state + Running + + + + + + rebootVirtualMachine + [Reboot Virtual Machine] + + + id + vmid + + + + + + destroyVirtualMachine + [Destroy virtual machine] + + + id + vmid + + + + + + listVirtualMachines + [Verify that vm was destroyed] + + + id + vmid + + + + + state + Destroyed + + + + + + deleteTemplate + Delete private template + + + id + privatetemplateid + + + + + + deleteAccount + [Delete account] + + + id + accountid + + + + + + \ No newline at end of file diff --git a/test/metadata/func/templates_sync.xml b/test/metadata/func/templates_sync.xml new file mode 100644 index 00000000000..8c8299270bb --- /dev/null +++ b/test/metadata/func/templates_sync.xml @@ -0,0 +1,1371 @@ + + + + + + + + deployVirtualMachine + Deploy a VM + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + admin + + + domainid + 1 + + + displayname + TempSyncVM + + + group + group1 + + + networkids + globalnetworkid + + + + + id + vmid + + + + + + select id from volumes + true + Getting volume id for the VM created + + + instance_id + vmid + + + + + id + volumeid + + + + + + stopVirtualMachine + Stop the Virtual Machine + + + id + vmid + + + + + + + createTemplate + Create template + + + volumeid + volumeid + + + name + privatetemplatename + + + displaytext + newtext + + + osTypeId + 12 + + + account + admin + + + domainid + 1 + + + + + id + privatetemplateid + + + + + + select download_state from template_host_ref + true + Getting volume path for the vm DATADISK volume + + + template_id + privatetemplateid + + + + + download_state + DOWNLOADED + + + + + + + select install_path from template_host_ref + true + Getting install_path from the template + + + template_id + privatetemplateid + + + + + install_path + template_path + + + + + + + listtemplate.sh + + List template directory after it was created + + + h + secondary_storage_ip + + + s + secondary_storage_dir + + + p + template_path + + + + + + removetemplate.sh + + Removing template file from secondary storage + + + h + secondary_storage_ip + + + s + secondary_storage_dir + + + p + template_path + + + + + + + ms.sh + + Restarting management server + + + h + ms1 + + + o + restart + + + + + + ms.sh + + Restarting management server + + + h + ms2 + + + o + restart + + + + + + + sleep.sh + + Sleep for 4 min + + + s + 240 + + + + + + select download_state from template_host_ref + true + Checking download state of the template in the DB after the template was deleted on secondary storage and management server process was restarted + + + template_id + privatetemplateid + + + + + download_state + DOWNLOAD_ERROR + + + + + + + + + createTemplate + Create template + + + volumeid + volumeid + + + name + privatetemplatename + + + displaytext + newtext + + + osTypeId + 12 + + + account + admin + + + domainid + 1 + + + + + id + privatetemplateid + + + + + + select download_state from template_host_ref + true + Getting volume path for the vm DATADISK volume + + + template_id + privatetemplateid + + + + + download_state + DOWNLOADED + + + + + + + select install_path from template_host_ref + true + Getting install_path from the template + + + template_id + privatetemplateid + + + + + install_path + template_path + + + + + + + listtemplate.sh + + List template directory after it was created + + + h + secondary_storage_ip + + + s + secondary_storage_dir + + + p + template_path + + + + + + corrupttemplate.sh + + Corrupting template file on secondary storage + + + h + secondary_storage_ip + + + s + secondary_storage_dir + + + i + privatetemplateid + + + a + 2 + + + + + + + ms.sh + + Restarting management server + + + h + ms1 + + + o + restart + + + + + + ms.sh + + Restarting management server + + + h + ms2 + + + o + restart + + + + + + + sleep.sh + + Sleep for 4 min + + + s + 240 + + + + + + select download_state from template_host_ref + true + Checking download state of the template in the DB after the template was deleted on secondary storage and management server process was restarted + + + template_id + privatetemplateid + + + + + download_state + DOWNLOAD_ERROR + + + + + + listtemplate.sh + + true + Verify that template got removed from the secondary storage by template sync + + + h + secondary_storage_ip + + + s + secondary_storage_dir + + + p + template_path + + + + + + + + createTemplate + Create template + + + volumeid + volumeid + + + name + privatetemplatename + + + displaytext + newtext + + + osTypeId + 12 + + + account + admin + + + domainid + 1 + + + + + id + privatetemplateid + + + + + + select download_state from template_host_ref + true + Getting volume path for the vm DATADISK volume + + + template_id + privatetemplateid + + + + + download_state + DOWNLOADED + + + + + + + select install_path from template_host_ref + true + Getting install_path from the template + + + template_id + privatetemplateid + + + + + install_path + template_path + + + + + + + listtemplate.sh + + List template directory after it was created + + + h + secondary_storage_ip + + + s + secondary_storage_dir + + + p + template_path + + + + + + createfaketemplate.sh + + Corrupting template file on secondary storage + + + h + secondary_storage_ip + + + s + secondary_storage_dir + + + i + privatetemplateid + + + a + 1 + + + dir + 300556 + + + + + + + ms.sh + + Restarting management server + + + h + ms1 + + + o + restart + + + + + + ms.sh + + Restarting management server + + + h + ms2 + + + o + restart + + + + + + + sleep.sh + + Sleep for 4 min + + + s + 240 + + + + + + listtemplate.sh + + true + Verify that template got removed from the secondary storage by template sync + + + h + secondary_storage_ip + + + s + secondary_storage_dir + + + p + /template/tmpl/1/300556/template.properties + + + + + + + + createTemplate + Create template + + + volumeid + volumeid + + + name + privatetemplatename + + + displaytext + newtext + + + osTypeId + 12 + + + account + admin + + + domainid + 1 + + + + + id + privatetemplateid + + + + + + select download_state from template_host_ref + true + Getting volume path for the vm DATADISK volume + + + template_id + privatetemplateid + + + + + download_state + DOWNLOADED + + + + + + + select install_path from template_host_ref + true + Getting install_path from the template + + + template_id + privatetemplateid + + + + + install_path + template_path + + + + + + + listtemplate.sh + + List template directory after it was created + + + h + secondary_storage_ip + + + s + secondary_storage_dir + + + p + template_path + + + + + + removetemplate.sh + + Removing template file from secondary storage + + + h + secondary_storage_ip + + + s + secondary_storage_dir + + + p + template_path + + + + + + + ms.sh + + Stopping management server + + + h + ms1 + + + o + stop + + + + + + ms.sh + + Stopping management server + + + h + ms2 + + + o + stop + + + + + + + ms.sh + + Starting management server + + + h + ms1 + + + o + start + + + + + + ms.sh + + Starting management server + + + h + ms2 + + + o + start + + + + + + sleep.sh + + Sleep for 4 min + + + s + 240 + + + + + + select download_state from template_host_ref + true + Checking download state of the template in the DB after the template was deleted on secondary storage and management server process was restarted + + + template_id + privatetemplateid + + + + + download_state + DOWNLOAD_ERROR + + + + + + + + + createTemplate + Create template + + + volumeid + volumeid + + + name + privatetemplatename + + + displaytext + newtext + + + osTypeId + 12 + + + account + admin + + + domainid + 1 + + + + + id + privatetemplateid + + + + + + select download_state from template_host_ref + true + Getting volume path for the vm DATADISK volume + + + template_id + privatetemplateid + + + + + download_state + DOWNLOADED + + + + + + + select install_path from template_host_ref + true + Getting install_path from the template + + + template_id + privatetemplateid + + + + + install_path + template_path + + + + + + + listtemplate.sh + + List template directory after it was created + + + h + secondary_storage_ip + + + s + secondary_storage_dir + + + p + template_path + + + + + + ms.sh + + Restarting management server + + + h + ms1 + + + o + restart + + + + + + ms.sh + + Restarting management server + + + h + ms2 + + + o + restart + + + + + + + sleep.sh + + Sleep for 4 min + + + s + 240 + + + + + + select download_state from template_host_ref + true + Checking download state of the template in the DB after the template was deleted on secondary storage and management server process was restarted + + + template_id + privatetemplateid + + + + + download_state + DOWNLOADED + + + + + + + deployVirtualMachine + Deploy vm from private template after management server was rebooted + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + privatetemplateid + + + account + admin + + + domainid + 1 + + + displayname + PrivateTempSyncVM + + + group + group2 + + + networkids + globalnetworkid + + + + + id + vmid + + + + + + + + registerTemplate + Register template + + + name + registername + + + displaytext + registerdisplay + + + url + globaltemplateurl + + + ostypeid + 12 + + + format + vhd + + + zoneid + globalzoneid + + + account + admin + + + domainid + 1 + + + + + id + privatetemplateid + + + + + + sleep.sh + + Sleep for 5 min + + + s + 300 + + + + + + + select download_state from template_host_ref + true + Getting volume path for the vm DATADISK volume + + + template_id + privatetemplateid + + + + + download_state + DOWNLOADED + + + + + + + select install_path from template_host_ref + true + Getting install_path from the template + + + template_id + privatetemplateid + + + + + install_path + template_path + + + + + + + listtemplate.sh + + List template directory after it was created + + + h + secondary_storage_ip + + + s + secondary_storage_dir + + + p + template_path + + + + + + removetemplate.sh + + Removing template file from secondary storage + + + h + secondary_storage_ip + + + s + secondary_storage_dir + + + p + template_path + + + + + + + ms.sh + + Stopping management server + + + h + ms1 + + + o + stop + + + + + + ms.sh + + Stopping management server + + + h + ms2 + + + o + stop + + + + + + + ms.sh + + Starting management server + + + h + ms1 + + + o + start + + + + + + ms.sh + + Starting management server + + + h + ms2 + + + o + start + + + + + + sleep.sh + + Sleep for 15 seconds + + + s + 15 + + + + + + select download_state from template_host_ref + true + Checking download state of the template in the DB after the template was deleted on secondary storage and management server process was restarted + + + template_id + privatetemplateid + + + + + download_state + DOWNLOAD_IN_PROGRESS + + + + + + + + destroyVirtualMachine + Destroy virtual machine as a part of cleanup + + + id + vmid + + + + + + + + + diff --git a/test/metadata/func/userapi.xml b/test/metadata/func/userapi.xml new file mode 100644 index 00000000000..96718034008 --- /dev/null +++ b/test/metadata/func/userapi.xml @@ -0,0 +1,1275 @@ + + + + + createAccount + [Create the Account and a User for the account] + + + account + accountname + + + accounttype + 1 + + + domainid + 1 + + + email + nimbus-user@gmail.com + + + firstname + nimbus-user + + + lastname + nimbus-userlastname + + + username + usernameparam + + + password + password + + + + + id + accountid + + + name + accountname + + + + + + + listUsers + 5 [List the Created User in (3)] + + + account + accountname + + + + + id + userid + + + username + usernameparam + + + + + + + createUser + [Create the Same User Again Should Fail] + true + + + account + accountname + + + accounttype + 1 + + + username + usernameparam + + + password + password + + + firstname + nimbus-user + + + lastname + nimbus-userlastname + + + email + nimbus-user@gmail.com + + + domainid + 1 + + + + + + + + + + + + createAccount + 54 [Create a Different Account with an Existing User's Name] + true + + + account + + + accounttype + 1 + + + domainid + 1 + + + email + nimbus-user@gmail.com + + + firstname + nimbus-user + + + lastname + nimbus-userlastname + + + username + usernameparam + + + password + password + + + + + + + + createUser + 593 [Create a Different User in the Same Account] + + + account + accountname + + + accounttype + 0 + + + username + + + password + password + + + firstname + nimbus-user + + + lastname + nimbus-userlastname + + + email + nimbus-user@gmail.com + + + domainid + 1 + + + + + + id + seconduserid + + + + + updateUser + 593 + true + + + id + seconduserid + + + username + usernameparam + + + + + + + + deleteUser + 56 + true + + + id + 100000000 + + + + + + + deleteUser + + + id + userid + + + + + + deleteUser + 58 + true + + + id + userid + + + + + + + listUsers + 59 + true + + + id + userid + + + + + + + listUsers + 60 + true + + + id + 10000000 + + + + + + + updateUser + 62 + true + + + id + userid + + + username + + + + + + + updateUser + 63 + true + + + id + 2000000000 + + + username + + + + + + + createUser + 45 + true + + + username + + + password + john12345 + + + firstname + admin + + + lastname + adminlastname + + + email + admin@gmail.com + + + accounttype + 0 + + + domainid + 1000000 + + + + + + + createUser + 46 + + + username + + + password + john12345 + + + firstname + admin + + + lastname + adminlastname + + + email + admin@gmail.com + + + accounttype + 0 + + + account + accountname + + + domainid + 1 + + + + + + + + createUser + 47 + true + + + username + + + firstname + admin + + + lastname + adminlastname + + + accounttype + 0 + + + email + admin@gmail.com + + + + + + + createUser + 47 + true + + + username + + + password + 1234567 + + + lastname + adminlastname + + + accounttype + 0 + + + email + admin@gmail.com + + + + + + createUser + 47 + true + + + username + + + password + 1234567 + + + firstname + admin + + + email + admin@gmail.com + + + accounttype + 0 + + + + + + createUser + 47 + true + + + username + + + password + 1234567 + + + firstname + admin + + + lastname + adminlastname + + + accounttype + 0 + + + + + + + + createDomain + + + name + + + + + name + domainname + + + id + newdomainid + + + + + + createAccount + [Create the Account and a User in the New Domain] + + + account + accountname1 + + + accounttype + 2 + + + domainid + newdomainid + + + email + nimbus-user@gmail.com + + + firstname + nimbus-user + + + lastname + nimbus-userlastname + + + username + usernameparam + + + password + password + + + + + id + accountid + + + name + accountname1 + + + + + + + listUsers + 52 [List the Created User in (3)] + + + account + accountname1 + + + + + id + userid + + + username + usernameparam + + + + + + + + createUser + 51 + true + + + username + + + password + password + + + firstname + alena + + + lastname + alenaslastname + + + email + alena@gmail.com + + + accounttype + 0 + + + domainid + 300000000 + + + account + accountname1 + + + + + + + + createUser + + + username + + + password + jane + + + firstname + jane + + + lastname + jane + + + email + jane@gmail.com + + + accounttype + 0 + + + account + accountname + + + domainid + newdomainid + + + + + + createUser + + + username + + + password + jane + + + firstname + jane + + + lastname + jane + + + email + jane@gmail.com + + + accounttype + 0 + + + account + accountname1 + + + domainid + newdomainid + + + + + + + createDomain + + + name + + + + + id + domaindomainid + + + name + domaindomainname + + + + + + createDomain + 64 + true + + + name + domaindomainname + + + + + + + + deleteDomain + + + id + domaindomainid + + + + + + listDomains + 65 + true + + + name + domaindomainname + + + + + + + + + deleteDomain + 66 + true + + + domainid + newdomainid + + + + + + + + + listDomains + 140 + + + name + root + + + + + + + + + createUser + + + username + + + password + testcase601 + + + firstname + admin + + + lastname + adminlastname + + + email + admin@gmail.com + + + accounttype + 0 + + + account + accountname + + + + + id + userid601 + + + username + username601 + + + account + account601 + + + + + + deployVirtualMachine + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + account601 + + + domainid + 1 + + + displayname + DomainTest-VM + + + group + group1 + + + networkids + networkid + + + + + + deleteUser + + + id + userid601 + + + + + + listEvents + 601 + + + account + account601 + + + + + + + + createUser + + + username + + + password + baduser + + + firstname + configuser + + + lastname + adminlastname + + + email + configuser@gmail.com + + + accounttype + 0 + + + account + accountname + + + domainid + 1 + + + + + id + baduserid + + + username + badusername + + + + + + registerUserKeys + + + id + baduserid + + + + + apikey + apikey + + + secretkey + secretkey + + + + + + listVirtualMachines + true + 75 + true + + + account + admin + + + + + + + + deleteDomain + + + id + newdomainid + + + cleanup + true + + + + + + + deleteAccount + + + id + accountid + + + + + + deleteAccount + + + id + accountid1 + + + + + \ No newline at end of file diff --git a/test/metadata/func/vmapi.xml b/test/metadata/func/vmapi.xml new file mode 100644 index 00000000000..0687018df29 --- /dev/null +++ b/test/metadata/func/vmapi.xml @@ -0,0 +1,873 @@ + + + + + + + + deployVirtualMachine + [Deploy Virtual Machine in Admin Account] + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + admin + + + domainid + 1 + + + displayname + VMapis-VM + + + group + group1 + + + networkids + globalnetworkid + + + + + id + vmid + + + name + vmname + + + ipaddress + vmipaddress + + + + + + destroyVirtualMachine + [Destroy Virtual Machine] + + + id + vmid + + + + + + listVirtualMachines + 72 [List the Destroyed Virutal Machine] + + + account + admin + + + name + vmname + + + + + + + startVirtualMachine + 92 [Check that the Destroyed VM cannot be started] + true + + + id + vmid + + + + + + + listVirtualMachines + 73 [Check that a non-existing VM cannot be listed (Id doesnt exist)] + + + account + admin + + + id + 100000000 + + + + + + + + createAccount + [Create the Account and a User for the account (List VM for a Removed User exercise BEGIN)] + + + account + accountname + + + accounttype + 0 + + + domainid + 1 + + + email + testcase74@gmail.com + + + firstname + testcase74 + + + lastname + testcase74lastname + + + username + + + password + password + + + + + id + accountid + + + name + accountname + + + + + + + listUsers + [List the Created User] + + + account + accountname + + + + + + id + userid + + + username + usernameparam + + + + + + + + + createNetwork + [Creating default network for the account] + + + zoneid + globalzoneid + + + networkOfferingId + globalnetworkofferingid + + + account + accountname + + + domainid + 1 + + + name + vmapi_network + + + displaytext + vmapi_network + + + + + id + networkid + + + + + + deployVirtualMachine + [Deploy Virtual Machine in the new Account] + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + accountname + + + domainid + 1 + + + displayname + VMapis-VM-2 + + + group + group1 + + + networkids + networkid + + + + + id + vmid2 + + + name + vmname + + + ipaddress + vmipaddress + + + + + + deleteUser + [Delete User] + + + id + userid + + + + + + deleteAccount + [Delete Account] + + + id + accountid + + + + + + listVirtualMachines + 74 [Check that no VMs present under the Account(List VM for a Removed User exercise END)] + true + + + account + accountname + + + domainid + 1 + + + + + + + updateVirtualMachine + 77 - Bug 3237 [updateVirtualMachine api: should deny to update Destroyed vms] + true + + + id + vmid + + + haenable + true + + + + + + + updateVirtualMachine + 592 [Verify that you can't enable HA for non-existing vm] + true + + + id + 1000000 + + + haenable + true + + + + + + + + recoverVirtualMachine + [Recover the Destroyed VM] + + + id + vmid + + + + + + resetPasswordForVirtualMachine + 79-1 [Verify that one can reset password for VM in stopped state] + + + id + vmid + + + + + + + + updateVirtualMachine + 76 [Verify that one can enable HA for VM in stopped state] + + + id + vmid + + + haenable + true + + + + + + + + startVirtualMachine + [Start Virtual Machine (reset password for VM in running state exercise BEGIN)] + + + id + vmid + + + + + + resetPasswordForVirtualMachine + 79-2 [Verify that one can reset password for VM in running state] + + + id + vmid + + + + + + + + updateVirtualMachine + 76 [Verify that one can disable HA for VM in running state] + + + id + vmid + + + haenable + false + + + + + + + + destroyVirtualMachine + [Destroy Virtual Machine (reset password on a destroyed VM exercise BEGIN)] + + + id + vmid + + + + + + resetPasswordForVirtualMachine + 80 [Verify that one can't reset password for VM in destroyed state] + true + + + id + vmid + + + + + + + rebootVirtualMachine + 89 [Verify that one can't reboot destroyed VM] + true + + + id + vmid + + + + + + + + deployVirtualMachine + [Deploy Virtual Machine to test reset password negative case] + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + admin + + + domainid + 1 + + + displayname + VMapis-VM-3 + + + group + group1 + + + networkids + networkid + + + + + id + windowsvmid + + + name + windowsvmname + + + ipaddress + windowsvmipaddress + + + + + + resetPasswordForVirtualMachine + 81 [Check whether password can be reset on virtual machine made from password disabled VM] + true + + + id + windowsvmid + + + + + + + changeServiceForVirtualMachine + 82 [Try to change service offering for VM in running state] + true + + + id + windowsvmid + + + serviceofferingid + mediumglobalserviceofferingid + + + + + + + stopVirtualMachine + [Stop the Virtual machine to change its Service Offering] + + + id + windowsvmid + + + + + + changeServiceForVirtualMachine + 83 [Try to change service offering to the one that VM already has -ve case] + true + + + id + windowsvmid + + + serviceofferingid + globalserviceofferingid + + + + + + + + rebootVirtualMachine + 90 [Try to reboot stopped vitrual machine - Negative case] + true + + + id + windowsvmid + + + + + + + + recoverVirtualMachine + 813 [Try to recover stopped virtual machine] + true + + + id + windowsvmid + + + + + + startVirtualMachine + [Start virtual machine] + + + id + windowsvmid + + + + + + recoverVirtualMachine + 813 [Try to recover running virtual machine] + true + + + id + windowsvmid + + + + + + + + deployVirtualMachine + 84 [Try to deploy vm and assign it to non-existing account -ve case] + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + blahblah-invaliduser + + + domainid + 1 + + + displayname + VMapis-VM-4 + + + group + group1 + + + networkids + globalnetworkid + + + + + + + deployVirtualMachine + 85 [Try to deploy vm and assign it to removed account -ve case] + true + + + zoneid + globalzoneid + + + serviceofferingid + globalserviceofferingid + + + diskofferingid + globaldiskofferingid + + + templateid + globaltemplateid + + + account + accountname + + + domainid + 1 + + + displayname + VMapis-VM-5 + + + group + group1 + + + networkids + networkid + + + + + + + destroyVirtualMachine + 87 [Try to send destroy command for non-existing vm -ve case] + true + + + id + 100000 + + + + + + + rebootVirtualMachine + 88 [Try to send reboot command for non-existing vm -ve case] + true + + + id + 100000 + + + + + + + startVirtualMachine + 88 [Try to send start command for non-existing vm -ve case] + true + + + id + 100000 + + + + + + + destroyVirtualMachine + [Destroy Virtual Machine as part of Clean up] + + + id + windowsvmid + + + + + + \ No newline at end of file diff --git a/test/metadata/func/vmsync.xml b/test/metadata/func/vmsync.xml new file mode 100644 index 00000000000..0ea2c65ea60 --- /dev/null +++ b/test/metadata/func/vmsync.xml @@ -0,0 +1,389 @@ + + + + + + deployVirtualMachine + deploy HA enabled VM test case + + + + diskofferingid + globaldiskofferingid + + + serviceofferingid + globalserviceofferingid + + + templateid + globaltemplateid + + + zoneid + globalzoneid + + + displayname + HAenabledVM + + + account + admin + + + domainid + 1 + + + group + group1 + + + networkids + globalnetworkid + + + + + id + vmid_en + + + name + vmname_en + + + hostid + hostid_en + + + + + + + deployVirtualMachine + deploy HA disabled VM test case + + + + diskofferingid + globaldiskofferingid + + + serviceofferingid + globalserviceofferingid + + + templateid + globaltemplateid + + + zoneid + globalzoneid + + + displayname + HAdisabledVM + + + account + admin + + + domainid + 1 + + + group + group1 + + + networkids + globalnetworkid + + + + + id + vmid_db + + + name + vmname_db + + + hostid + hostid_db + + + + + + + + updateVirtualMachine + HA enable virtual machine + + + id + vmid_en + + + displayname + HAenabledVirtualMachine + + + haenable + true + + + + + + + updateVirtualMachine + HA disable virtual machine + + + id + vmid_db + + + displayname + HAdisabledVirtualMachine + + + haenable + false + + + + + + + + listHosts + Obtain IP address of ha disabled VM's Host Test Case + + + id + hostid_db + + + + + ipaddress + ipaddress_db + + + + + + + + listHosts + Obtain IP address of ha enabled VM's Host Test Case + + + id + hostid_en + + + + + ipaddress + ipaddress_en + + + + + + + select instance_name from vm_instance + true + Obtaining the internal instance name for the ha disabled VM Test Case + + + id + vmid_db + + + + + instance_name + instance_name_db + + + + + + select instance_name from vm_instance + true + Obtaining the internal instance name for the ha enabled VM Test Case + + + id + vmid_en + + + + + instance_name + instance_name_en + + + + + + + + killvm.sh + Kill the HA enabled VM + + + + + n + instance_name_en + + + + h + ipaddress_en + + + + + + + killvm.sh + Kill the HA disabled VM + + + + + n + instance_name_db + + + + h + ipaddress_db + + + + + + + sleep.sh + + Sleep for some time + + + s + 300 + + + + + + + + + listVirtualMachines + List virtual machine with ha disabled + + + id + vmid_db + + + + + state + Stopped + + + + + + listVirtualMachines + List virtual machine with ha enabled + + + id + vmid_en + + + + + state + Running + + + hostid + hostid_en + + + + + + + listHosts + List host with ha enabled machine + + + id + hostid_en + + + + + ipaddress + ipaddress_en + + + + + + + listvm.sh + + List ha enabled machine + + + h + ipaddress_en + + + n + instance_name_en + + + + + + + + destroyVirtualMachine + Destroy ha disabled vm as a part of cleanup + + + id + vmid_db + + + + + + destroyVirtualMachine + Destroy ha enabled vm as a part of cleanup + + + id + vmid_en + + + + \ No newline at end of file diff --git a/test/scripts/bootstrap-regression.sh b/test/scripts/bootstrap-regression.sh new file mode 100755 index 00000000000..29db3c57663 --- /dev/null +++ b/test/scripts/bootstrap-regression.sh @@ -0,0 +1,40 @@ +#!/bin/bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + + +set -e +set -x + +# at the moment, my PWD is /root + +mypwd=`dirname $0` +cd "$mypwd"/regression # now my PWD is /root/artifacts/regression or wherever I was copied + +unzip test.zip +tar zxvmf ../cloud-management-dist.tar.gz +cd scripts +./cleanparallel.sh +./deploy.sh -b ../cloud-management-dist -d -r +sleep 300 +./regression.sh \ No newline at end of file diff --git a/test/scripts/build-env.sh b/test/scripts/build-env.sh new file mode 100755 index 00000000000..81e5352c969 --- /dev/null +++ b/test/scripts/build-env.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + +PATHSEP=':' +if [[ $OSTYPE == "cygwin" ]] ; then + PATHSEP=';' +fi + +CP=commons-httpclient-3.1.jar${PATHSEP}commons-logging-1.1.1.jar${PATHSEP}commons-codec-1.3.jar${PATHSEP}testclient.jar${PATHSEP}log4j-1.2.15.jar${PATHSEP}utils.jar${PATHSEP}./conf +java -cp $CP com.vmops.test.longrun.BuildGuestNetwork $* + + diff --git a/test/scripts/certDeleteEC2.sh b/test/scripts/certDeleteEC2.sh new file mode 100755 index 00000000000..e5bec3213ca --- /dev/null +++ b/test/scripts/certDeleteEC2.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + +set -e +DST='src/' + +java -cp ${DST}commons-httpclient-3.1.jar:${DST}mysql-connector-java-5.1.7-bin.jar:${DST}commons-logging-1.1.1.jar:${DST}commons-codec-1.4.jar:${DST}cloud-test.jar:${DST}log4j-1.2.15.jar:${DST}trilead-ssh2-build213.jar:${DST}cloud-utils.jar:./conf com.cloud.test.utils.SubmitCert -action DeleteCertificate $* diff --git a/test/scripts/certSubmitEC2.sh b/test/scripts/certSubmitEC2.sh new file mode 100755 index 00000000000..07e6dcab0cc --- /dev/null +++ b/test/scripts/certSubmitEC2.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + +set -e +DST='src/' + +java -cp ${DST}commons-httpclient-3.1.jar:${DST}mysql-connector-java-5.1.7-bin.jar:${DST}commons-logging-1.1.1.jar:${DST}commons-codec-1.4.jar:${DST}cloud-test.jar:${DST}log4j-1.2.15.jar:${DST}trilead-ssh2-build213.jar:${DST}cloud-utils.jar:./conf com.cloud.test.utils.SubmitCert $* diff --git a/test/scripts/checkLog.sh b/test/scripts/checkLog.sh new file mode 100755 index 00000000000..e3e029b0c60 --- /dev/null +++ b/test/scripts/checkLog.sh @@ -0,0 +1,71 @@ +#!/bin/bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + + +#set -x + +rm -rf log.out + +dir=$(dirname "$0") +if [ -f $dir/../deploy.properties ]; then + . "$dir/../deploy.properties" +fi + + +echo "Starting checking the logs for errors...." + + for i in $SERVER + do + echo -ne "Log from Management server $i: \n=====================================================================================\n" >> log.out + ssh root@$i "grep -i -E 'error|exce|fail|unable|leak' /var/log/vmops/vmops.log" >> log.out + echo -e "\n" >> log.out + done + + for i in $COMPUTE + do + echo -ne "Log from Computing host $i: \n=====================================================================================\n" >> log.out + ssh root@$i "grep -i -E 'error|exce|fail|timed out|unable' /var/log/vmops/agent.log" >> log.out + echo -e "\n\n" >> log.out + done + + for i in $ROUTER + do + echo -ne "Log from Routing host $i: \n=====================================================================================\n" >> log.out + ssh root@$i "grep -i -E 'error|exce|fail|timed out|unable' /var/log/vmops/agent.log" >> log.out + echo -e "\n" >> log.out + done + + for i in $STORAGE + do + echo -ne "Log from Storage host $i: \n=====================================================================================\n" >> log.out + ssh root@$i "grep -i error /var/log/vmops/agent.log" >> log.out + ssh root@$i "grep -i fail /var/log/vmops/agent.log" >> log.out + ssh root@$i "grep -i exce /var/log/vmops/agent.log" >> log.out + ssh root@$i "grep -i unable /var/log/vmops/agent.log" >> log.out + ssh root@$i "grep -i \'timed out\' /var/log/vmops/agent.log" >> log.out + echo -e "\n" >> log.out + done + + +echo "Done! Check log.out file for the results" diff --git a/test/scripts/checkOutOfMemory.sh b/test/scripts/checkOutOfMemory.sh new file mode 100755 index 00000000000..24bf6e7965e --- /dev/null +++ b/test/scripts/checkOutOfMemory.sh @@ -0,0 +1,39 @@ +#!/bin/bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + + +while true +do +sleep 600 +pid=`ps -ef | grep 'management.jmxremote' | grep -v 'cloud-management' | grep -v grep | awk '{print \$2}'` +if grep -q java.lang.OutOfMemoryError /var/log/vmops/vmops.log +then +while true +do +t=$(date +"%h%d_%H_%M_%S") +jmap -dump:format=b,file=/root/dump/heap.bin.$t $pid +sleep 1800 +done +fi +done \ No newline at end of file diff --git a/test/scripts/cleanparallel.sh b/test/scripts/cleanparallel.sh new file mode 100755 index 00000000000..927ffcd1510 --- /dev/null +++ b/test/scripts/cleanparallel.sh @@ -0,0 +1,117 @@ +#!/bin/bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + + +. /etc/rc.d/init.d/functions + +set -x + +kill_server() { +ssh root@$1 "service cloud-management stop && service cloud-usage stop 2>&1 &" +} + + + +cleanup_server() { + kill_server $1 $2 +t=$(date +"%h%d_%H_%M_%S") +ssh root@$1 "mkdir $2/logs.$t; mv $2/management-server.log $2/logs.$t/management-server.log.$t " +ssh root@$1 "mkdir $2/logs.$t; mv $2/catalina.out $2/logs.$t/catalina.out.$t" + return 0 +} + + +cleanup_linux(){ +ssh root@$1 "for vm in \`xe vm-list | grep name-label | grep -v Control | awk '{print \$4}'\`; do uuid=\`xe vm-list name-label=\$vm | grep uuid | awk '{print \$5}'\`; echo \$uuid; xe vm-shutdown --force uuid=\$uuid; xe vm-destroy uuid=\$uuid; done" + +ssh root@$1 "for vlan in \`xe vlan-list | grep uuid | awk '{print \$5}'\`; do pif=\`xe pif-list VLAN=\$vlan | grep ^uuid | awk '{print \$5}'\`; xe pif-unplug uuid=\$pif; xe vlan-destroy uuid=\$vlan; done" + +ssh root@$1 "for vlan in \`xe network-list | grep name-label | grep VLAN| awk '{print \$4}'\`; do echo \$vlan; uuid=\`xe network-list name-label=\$vlan | grep uuid | awk '{print \$5}'\`; xe network-destroy uuid=\$uuid; done" + +ssh root@$1 "for sr in \`xe sr-list type=nfs name-description=storage | grep uuid | awk '{print \$5}'\`; do pbd=\`xe pbd-list sr-uuid=\$sr | grep ^uuid | awk '{ print \$5}'\` ; echo \$pbd; xe pbd-unplug uuid=\$pbd; xe pbd-destroy uuid=\$pbd; xe sr-forget uuid=\$sr; done" + +ssh root@$1 "for sr in \`xe sr-list type=iso name-description=iso | grep uuid | awk '{print \$5}'\`; do echo \$sr; for vdi in \`xe vdi-list sr-uuid=\$sr | grep ^uuid | awk '{ print \$5}'\` ; do echo \$vdi; xe vdi-destroy uuid=\$vdi; done; for pbd in \`xe pbd-list sr-uuid=\$sr | grep ^uuid | awk '{ print \$5}'\` ; do echo \$pbd; xe pbd-unplug uuid=\$pbd; xe pbd-destroy uuid=\$pbd; done; done" + +ssh root@$1 "xentoolsiso=\$(xe sr-list name-label='XenServer Tools' | grep uuid | awk '{print \$5}'); for sr in \`xe sr-list type=iso content-type=iso | grep uuid | awk '{print \$5}' | grep -v \$xentoolsiso \`; do echo \$sr; for vdi in \`xe vdi-list sr-uuid=\$sr | grep ^uuid | awk '{ print \$5}'\` ; do echo \$vdi; xe vdi-destroy uuid=\$vdi; done; for pbd in \`xe pbd-list sr-uuid=\$sr | grep ^uuid | awk '{ print \$5}'\` ; do echo \$pbd; xe pbd-unplug uuid=\$pbd; xe pbd-destroy uuid=\$pbd; done; done" + +ssh root@$1 "for sr in \`xe sr-list type=nfs | grep uuid | awk '{print \$5}'\`; do echo \$sr; for pbd in \`xe pbd-list sr-uuid=\$sr | grep ^uuid | awk '{ print \$5}'\` ; do echo \$pbd; xe pbd-unplug uuid=\$pbd; xe pbd-destroy uuid=\$pbd; done; xe sr-forget uuid=\$sr; done" + +ssh root@$1 "for sr in \`xe sr-list type=lvmoiscsi | grep uuid | awk '{print \$5}'\`; do echo \$sr; for vdi in \`xe vdi-list sr-uuid=\$sr | grep ^uuid | awk '{ print \$5}'\` ; do echo \$vdi; xe vdi-destroy uuid=\$vdi; done; for pbd in \`xe pbd-list sr-uuid=\$sr | grep ^uuid | awk '{ print \$5}'\` ; do echo \$pbd; xe pbd-unplug uuid=\$pbd; xe pbd-destroy uuid=\$pbd; done; xe sr-forget uuid=\$sr; done" + +ssh root@$1 "for sr in \`xe sr-list type=lvm | grep uuid | awk '{print \$5}'\`; do echo \$sr; for vdi in \`xe vdi-list sr-uuid=\$sr | grep ^uuid | awk '{ print \$5}'\` ; do echo \$vdi; xe vdi-destroy uuid=\$vdi; done; done" + +ssh root@$1 "for mount in \`mount | grep '/var/run/sr-mount' | awk '{print \$3}'\`; do echo \$mount; umount \$mount; done" +ssh root@$1 "cd /opt/xensource/bin/ && rm -rf heartbeat" +} + + +cleanup_storage(){ +echo 'Deleting snapshot directory' +ssh root@$1 "cd $2/ && rm -rf snapshots" +echo 'Deleteing private directories' +ssh root@$1 "cd $2/template/tmpl && for dir in \`ls | grep -v 1\$\`; do rm -rf \$dir; done" +echo 'Deleting system templates except for 1,2 and 3' +ssh root@$1 "cd $2/template/tmpl/1 && for dir in \`ls | grep -v \^1\$ | grep -v \^2\$ | grep -v \^3\$\`; do rm -rf \$dir; done" +} + + +dir=$(dirname "$0") +if [ -f $dir/../deploy.properties ]; then + . "$dir/../deploy.properties" +fi + +if [ "$USER" == "" ]; then + printf "ERROR: Need tospecify the user\n" + exit 4 +fi + + +#Delete all active users and kill the management server +for h in "$SERVER" +do + kill_server $h $VMOPSDIR +done + +#Kill vms and delete vlans on all computing hosts +for i in $COMPUTE +do + cleanup_linux $i +done + +#Cleanup management server +for i in $SERVER +do + echo "Starting cleanup on $i"; + cleanup_server $i $LOGDIR +done + +#Cleanup secondary storage +for i in $SECONDARY_STORAGE +do + echo "Starting cleanup on secondary storage $i"; + cleanup_storage $i $SECONDARY_STORAGE_DIR +done + + + diff --git a/test/scripts/deploy-and-run-regression.sh b/test/scripts/deploy-and-run-regression.sh new file mode 100755 index 00000000000..1c2e1c48840 --- /dev/null +++ b/test/scripts/deploy-and-run-regression.sh @@ -0,0 +1,53 @@ +#!/bin/bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + + +set -e +set -x + + +# $0: the name of myself +# $1: the dest host where we will run eeeeeeverything +# $2: the source dir to copy files from, on this machine +# $3: the dest dir in the dest machine where everything will be run + +# "${build.schedule.workingDir}/branches/GA-1.0.0-09-11-15/java/test/scripts/deploy-and-run-regression.sh" root@192.168.0.3 "${build.artifactsDir}" /root/artifacts + +dir=`dirname $0` +r=bootstrap-regression.sh + +host="$1" +src="$2" +dest="$3" + +srcbootstrapper="$dir"/"$r" # that script is launched from this one, remotely via ssh +destbootstrapper="$dest"/"$r" # this is the path on the remote machine + + +ssh -o BatchMode\ yes $host rm -rf $dest +scp -o BatchMode\ yes -r $src $host:$dest +scp -o BatchMode\ yes -r "$srcbootstrapper" $host:$destbootstrapper + +ssh -o BatchMode\ yes $host $destbootstrapper + diff --git a/test/scripts/deploy.sh b/test/scripts/deploy.sh new file mode 100755 index 00000000000..89ca6db8369 --- /dev/null +++ b/test/scripts/deploy.sh @@ -0,0 +1,174 @@ +#!/bin/bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + + +. /etc/rc.d/init.d/functions + +set -x + +usage() { + printf "Usage: %s: [-d] [-r] \n" $(basename $0) >&2 +} + +deploy_server() { + ssh root@$1 "yum remove -y \"cloud*\" ; yum clean all ; cd /usr/share/cloud/ && rm -rf * && rm -rf /var/cache/cloud ; yum install -y cloud-client cloud-premium cloud-usage" + ssh root@$1 "cloud-setup-databases alena@$2 xenserver" + ssh root@$1 "cd /usr/share/cloud/management/conf; sed '/db.cloud.url.params/ d' db.properties > db.properties1; dos2unix db.properties1; mv -f db.properties1 db.properties" + ssh root@$1 "cd /usr/share/cloud/management/conf; echo \db.cloud.url.params=includeInnodbStatusInDeadlockExceptions=true\&logSlowQueries=true\&prepStmtCacheSize=517\&cachePrepStmts=true >> db.properties" + if [ $? -gt 0 ]; then echo "failed to install on $1"; return 2; fi + echo "Management server is deployed successfully" +} + +deploy_db() { + echo "Deploying database on $1" + # ssh root@$1 "cp $CONFIGDIR/conf/templates.sql /usr/share/cloud/setup/templates.xenserver.sql " +ssh root@$1 "cloud-setup-databases alena@$1 --deploy-as=root xenserver" + if [ $? -gt 0 ]; then echo "failed to deploy db on $1"; return 2; fi + echo "Database is deployed successfully" +} + +run_server() { + ssh root@$1 "service cloud-management start; service cloud-usage start 2>&1 &" +} + +stop_server() { + ssh root@$1 "service cloud-management stop; service cloud-usage stop 2>&1 &" +} + +dir=$(dirname "$0") +if [ -f $dir/../deploy.properties ]; then + . "$dir/../deploy.properties" +fi + +if [ "$USER" == "" ]; then + printf "ERROR: Need tospecify the user\n" + exit 4 +fi + +if [ "$SERVER" == "" ]; then + printf "ERROR: Need to specify the management server\n" + exit 1 +fi + +installflag= +deployflag= +runflag= +killflag= +setupflag= +mgmtIp= +mode=expert +distdir=dist + +while getopts 'idkrsb:D' OPTION +do + case $OPTION in + i) installflag=1 + ;; + d) deployflag=1 + ;; + k) killflag=1 + ;; + r) runflag=1 + ;; + b) distdir="$OPTARG" + ;; + s) setupflag=1 + mode=setup + ;; + D) developer=1; distdir=dist/developer;; + + ?) usage + esac +done + + +if [ "$setupflag$deployflag$installflag$killflag$runflag" == "" ] +then + usage + exit +fi + + +if [ "$installflag" == "1" ] +then + echo "Deploying server...." + + for i in $SERVER + do + echo -n "$i: " + deploy_server $i $DB + if [ $? -gt 0 ]; then failure ; else success;fi + echo + done +fi + +if [ "$deployflag" == "1" ] +then + echo "Deploying database..." + for i in $DB + do + echo -n "$i: " + deploy_db $i + if [ $? -gt 0 ]; then failure ; else success;fi + echo + done +fi + + +if [ "$runflag" == "1" ] +then + echo "Starting Management server" + for i in $SERVER + do + run_server $i + sleep 30 + done + + +echo "Setting up configuration values..." + for i in $LB + do + DST='../src/' + java -cp ${DST}commons-httpclient-3.1.jar:${DST}mysql-connector-java-5.1.7-bin.jar:${DST}commons-logging-1.1.1.jar:${DST}commons-codec-1.4.jar:${DST}cloud-test.jar:${DST}log4j-1.2.15.jar:${DST}trilead-ssh2-build213.jar:${DST}cloud-utils.jar:.././conf com.cloud.test.regression.Deploy -h $i -f ../conf/deploy.xml + echo "Restarting Management server to apply configuration values" + done + +echo "Restarting management servers" + for i in $SERVER + do + echo "Restarting Management server to apply configuration values" + stop_server $i + run_server $i + sleep 60 + done + + +echo "Adding secondary/primary storage/hosts..." + for i in $LB + do + DST='../src/' + java -cp ${DST}commons-httpclient-3.1.jar:${DST}mysql-connector-java-5.1.7-bin.jar:${DST}commons-logging-1.1.1.jar:${DST}commons-codec-1.4.jar:${DST}cloud-test.jar:${DST}log4j-1.2.15.jar:${DST}trilead-ssh2-build213.jar:${DST}cloud-utils.jar:.././conf com.cloud.test.regression.Deploy -h $i -f ../conf/config.xml + done + +fi diff --git a/test/scripts/deploycluster.sh b/test/scripts/deploycluster.sh new file mode 100755 index 00000000000..fa829ea536d --- /dev/null +++ b/test/scripts/deploycluster.sh @@ -0,0 +1,79 @@ +#!/usr/bin/env bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + +set -x + +usage() { + printf "Usage: %s: [-f] [-d] [-i] \n" $(basename $0) >&2 +} + + +path= +db= +ips= + +while getopts 'p:d:i:' OPTION +do + case $OPTION in + p) path="$OPTARG" + ;; + d) db="$OPTARG" + ;; + i) ips="$OPTARG" + ;; + + ?) usage + esac +done + + +deploy_server() { + echo "Deploying management server software on remote machine $1" + + rsync -avzh -e ssh $path/cloudstack-oss root@$1:/root/ + if [ $? -gt 0 ]; then echo "failed to rsync software between $path/cloudstack-oss and and remote machine $1"; return 2; fi + + ssh root@$1 "cd /root/cloudstack-oss && ant clean build-all deploy-server" + if [ $? -gt 0 ]; then echo "failed to deploy cluster on $1"; return 2; fi + + + ssh root@$1 "dir=\`cat ~/.bashrc | grep 'export CATALINA_HOME' | awk -F '=' '{ print \$2}'\` && file=\$dir/conf/db.properties && sed '/cluster.node.IP/ d' \$file > db.properties1; dos2unix db.properties1; mv -f db.properties1 \$file; echo \cluster.node.IP=$1 >> \$file && file=\$dir/conf/db.properties && sed '/db.cloud.host/ d' \$file > db.properties1; dos2unix db.properties1; mv -f db.properties1 \$file; echo \db.cloud.host=$db >> \$file && file=\$dir/conf/db.properties && sed '/db.usage.host/ d' \$file > db.properties1; dos2unix db.properties1; mv -f db.properties1 \$file; echo \db.usage.host=$db >> \$file" + +if [ $? -gt 0 ]; then echo "failed to setup db.properties file on remote $1"; return 2; fi + +#ssh root@$1 "cd /root/cloudstack-oss && nohup ant run &" + #if [ $? -gt 0 ]; then echo "failed to start the softare on remote $1"; return 2; fi + + echo "Remote management server is deployed as a part of cluster setup; you have to start it manually by logging in remotely" +} + +export IFS="," +for ip in $ips; do + echo "$ip" + deploy_server $ip +done + + + + + diff --git a/test/scripts/executeUserAPI.sh b/test/scripts/executeUserAPI.sh new file mode 100755 index 00000000000..1d65e53ef9d --- /dev/null +++ b/test/scripts/executeUserAPI.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + +PATHSEP=':' +if [[ $OSTYPE == "cygwin" ]] ; then + PATHSEP=';' +fi + +#directory with jar files +DST='../src/' + +CP=${DST}commons-httpclient-3.1.jar${PATHSEP}${DST}commons-logging-1.1.1.jar${PATHSEP}${DST}commons-codec-1.4.jar${PATHSEP}${DST}testclient.jar${PATHSEP}.././conf +java -cp $CP com.cloud.sample.UserCloudAPIExecutor + + diff --git a/test/scripts/invoke.sh b/test/scripts/invoke.sh new file mode 100755 index 00000000000..049ef93a184 --- /dev/null +++ b/test/scripts/invoke.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + +cd /root/test/scripts && ./cleanparallel.sh && ./deploy.sh -i -d -r +if [ $? -ne 0 ]; then exit 2; fi; + +echo 'sleeping for 5 min before executing regression test' +sleep 600 +cd /root/test/scripts && ./regression.sh -type $1 diff --git a/test/scripts/regression.sh b/test/scripts/regression.sh new file mode 100755 index 00000000000..d8a881007c5 --- /dev/null +++ b/test/scripts/regression.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + +set -e +DST='../src/' +java -Xrunjdwp:transport=dt_socket,address=8789,server=y,suspend=n -ea -cp ${DST}commons-httpclient-3.1.jar:${DST}mysql-connector-java-5.1.7-bin.jar:${DST}commons-logging-1.1.1.jar:${DST}commons-codec-1.4.jar:${DST}cloud-test.jar:${DST}log4j.jar:${DST}trilead-ssh2-build213.jar:${DST}cloud-utils.jar:.././conf com.cloud.test.regression.TestCaseEngine $* diff --git a/test/scripts/run.bat b/test/scripts/run.bat new file mode 100644 index 00000000000..6a558508fc2 --- /dev/null +++ b/test/scripts/run.bat @@ -0,0 +1 @@ +java -cp "commons-httpclient-3.1.jar;commons-logging-1.1.1.jar;commons-codec-1.3.jar;testclient.jar;log4j-1.2.15.jar;trilead-ssh2-build213.jar;utils.jar;./conf" com.vmops.test.TestClientWithAPI %* \ No newline at end of file diff --git a/test/scripts/run.sh b/test/scripts/run.sh new file mode 100755 index 00000000000..39a7e53764f --- /dev/null +++ b/test/scripts/run.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + +PATHSEP=':' +if [[ $OSTYPE == "cygwin" ]] ; then + PATHSEP=';' +fi + +#directory with jar files +DST='../src/' + +CP=${DST}commons-httpclient-3.1.jar${PATHSEP}${DST}commons-logging-1.1.1.jar${PATHSEP}${DST}commons-codec-1.4.jar${PATHSEP}${DST}cloud-test.jar${PATHSEP}${DST}log4j.jar${PATHSEP}${DST}trilead-ssh2-build213.jar${PATHSEP}${DST}cloud-utils.jar${PATHSEP}.././conf +java -cp $CP com.cloud.test.stress.TestClientWithAPI $* +#java -cp $CP com.cloud.test.stress.StressTestDirectAttach $* + diff --git a/test/scripts/sign.sh b/test/scripts/sign.sh new file mode 100755 index 00000000000..24f39fe3b33 --- /dev/null +++ b/test/scripts/sign.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + +set -e +DST='../src/' + +java -cp ${DST}cloud-test.jar:${DST}cloud-utils.jar com.cloud.test.utils.SignRequest $* diff --git a/test/scripts/signEC2.sh b/test/scripts/signEC2.sh new file mode 100755 index 00000000000..965af050066 --- /dev/null +++ b/test/scripts/signEC2.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + +set -e +DST='../src/' +#java -cp ${DST}commons-httpclient-3.1.jar:${DST}mysql-connector-java-5.1.7-bin.jar:${DST}commons-logging-1.1.1.jar:${DST}commons-codec-1.3.jar:${DST}cloud-test.jar:${DST}log4j-1.2.15.jar:${DST}trilead-ssh2-build213.jar:${DST}cloud-utils.jar:.././conf com.cloud.test.utils.SignRequest $* + +java -cp ${DST}commons-httpclient-3.1.jar:${DST}mysql-connector-java-5.1.7-bin.jar:${DST}commons-logging-1.1.1.jar:${DST}commons-codec-1.3.jar:${DST}cloud-test.jar:${DST}log4j-1.2.15.jar:${DST}trilead-ssh2-build213.jar:${DST}cloud-utils.jar:.././conf com.cloud.test.utils.SignEC2 $* diff --git a/test/scripts/usage/allocated.sh b/test/scripts/usage/allocated.sh new file mode 100755 index 00000000000..384c672b24a --- /dev/null +++ b/test/scripts/usage/allocated.sh @@ -0,0 +1,88 @@ +#!/bin/bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + +#set -x +iteration=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select count(*) from account;") +echo "Created/Destroyed for the first VM:\n" +for ((i=3; i<$iteration+1; i++)) +do +vm_name=$(mysql -h $1 --user=root --skip-column-names -U cloud -e "select v.name from vm_instance v, user_vm u where v.id=u.id and u.account_id=$i limit 0,1;") +created_time=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select TIME_TO_SEC(created) from event where description like '%$vm_name%' and type='VM.CREATE' and level='INFO';") +destroyed_time=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select TIME_TO_SEC(created) from event where description like '%$vm_name%' and type='VM.DESTROY' and level='INFO';") + + +if [ "$vm_name" != "" ] && [ "$destroyed_time" != "" ] +then + +event_time=`expr $destroyed_time - $created_time` +cloud_usage_time=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select ROUND(SUM(raw_usage*3600)) from cloud_usage where usage_type=2 and description like '%$vm_name%';") + +if [ "$cloud_usage_time" = "NULL" ] +then +echo "Running time is missing in cloud_usage table for VM $vm_name belonging to account $i" +else +temp=`expr $event_time - $cloud_usage_time` +if [ $temp -ne 0 ] && [ $temp != "-86400" ] +then +echo "For account $i difference in running time for vm $vm_name is $temp" +else +echo "Test passed for the first VM belonging to account $i" +fi +fi +else +echo "Skipping verification for account $i (the account either a) misses the first VM b) VM wasn't destroyed 3) VM Destroy failed " +fi +done + +echo "Created/Destroyed for the second VM:\n" +for ((i=3; i<$iteration+1; i++)) +do +vm_name=$(mysql -h $1 --user=root --skip-column-names -U cloud -e "select v.name from vm_instance v, user_vm u where v.id=u.id and u.account_id=$i limit 1,1;") +created_time=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select TIME_TO_SEC(created) from event where description like '%$vm_name%' and type='VM.CREATE' and level='INFO';") +destroyed_time=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select TIME_TO_SEC(created) from event where description like '%$vm_name%' and type='VM.DESTROY' and level='INFO';") + + +if [ "$vm_name" != "" ] && [ "$destroyed_time" != "" ] +then + +event_time=`expr $destroyed_time - $created_time` +cloud_usage_time=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select ROUND(SUM(raw_usage*3600)) from cloud_usage where usage_type=2 and description like '%$vm_name%';") + +if [ "$cloud_usage_time" = "NULL" ] +then +echo "Running time is missing in cloud_usage table for VM $vm_name belonging to account $i" +else +temp=`expr $event_time - $cloud_usage_time` +if [ $temp -ne 0 ] && [ $temp != "-86400" ] +then +echo "For account $i difference in running time for vm $vm_name is $temp" +else +echo "Test passed for the second vm belonging to account $i" +fi +fi +else +echo "Skipping verification for account $i (the account either a) misses the second VM b) VM wasn't stopped 3) VM Stop failed " +fi +done + diff --git a/test/scripts/usage/network.sh b/test/scripts/usage/network.sh new file mode 100755 index 00000000000..4eea8eb06fb --- /dev/null +++ b/test/scripts/usage/network.sh @@ -0,0 +1,73 @@ +#!/bin/bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + +#set -x +iteration=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select count(*) from user_statistics;") +echo "Bytes received:" +for ((i=3; i<$iteration; i++)) +do +cloud_usage=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select SUM(raw_usage) from cloud_usage where account_id=$i and usage_type=5;") +if [ "$cloud_usage" = "NULL" ] +then +cloud_usage=0 +fi + +user_stat=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select net_bytes_received+current_bytes_received from user_statistics where account_id=$i;") + +if [ "$user_stat" = "" ] +then +user_stat=0 +fi + +temp=`expr $user_stat - $cloud_usage` +if [ $temp -ne 0 ] +then +echo "For account $i difference in bytes_received is $temp" +fi +done + +echo "\n" +echo "Bytes sent:" +for ((i=3; i<$iteration; i++)) +do +cloud_usage=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select SUM(raw_usage) from cloud_usage where account_id=$i and usage_type=4;") + +if [ "$cloud_usage" = "NULL" ] +then +cloud_usage=0 +fi + +user_stat=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select net_bytes_sent+current_bytes_sent from user_statistics where account_id=$i;") + +if [ "$user_stat" = "" ] +then +user_stat=0 +fi + +temp=`expr $user_stat - $cloud_usage` +if [ $temp -ne 0 ] +then +echo "For account $i difference in bytes_sent is $temp" +fi +done diff --git a/test/scripts/usage/running.sh b/test/scripts/usage/running.sh new file mode 100755 index 00000000000..4822cf15c0e --- /dev/null +++ b/test/scripts/usage/running.sh @@ -0,0 +1,89 @@ +#!/bin/bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + +#set -x +iteration=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select count(*) from account;") +echo "Started/Stopped for the first VM:\n" +for ((i=3; i<$iteration+1; i++)) +do +vm_name=$(mysql -h $1 --user=root --skip-column-names -U cloud -e "select v.name from vm_instance v, user_vm u where v.id=u.id and u.account_id=$i limit 0,1;") +created_time=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select TIME_TO_SEC(created) from event where description like '%$vm_name%' and type='VM.START' and level='INFO';") +destroyed_time=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select TIME_TO_SEC(created) from event where description like '%$vm_name%' and type='VM.STOP' and level='INFO';") + + +if [ "$vm_name" != "" ] && [ "$destroyed_time" != "" ] +then + +event_time=`expr $destroyed_time - $created_time` +cloud_usage_time=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select ROUND(SUM(raw_usage*3600)) from cloud_usage where usage_type=1 and description like '%$vm_name%';") + +if [ "$cloud_usage_time" = "NULL" ] +then +echo "Running time is missing in cloud_usage table for VM $vm_name belonging to account $i" +else +temp=`expr $event_time - $cloud_usage_time` +if [ $temp -ne 0 ] && [ $temp != "-86400" ] +then +echo "For account $i difference in running time for vm $vm_name is $temp" +else +echo "Test passed for the first VM belonging to account $i" +fi +fi +else +echo "Skipping verification for account $i (the account either a) misses the first VM b) VM wasn't stopped 3) VM Stop failed " +fi +done + + + +echo "Started/Stopped for the second VM:\n" +for ((i=3; i<$iteration+1; i++)) +do +vm_name=$(mysql -h $1 --user=root --skip-column-names -U cloud -e "select v.name from vm_instance v, user_vm u where v.id=u.id and u.account_id=$i limit 1,1;") +created_time=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select TIME_TO_SEC(created) from event where description like '%$vm_name%' and type='VM.START' and level='INFO';") +destroyed_time=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select TIME_TO_SEC(created) from event where description like '%$vm_name%' and type='VM.STOP' and level='INFO';") + + +if [ "$vm_name" != "" ] && [ "$destroyed_time" != "" ] +then + +event_time=`expr $destroyed_time - $created_time` +cloud_usage_time=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select ROUND(SUM(raw_usage*3600)) from cloud_usage where usage_type=1 and description like '%$vm_name%';") + +if [ "$cloud_usage_time" = "NULL" ] +then +echo "Running time is missing in cloud_usage table for VM $vm_name belonging to account $i" +else +temp=`expr $event_time - $cloud_usage_time` +if [ $temp -ne 0 ] && [ $temp != "-86400" ] +then +echo "For account $i difference in running time for vm $vm_name is $temp" +else +echo "Test passed for the second vm belonging to account $i" +fi +fi +else +echo "Skipping verification for account $i (the account either a) misses the second VM b) VM wasn't stopped 3) VM Stop failed " +fi +done diff --git a/test/scripts/usage/volume_usage.sh b/test/scripts/usage/volume_usage.sh new file mode 100755 index 00000000000..5b255f3b0ee --- /dev/null +++ b/test/scripts/usage/volume_usage.sh @@ -0,0 +1,163 @@ +#!/bin/bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + +#set -x +#Check first ROOT volume +iteration=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select count(*) from account;") +echo "Created/removed for the first ROOT volume:\n" +for ((i=3; i<$iteration+1; i++)) +do +volume_name=$(mysql -h $1 --user=root --skip-column-names -U cloud -e "select name from volumes where account_id=$i and volume_type='ROOT' and name like 'i-%' limit 0,1;") +volume_id=$(mysql -h $1 --user=root --skip-column-names -U cloud -e "select id from volumes where account_id=$i and volume_type='ROOT' and name like 'i-%'limit 0,1;") +created_time=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select TIME_TO_SEC(created) from event where description like '%$volume_name%' and type='VOLUME.CREATE' and level='INFO';") +destroyed_time=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select TIME_TO_SEC(created) from event where description like '%$volume_name%' and type='VOLUME.DELETE' and level='INFO';") + + +if [ "$volume_name" != "" ] && [ "$destroyed_time" != "" ] +then + +event_time=`expr $destroyed_time - $created_time` +cloud_usage_time=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select ROUND(SUM(raw_usage*3600)) from cloud_usage where usage_type=6 and description like '%Volume Id: $volume_id%';") + +if [ "$cloud_usage_time" = "NULL" ] +then +echo "Allocated time is missing in cloud_usage table for volume $volume_name belonging to account $i" +else +temp=`expr $event_time - $cloud_usage_time` +if [ $temp -ne 0 ] && [ $temp != "-86400" ] +then +echo "For account $i difference in time for volume $volume_name is $temp" +else +echo "Test passed for the ROOT volume $volume_name belonging to account $i" +fi +fi +else +echo "Skipping verification for account $i (the account either a) misses root volume $volume_name b) volume wasn't deleted 3) Delete volume failed " +fi +done + +#Check second ROOT volume +iteration=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select count(*) from account;") +echo "Created/removed for the second ROOT volume:\n" +for ((i=3; i<$iteration+1; i++)) +do +volume_name=$(mysql -h $1 --user=root --skip-column-names -U cloud -e "select name from volumes where account_id=$i and volume_type='ROOT' and name like 'i-%' limit 1,1;") +volume_id=$(mysql -h $1 --user=root --skip-column-names -U cloud -e "select id from volumes where account_id=$i and volume_type='ROOT' and name like 'i-%'limit 1,1;") +created_time=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select TIME_TO_SEC(created) from event where description like '%$volume_name%' and type='VOLUME.CREATE' and level='INFO';") +destroyed_time=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select TIME_TO_SEC(created) from event where description like '%$volume_name%' and type='VOLUME.DELETE' and level='INFO';") + + +if [ "$volume_name" != "" ] && [ "$destroyed_time" != "" ] +then + +event_time=`expr $destroyed_time - $created_time` +cloud_usage_time=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select ROUND(SUM(raw_usage*3600)) from cloud_usage where usage_type=6 and description like '%Volume Id: $volume_id%';") + +if [ "$cloud_usage_time" = "NULL" ] +then +echo "Allocated time is missing in cloud_usage table for volume $volume_name belonging to account $i" +else +temp=`expr $event_time - $cloud_usage_time` +if [ $temp -ne 0 ] && [ $temp != "-86400" ] +then +echo "For account $i difference in time for volume $volume_name is $temp" +else +echo "Test passed for the ROOT volume $volume_name belonging to account $i" +fi +fi +else +echo "Skipping verification for account $i (the account either a) misses root volume $volume_name b) volume wasn't deleted 3) Delete volume failed " +fi +done + + +#Check first DATADISK volume +iteration=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select count(*) from account;") +echo "Created/removed for the first DATADISK volume:\n" +for ((i=3; i<$iteration+1; i++)) +do +volume_name=$(mysql -h $1 --user=root --skip-column-names -U cloud -e "select name from volumes where account_id=$i and volume_type='DATADISK' and name like 'i-%' limit 0,1;") +volume_id=$(mysql -h $1 --user=root --skip-column-names -U cloud -e "select id from volumes where account_id=$i and volume_type='DATADISK' and name like 'i-%'limit 0,1;") +created_time=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select TIME_TO_SEC(created) from event where description like '%$volume_name%' and type='VOLUME.CREATE' and level='INFO';") +destroyed_time=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select TIME_TO_SEC(created) from event where description like '%$volume_name%' and type='VOLUME.DELETE' and level='INFO';") + + +if [ "$volume_name" != "" ] && [ "$destroyed_time" != "" ] +then + +event_time=`expr $destroyed_time - $created_time` +cloud_usage_time=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select ROUND(SUM(raw_usage*3600)) from cloud_usage where usage_type=6 and description like '%Volume Id: $volume_id%';") + +if [ "$cloud_usage_time" = "NULL" ] +then +echo "Allocated time is missing in cloud_usage table for volume $volume_name belonging to account $i" +else +temp=`expr $event_time - $cloud_usage_time` +if [ $temp -ne 0 ] && [ $temp != "-86400" ] +then +echo "For account $i difference in time for volume $volume_name is $temp" +else +echo "Test passed for the DATADISK volume $volume_name belonging to account $i" +fi +fi +else +echo "Skipping verification for account $i (the account either a) misses root volume $volume_name b) volume wasn't deleted 3) Delete volume failed " +fi +done + +#Check second DATADISK volume +iteration=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select count(*) from account;") +echo "Created/removed for the second DATADISK volume:\n" +for ((i=3; i<$iteration+1; i++)) +do +volume_name=$(mysql -h $1 --user=root --skip-column-names -U cloud -e "select name from volumes where account_id=$i and volume_type='DATADISK' and name like 'i-%' limit 1,1;") +volume_id=$(mysql -h $1 --user=root --skip-column-names -U cloud -e "select id from volumes where account_id=$i and volume_type='DATADISK' and name like 'i-%'limit 1,1;") +created_time=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select TIME_TO_SEC(created) from event where description like '%$volume_name%' and type='VOLUME.CREATE' and level='INFO';") +destroyed_time=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select TIME_TO_SEC(created) from event where description like '%$volume_name%' and type='VOLUME.DELETE' and level='INFO';") + + +if [ "$volume_name" != "" ] && [ "$destroyed_time" != "" ] +then + +event_time=`expr $destroyed_time - $created_time` +cloud_usage_time=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select ROUND(SUM(raw_usage*3600)) from cloud_usage where usage_type=6 and description like '%Volume Id: $volume_id%';") + +if [ "$cloud_usage_time" = "NULL" ] +then +echo "Allocated time is missing in cloud_usage table for volume $volume_name belonging to account $i" +else +temp=`expr $event_time - $cloud_usage_time` +if [ $temp -ne 0 ] && [ $temp != "-86400" ] +then +echo "For account $i difference in time for volume $volume_name is $temp" +else +echo "Test passed for the DATADISK volume $volume_name belonging to account $i" +fi +fi +else +echo "Skipping verification for account $i (the account either a) misses root volume $volume_name b) volume wasn't deleted 3) Delete volume failed " +fi +done + + diff --git a/test/scripts/usercloud.properties b/test/scripts/usercloud.properties new file mode 100644 index 00000000000..f93c37305fa --- /dev/null +++ b/test/scripts/usercloud.properties @@ -0,0 +1,4 @@ +host=http://localhost:8080/client/api +apiUrl=command=deployVirtualMachine&serviceOfferingId=1&diskOfferingId=1&templateId=2&zoneId=4&displayName=Test +apiKey=miVr6X7u6bN_sdahOBpjNejPgEsT35eXq-jB8CG20YI3yaxXcgpyuaIRmFI_EJTVwZ0nUkkJbPmY3y2bciKwFQ +secretKey=AdpTvsQMZwv9MNvfqDcQhWSL9pHQvq7z13CFP2SU1iToDkkM3d8iZciWEKsGREhMtV9yLVMxmbbJJgrXo8O5jg \ No newline at end of file diff --git a/test/scripts/wget.exe b/test/scripts/wget.exe new file mode 100644 index 0000000000000000000000000000000000000000..1b15a04242a5a785758ac4ec39d3985c97e203de GIT binary patch literal 162816 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 z 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

;?^Rlcrd|1CJKe@Zl`H4Qe=H57( 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 esv;Mre. + # + # + + + +host="" +account="" +templateid="" +storage="" +var="" + +while getopts h:s:a:i: OPTION +do + case $OPTION in + a) account="$OPTARG" + ;; + i) templateid="$OPTARG" + ;; + h) host="$OPTARG" + ;; + s) storage="$OPTARG" + esac +done + +var=`ssh root@$host "cd $storage && mv template/tmpl/$account/$templateid/template.properties template/tmpl/$account/$templateid/template.properties1 && touch template/tmpl/$account/$templateid/template.properties"` + + +if [ "$var" != "" ] +then echo "Was unable to corrupt template $path on host $host" +exit 2 +else +exit 0 +fi \ No newline at end of file diff --git a/test/scripts/xen/createfaketemplate.sh b/test/scripts/xen/createfaketemplate.sh new file mode 100755 index 00000000000..902cb271d09 --- /dev/null +++ b/test/scripts/xen/createfaketemplate.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + + +host="" +account="" +templateid="" +storage="" +var="" +dir="" + +while getopts h:s:a:i:d: OPTION +do + case $OPTION in + a) account="$OPTARG" + ;; + i) templateid="$OPTARG" + ;; + h) host="$OPTARG" + ;; + s) storage="$OPTARG" + ;; + d) dir="$OPTARG" + esac +done + +var=`ssh root@$host "cd $storage && cp -rf template/tmpl/$account/$templateid template/tmpl/$account/$dir` + +if [ "$var" != "" ] +then echo "Was unable to create fake template on host $host" +exit 2 +else +exit 0 +fi \ No newline at end of file diff --git a/test/scripts/xen/killvm.sh b/test/scripts/xen/killvm.sh new file mode 100755 index 00000000000..d99311e8494 --- /dev/null +++ b/test/scripts/xen/killvm.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + + +uuid="" +name="" +host="" + +while getopts n:h: OPTION +do + case $OPTION in + n) name="$OPTARG" + ;; + h) host="$OPTARG" + esac +done + + + +if [ "$name" != "" ] +then + uuid=`ssh root@$host "xe vm-list name-label=$name | grep uuid | awk '{print \\$5}'"` +fi + +echo "uuid is $uuid" +var=`ssh root@$host "xe vm-shutdown uuid=$uuid; xe vm-destroy uuid=$uuid"` + +if [ "$var" != "" ] +then echo "Was unable to destroy the vm with name $name and uuid $uuid on host $host" +exit 2 +else +exit 0 +fi \ No newline at end of file diff --git a/test/scripts/xen/listtemplate.sh b/test/scripts/xen/listtemplate.sh new file mode 100755 index 00000000000..d0322f8691f --- /dev/null +++ b/test/scripts/xen/listtemplate.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + + +host="" +path="" +storage="" +var="" + +while getopts h:s:p: OPTION +do + case $OPTION in + p) path="$OPTARG" + ;; + h) host="$OPTARG" + ;; + s) storage="$OPTARG" + esac +done + + var=`ssh root@$host "ls -ltr $storage/$path"` + +if [ "$var" == "" ] +then echo "Template $path doesn't exist on storage host $host" +exit 2 +else +exit 0 +fi \ No newline at end of file diff --git a/test/scripts/xen/listvdi.sh b/test/scripts/xen/listvdi.sh new file mode 100755 index 00000000000..1374e2dd9b7 --- /dev/null +++ b/test/scripts/xen/listvdi.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + + +uuid="" +name="" +host="" +var="" + +while getopts u:n:h: OPTION +do + case $OPTION in + u) uuid="$OPTARG" + ;; + n) name="$OPTARG" + ;; + h) host="$OPTARG" + esac +done + + + +if [ "$uuid" != "" ] +then + var=`ssh root@$host "xe vdi-list uuid=$uuid"` +else + if [ "$name" != "" ] + then + var=`ssh root@$host "xe vdi-list name-label=$name"` + fi +fi + + +if [ "$var" == "" ] +then echo "VDI $name $uuid doesn't exist on host $host" +exit 2 +else +exit 0 +fi \ No newline at end of file diff --git a/test/scripts/xen/listvm.sh b/test/scripts/xen/listvm.sh new file mode 100755 index 00000000000..c7dac04ed23 --- /dev/null +++ b/test/scripts/xen/listvm.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + + +uuid="" +name="" +host="" +var="" + +while getopts u:n:h: OPTION +do + case $OPTION in + u) uuid="$OPTARG" + ;; + n) name="$OPTARG" + ;; + h) host="$OPTARG" + esac +done + + + +if [ "$uuid" != "" ] +then + var=`ssh root@$host "xe vm-list uuid=$uuid"` +else + if [ "$name" != "" ] + then + var=`ssh root@$host "xe vm-list name-label=$name"` + fi +fi + + +if [ "$var" == "" ] +then echo "VM $name doesn't exist on host $host" +exit 2 +else +exit 0 +fi \ No newline at end of file diff --git a/test/scripts/xen/ms.sh b/test/scripts/xen/ms.sh new file mode 100755 index 00000000000..785603c8c10 --- /dev/null +++ b/test/scripts/xen/ms.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + + +host="" +operation="" + +while getopts h:o: OPTION +do + case $OPTION in + h) host="$OPTARG" + ;; + o) operation="$OPTARG" + esac +done + +var=`ssh root@$host "service cloud-management $operation"` +sleep 30 + +exit 0 +fi \ No newline at end of file diff --git a/test/scripts/xen/removetemplate.sh b/test/scripts/xen/removetemplate.sh new file mode 100755 index 00000000000..901963a3678 --- /dev/null +++ b/test/scripts/xen/removetemplate.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + + +host="" +path="" +storage="" +var="" + +while getopts h:s:p: OPTION +do + case $OPTION in + p) path="$OPTARG" + ;; + h) host="$OPTARG" + ;; + s) storage="$OPTARG" + esac +done + +if [ $path != "" ] +then + var=`ssh root@$host "cd $storage && rm -rf $path"` +fi + + +if [ "$var" != "" ] +then echo "Was unable to remove template $path from host $host" +exit 2 +else +exit 0 +fi \ No newline at end of file diff --git a/test/scripts/xen/shutdown.sh b/test/scripts/xen/shutdown.sh new file mode 100755 index 00000000000..b95a2915023 --- /dev/null +++ b/test/scripts/xen/shutdown.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + + +uuid="" +name="" +host="" + +while getopts n:h: OPTION +do + case $OPTION in + n) name="$OPTARG" + ;; + h) host="$OPTARG" + esac +done + + + +if [ "$name" != "" ] +then + uuid=`ssh root@$host "xe vm-list name-label=$name | grep uuid | awk '{print \\$5}'"` +fi + +echo "uuid is $uuid" +var=`ssh root@$host "xe vm-shutdown uuid=$uuid;"` + +if [ "$var" != "" ] +then echo "Was unable to shutdown the vm with name $name and uuid $uuid on host $host" +exit 2 +else +exit 0 +fi \ No newline at end of file diff --git a/test/scripts/xen/sleep.sh b/test/scripts/xen/sleep.sh new file mode 100755 index 00000000000..9192b14cd52 --- /dev/null +++ b/test/scripts/xen/sleep.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + + +sleep=60 + +while getopts s: OPTION +do + case $OPTION in + s) sleep=$OPTARG + esac +done + +sleep $sleep \ No newline at end of file diff --git a/test/scripts/xen/ssh.sh b/test/scripts/xen/ssh.sh new file mode 100755 index 00000000000..1e84085ec47 --- /dev/null +++ b/test/scripts/xen/ssh.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash + + + + # + # Copyright (C) 2011 Citrix Systems, Inc. All rights reserved + # + # + # This software is licensed under the GNU General Public License v3 or later. + # + # It is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or any later version. + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # + + + +PATHSEP=':' +if [[ $OSTYPE == "cygwin" ]] ; then + PATHSEP=';' +fi + +DST='../src/' +password="" +host="" +url="" + +while getopts p:h:u: OPTION +do + case $OPTION in + p) password="$OPTARG" + ;; + h) host="$OPTARG" + ;; + u) url="$OPTARG" + esac +done + + +CP=${DST}commons-httpclient-3.1.jar${PATHSEP}${DST}commons-logging-1.1.1.jar${PATHSEP}${DST}commons-codec-1.4.jar${PATHSEP}${DST}cloud-test.jar${PATHSEP}${DST}log4j-1.2.15.jar${PATHSEP}${DST}trilead-ssh2-build213.jar${PATHSEP}${DST}cloud-utils.jar${PATHSEP}.././conf +java -cp $CP com.cloud.test.stress.SshTest $* diff --git a/test/src/com/cloud/sample/Base64.java b/test/src/com/cloud/sample/Base64.java new file mode 100644 index 00000000000..34027b28952 --- /dev/null +++ b/test/src/com/cloud/sample/Base64.java @@ -0,0 +1,1759 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.sample; + +/** + *

Encodes and decodes to and from Base64 notation.

+ *

Homepage: http://iharder.net/base64.

+ * + *

+ * Change Log: + *

+ *
    + *
  • v2.2.1 - Fixed bug using URL_SAFE and ORDERED encodings. Fixed bug + * when using very small files (~< 40 bytes).
  • + *
  • v2.2 - Added some helper methods for encoding/decoding directly from + * one file to the next. Also added a main() method to support command line + * encoding/decoding from one file to the next. Also added these Base64 dialects: + *
      + *
    1. The default is RFC3548 format.
    2. + *
    3. Calling Base64.setFormat(Base64.BASE64_FORMAT.URLSAFE_FORMAT) generates + * URL and file name friendly format as described in Section 4 of RFC3548. + * http://www.faqs.org/rfcs/rfc3548.html
    4. + *
    5. Calling Base64.setFormat(Base64.BASE64_FORMAT.ORDERED_FORMAT) generates + * URL and file name friendly format that preserves lexical ordering as described + * in http://www.faqs.org/qa/rfcc-1940.html
    6. + *
    + * Special thanks to Jim Kellerman at http://www.powerset.com/ + * for contributing the new Base64 dialects. + *
  • + * + *
  • v2.1 - Cleaned up javadoc comments and unused variables and methods. Added + * some convenience methods for reading and writing to and from files.
  • + *
  • v2.0.2 - Now specifies UTF-8 encoding in places where the code fails on systems + * with other encodings (like EBCDIC).
  • + *
  • v2.0.1 - Fixed an error when decoding a single byte, that is, when the + * encoded data was a single byte.
  • + *
  • v2.0 - I got rid of methods that used booleans to set options. + * Now everything is more consolidated and cleaner. The code now detects + * when data that's being decoded is gzip-compressed and will decompress it + * automatically. Generally things are cleaner. You'll probably have to + * change some method calls that you were making to support the new + * options format (ints that you "OR" together).
  • + *
  • v1.5.1 - Fixed bug when decompressing and decoding to a + * byte[] using decode( String s, boolean gzipCompressed ). + * Added the ability to "suspend" encoding in the Output Stream so + * you can turn on and off the encoding if you need to embed base64 + * data in an otherwise "normal" stream (like an XML file).
  • + *
  • v1.5 - Output stream pases on flush() command but doesn't do anything itself. + * This helps when using GZIP streams. + * Added the ability to GZip-compress objects before encoding them.
  • + *
  • v1.4 - Added helper methods to read/write files.
  • + *
  • v1.3.6 - Fixed OutputStream.flush() so that 'position' is reset.
  • + *
  • v1.3.5 - Added flag to turn on and off line breaks. Fixed bug in input stream + * where last buffer being read, if not completely full, was not returned.
  • + *
  • v1.3.4 - Fixed when "improperly padded stream" error was thrown at the wrong time.
  • + *
  • v1.3.3 - Fixed I/O streams which were totally messed up.
  • + *
+ * + *

+ * I am placing this code in the Public Domain. Do with it as you will. + * This software comes with no guarantees or warranties but with + * plenty of well-wishing instead! + * Please visit http://iharder.net/base64 + * periodically to check for updates or to contribute improvements. + *

+ * + * @author Robert Harder + * @author rob@iharder.net + * @version 2.2.1 + */ +public class Base64 +{ + +/* ******** P U B L I C F I E L D S ******** */ + + + /** No options specified. Value is zero. */ + public final static int NO_OPTIONS = 0; + + /** Specify encoding. */ + public final static int ENCODE = 1; + + + /** Specify decoding. */ + public final static int DECODE = 0; + + + /** Specify that data should be gzip-compressed. */ + public final static int GZIP = 2; + + + /** Don't break lines when encoding (violates strict Base64 specification) */ + public final static int DONT_BREAK_LINES = 8; + + /** + * Encode using Base64-like encoding that is URL- and Filename-safe as described + * in Section 4 of RFC3548: + * http://www.faqs.org/rfcs/rfc3548.html. + * It is important to note that data encoded this way is not officially valid Base64, + * or at the very least should not be called Base64 without also specifying that is + * was encoded using the URL- and Filename-safe dialect. + */ + public final static int URL_SAFE = 16; + + + /** + * Encode using the special "ordered" dialect of Base64 described here: + * http://www.faqs.org/qa/rfcc-1940.html. + */ + public final static int ORDERED = 32; + + +/* ******** P R I V A T E F I E L D S ******** */ + + + /** Maximum line length (76) of Base64 output. */ + private final static int MAX_LINE_LENGTH = 76; + + + /** The equals sign (=) as a byte. */ + private final static byte EQUALS_SIGN = (byte)'='; + + + /** The new line character (\n) as a byte. */ + private final static byte NEW_LINE = (byte)'\n'; + + + /** Preferred encoding. */ + private final static String PREFERRED_ENCODING = "UTF-8"; + + + // I think I end up not using the BAD_ENCODING indicator. + //private final static byte BAD_ENCODING = -9; // Indicates error in encoding + private final static byte WHITE_SPACE_ENC = -5; // Indicates white space in encoding + private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in encoding + + +/* ******** S T A N D A R D B A S E 6 4 A L P H A B E T ******** */ + + /** The 64 valid Base64 values. */ + //private final static byte[] ALPHABET; + /* Host platform me be something funny like EBCDIC, so we hardcode these values. */ + private final static byte[] _STANDARD_ALPHABET = + { + (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', + (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', + (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', + (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', + (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', + (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', + (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', + (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z', + (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', + (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'+', (byte)'/' + }; + + + /** + * Translates a Base64 value to either its 6-bit reconstruction value + * or a negative number indicating some other meaning. + **/ + private final static byte[] _STANDARD_DECODABET = + { + -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8 + -5,-5, // Whitespace: Tab and Linefeed + -9,-9, // Decimal 11 - 12 + -5, // Whitespace: Carriage Return + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26 + -9,-9,-9,-9,-9, // Decimal 27 - 31 + -5, // Whitespace: Space + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42 + 62, // Plus sign at decimal 43 + -9,-9,-9, // Decimal 44 - 46 + 63, // Slash at decimal 47 + 52,53,54,55,56,57,58,59,60,61, // Numbers zero through nine + -9,-9,-9, // Decimal 58 - 60 + -1, // Equals sign at decimal 61 + -9,-9,-9, // Decimal 62 - 64 + 0,1,2,3,4,5,6,7,8,9,10,11,12,13, // Letters 'A' through 'N' + 14,15,16,17,18,19,20,21,22,23,24,25, // Letters 'O' through 'Z' + -9,-9,-9,-9,-9,-9, // Decimal 91 - 96 + 26,27,28,29,30,31,32,33,34,35,36,37,38, // Letters 'a' through 'm' + 39,40,41,42,43,44,45,46,47,48,49,50,51, // Letters 'n' through 'z' + -9,-9,-9,-9 // Decimal 123 - 126 + /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */ + }; + + +/* ******** U R L S A F E B A S E 6 4 A L P H A B E T ******** */ + + /** + * Used in the URL- and Filename-safe dialect described in Section 4 of RFC3548: + * http://www.faqs.org/rfcs/rfc3548.html. + * Notice that the last two bytes become "hyphen" and "underscore" instead of "plus" and "slash." + */ + private final static byte[] _URL_SAFE_ALPHABET = + { + (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', + (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', + (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', + (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', + (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', + (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', + (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', + (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z', + (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', + (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'-', (byte)'_' + }; + + /** + * Used in decoding URL- and Filename-safe dialects of Base64. + */ + private final static byte[] _URL_SAFE_DECODABET = + { + -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8 + -5,-5, // Whitespace: Tab and Linefeed + -9,-9, // Decimal 11 - 12 + -5, // Whitespace: Carriage Return + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26 + -9,-9,-9,-9,-9, // Decimal 27 - 31 + -5, // Whitespace: Space + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42 + -9, // Plus sign at decimal 43 + -9, // Decimal 44 + 62, // Minus sign at decimal 45 + -9, // Decimal 46 + -9, // Slash at decimal 47 + 52,53,54,55,56,57,58,59,60,61, // Numbers zero through nine + -9,-9,-9, // Decimal 58 - 60 + -1, // Equals sign at decimal 61 + -9,-9,-9, // Decimal 62 - 64 + 0,1,2,3,4,5,6,7,8,9,10,11,12,13, // Letters 'A' through 'N' + 14,15,16,17,18,19,20,21,22,23,24,25, // Letters 'O' through 'Z' + -9,-9,-9,-9, // Decimal 91 - 94 + 63, // Underscore at decimal 95 + -9, // Decimal 96 + 26,27,28,29,30,31,32,33,34,35,36,37,38, // Letters 'a' through 'm' + 39,40,41,42,43,44,45,46,47,48,49,50,51, // Letters 'n' through 'z' + -9,-9,-9,-9 // Decimal 123 - 126 + /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */ + }; + + + +/* ******** O R D E R E D B A S E 6 4 A L P H A B E T ******** */ + + /** + * I don't get the point of this technique, but it is described here: + * http://www.faqs.org/qa/rfcc-1940.html. + */ + private final static byte[] _ORDERED_ALPHABET = + { + (byte)'-', + (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', + (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9', + (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', + (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', + (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', + (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', + (byte)'_', + (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', + (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', + (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', + (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z' + }; + + /** + * Used in decoding the "ordered" dialect of Base64. + */ + private final static byte[] _ORDERED_DECODABET = + { + -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8 + -5,-5, // Whitespace: Tab and Linefeed + -9,-9, // Decimal 11 - 12 + -5, // Whitespace: Carriage Return + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26 + -9,-9,-9,-9,-9, // Decimal 27 - 31 + -5, // Whitespace: Space + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42 + -9, // Plus sign at decimal 43 + -9, // Decimal 44 + 0, // Minus sign at decimal 45 + -9, // Decimal 46 + -9, // Slash at decimal 47 + 1,2,3,4,5,6,7,8,9,10, // Numbers zero through nine + -9,-9,-9, // Decimal 58 - 60 + -1, // Equals sign at decimal 61 + -9,-9,-9, // Decimal 62 - 64 + 11,12,13,14,15,16,17,18,19,20,21,22,23, // Letters 'A' through 'M' + 24,25,26,27,28,29,30,31,32,33,34,35,36, // Letters 'N' through 'Z' + -9,-9,-9,-9, // Decimal 91 - 94 + 37, // Underscore at decimal 95 + -9, // Decimal 96 + 38,39,40,41,42,43,44,45,46,47,48,49,50, // Letters 'a' through 'm' + 51,52,53,54,55,56,57,58,59,60,61,62,63, // Letters 'n' through 'z' + -9,-9,-9,-9 // Decimal 123 - 126 + /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */ + }; + + +/* ******** D E T E R M I N E W H I C H A L H A B E T ******** */ + + + /** + * Returns one of the _SOMETHING_ALPHABET byte arrays depending on + * the options specified. + * It's possible, though silly, to specify ORDERED and URLSAFE + * in which case one of them will be picked, though there is + * no guarantee as to which one will be picked. + * @param options Specify the type of alphabet desired. + * @return The requested alphabet. + */ + private static byte[] getAlphabet( int options ) + { + if( (options & URL_SAFE) == URL_SAFE ) return _URL_SAFE_ALPHABET; + else if( (options & ORDERED) == ORDERED ) return _ORDERED_ALPHABET; + else return _STANDARD_ALPHABET; + + } + + /** + * Returns one of the _SOMETHING_DECODABET byte arrays depending on + * the options specified. + * It's possible, though silly, to specify ORDERED and URL_SAFE + * in which case one of them will be picked, though there is + * no guarantee as to which one will be picked. + * @param options Specify the type of alphabet desired. + * @return The requested alphabet. + */ + private static byte[] getDecodabet( int options ) + { + if( (options & URL_SAFE) == URL_SAFE ) return _URL_SAFE_DECODABET; + else if( (options & ORDERED) == ORDERED ) return _ORDERED_DECODABET; + else return _STANDARD_DECODABET; + + } + + /** Defeats instantiation. */ + private Base64(){} + +/* ******** E N C O D I N G M E T H O D S ******** */ + + /** + * Encodes up to the first three bytes of array threeBytes + * and returns a four-byte array in Base64 notation. + * The actual number of significant bytes in your array is + * given by numSigBytes. + * The array threeBytes needs only be as big as + * numSigBytes. + * Code can reuse a byte array by passing a four-byte array as b4. + * + * @param b4 A reusable byte array to reduce array instantiation + * @param threeBytes the array to convert + * @param numSigBytes the number of significant bytes in your array + * @param options the alphabet options to use. + * @return four byte array in Base64 notation. + * @since 1.5.1 + */ + private static byte[] encode3to4( byte[] b4, byte[] threeBytes, int numSigBytes, int options ) + { + encode3to4( threeBytes, 0, numSigBytes, b4, 0, options ); + return b4; + } + + /** + *

Encodes up to three bytes of the array source + * and writes the resulting four Base64 bytes to destination. + * The source and destination arrays can be manipulated + * anywhere along their length by specifying + * srcOffset and destOffset. + * This method does not check to make sure your arrays + * are large enough to accomodate srcOffset + 3 for + * the source array or destOffset + 4 for + * the destination array. + * The actual number of significant bytes in your array is + * given by numSigBytes.

+ *

This is the lowest level of the encoding methods with + * all possible parameters.

+ * + * @param source the array to convert + * @param srcOffset the index where conversion begins + * @param numSigBytes the number of significant bytes in your array + * @param destination the array to hold the conversion + * @param destOffset the index where output will be put + * @param options the alphabet options to use + * @return the destination array + * @since 1.3 + */ + private static byte[] encode3to4( + byte[] source, int srcOffset, int numSigBytes, + byte[] destination, int destOffset, int options ) + { + byte[] ALPHABET = getAlphabet( options ); + + // 1 2 3 + // 01234567890123456789012345678901 Bit position + // --------000000001111111122222222 Array position from threeBytes + // --------| || || || | Six bit groups to index ALPHABET + // >>18 >>12 >> 6 >> 0 Right shift necessary + // 0x3f 0x3f 0x3f Additional AND + + // Create buffer with zero-padding if there are only one or two + // significant bytes passed in the array. + // We have to shift left 24 in order to flush out the 1's that appear + // when Java treats a value as negative that is cast from a byte to an int. + int inBuff = ( numSigBytes > 0 ? ((source[ srcOffset ] << 24) >>> 8) : 0 ) + | ( numSigBytes > 1 ? ((source[ srcOffset + 1 ] << 24) >>> 16) : 0 ) + | ( numSigBytes > 2 ? ((source[ srcOffset + 2 ] << 24) >>> 24) : 0 ); + + switch( numSigBytes ) + { + case 3: + destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ]; + destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ]; + destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>> 6) & 0x3f ]; + destination[ destOffset + 3 ] = ALPHABET[ (inBuff ) & 0x3f ]; + return destination; + + case 2: + destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ]; + destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ]; + destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>> 6) & 0x3f ]; + destination[ destOffset + 3 ] = EQUALS_SIGN; + return destination; + + case 1: + destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ]; + destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ]; + destination[ destOffset + 2 ] = EQUALS_SIGN; + destination[ destOffset + 3 ] = EQUALS_SIGN; + return destination; + + default: + return destination; + } // end switch + } + + /** + * Serializes an object and returns the Base64-encoded + * version of that serialized object. If the object + * cannot be serialized or there is another error, + * the method will return null. + * The object is not GZip-compressed before being encoded. + * + * @param serializableObject The object to encode + * @return The Base64-encoded object + * @since 1.4 + */ + public static String encodeObject( java.io.Serializable serializableObject ) + { + return encodeObject( serializableObject, NO_OPTIONS ); + } // end encodeObject + + + + /** + * Serializes an object and returns the Base64-encoded + * version of that serialized object. If the object + * cannot be serialized or there is another error, + * the method will return null. + *

+ * Valid options:

+     *   GZIP: gzip-compresses object before encoding it.
+     *   DONT_BREAK_LINES: don't break lines at 76 characters
+     *     Note: Technically, this makes your encoding non-compliant.
+     * 
+ *

+ * Example: encodeObject( myObj, Base64.GZIP ) or + *

+ * Example: encodeObject( myObj, Base64.GZIP | Base64.DONT_BREAK_LINES ) + * + * @param serializableObject The object to encode + * @param options Specified options + * @return The Base64-encoded object + * @see Base64#GZIP + * @see Base64#DONT_BREAK_LINES + * @since 2.0 + */ + public static String encodeObject( java.io.Serializable serializableObject, int options ) + { + // Streams + java.io.ByteArrayOutputStream baos = null; + java.io.OutputStream b64os = null; + java.io.ObjectOutputStream oos = null; + java.util.zip.GZIPOutputStream gzos = null; + + // Isolate options + int gzip = (options & GZIP); + + try + { + // ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream + baos = new java.io.ByteArrayOutputStream(); + b64os = new Base64.OutputStream( baos, ENCODE | options ); + + // GZip? + if( gzip == GZIP ) + { + gzos = new java.util.zip.GZIPOutputStream( b64os ); + oos = new java.io.ObjectOutputStream( gzos ); + } // end if: gzip + else + oos = new java.io.ObjectOutputStream( b64os ); + + oos.writeObject( serializableObject ); + } // end try + catch( java.io.IOException e ) + { + e.printStackTrace(); + return null; + } // end catch + finally + { + try{ oos.close(); } catch( Exception e ){ /* empty */ } + try{ gzos.close(); } catch( Exception e ){ /* empty */ } + try{ b64os.close(); } catch( Exception e ){ /* empty */ } + try{ baos.close(); } catch( Exception e ){ /* empty */ } + } // end finally + + // Return value according to relevant encoding. + try + { + return new String( baos.toByteArray(), PREFERRED_ENCODING ); + } // end try + catch (java.io.UnsupportedEncodingException uue) + { + return new String( baos.toByteArray() ); + } // end catch + + } // end encode + + + + /** + * Encodes a byte array into Base64 notation. + * Does not GZip-compress data. + * + * @param source The data to convert + * @return the string of encoded bytes. + * @since 1.4 + */ + public static String encodeBytes( byte[] source ) + { + return encodeBytes( source, 0, source.length, NO_OPTIONS ); + } // end encodeBytes + + + + /** + * Encodes a byte array into Base64 notation. + *

+ * Valid options:

+     *   GZIP: gzip-compresses object before encoding it.
+     *   DONT_BREAK_LINES: don't break lines at 76 characters
+     *     Note: Technically, this makes your encoding non-compliant.
+     * 
+ *

+ * Example: encodeBytes( myData, Base64.GZIP ) or + *

+ * Example: encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES ) + * + * + * @param source The data to convert + * @param options Specified options + * @return the string of encoded bytes + * @see Base64#GZIP + * @see Base64#DONT_BREAK_LINES + * @since 2.0 + */ + public static String encodeBytes( byte[] source, int options ) + { + return encodeBytes( source, 0, source.length, options ); + } // end encodeBytes + + + /** + * Encodes a byte array into Base64 notation. + * Does not GZip-compress data. + * + * @param source The data to convert + * @param off Offset in array where conversion should begin + * @param len Length of data to convert + * @return the string of encoded bytes + * @since 1.4 + */ + public static String encodeBytes( byte[] source, int off, int len ) + { + return encodeBytes( source, off, len, NO_OPTIONS ); + } // end encodeBytes + + + + /** + * Encodes a byte array into Base64 notation. + *

+ * Valid options:

+     *   GZIP: gzip-compresses object before encoding it.
+     *   DONT_BREAK_LINES: don't break lines at 76 characters
+     *     Note: Technically, this makes your encoding non-compliant.
+     * 
+ *

+ * Example: encodeBytes( myData, Base64.GZIP ) or + *

+ * Example: encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES ) + * + * + * @param source The data to convert + * @param off Offset in array where conversion should begin + * @param len Length of data to convert + * @param options alphabet type is pulled from this (standard, url-safe, ordered) + * @return the string of encoded bytes + * @see Base64#GZIP + * @see Base64#DONT_BREAK_LINES + * @since 2.0 + */ + public static String encodeBytes( byte[] source, int off, int len, int options ) + { + // Isolate options + int dontBreakLines = ( options & DONT_BREAK_LINES ); + int gzip = ( options & GZIP ); + + // Compress? + if( gzip == GZIP ) + { + java.io.ByteArrayOutputStream baos = null; + java.util.zip.GZIPOutputStream gzos = null; + Base64.OutputStream b64os = null; + + + try + { + // GZip -> Base64 -> ByteArray + baos = new java.io.ByteArrayOutputStream(); + b64os = new Base64.OutputStream( baos, ENCODE | options ); + gzos = new java.util.zip.GZIPOutputStream( b64os ); + + gzos.write( source, off, len ); + gzos.close(); + } // end try + catch( java.io.IOException e ) + { + e.printStackTrace(); + return null; + } // end catch + finally + { + try{ gzos.close(); } catch( Exception e ){ /* empty */ } + try{ b64os.close(); } catch( Exception e ){ /* empty */ } + try{ baos.close(); } catch( Exception e ){ /* empty */ } + } // end finally + + // Return value according to relevant encoding. + try + { + return new String( baos.toByteArray(), PREFERRED_ENCODING ); + } // end try + catch (java.io.UnsupportedEncodingException uue) + { + return new String( baos.toByteArray() ); + } // end catch + } // end if: compress + + // Else, don't compress. Better not to use streams at all then. + else + { + // Convert option to boolean in way that code likes it. + boolean breakLines = dontBreakLines == 0; + + int len43 = len * 4 / 3; + byte[] outBuff = new byte[ ( len43 ) // Main 4:3 + + ( (len % 3) > 0 ? 4 : 0 ) // Account for padding + + (breakLines ? ( len43 / MAX_LINE_LENGTH ) : 0) ]; // New lines + int d = 0; + int e = 0; + int len2 = len - 2; + int lineLength = 0; + for( ; d < len2; d+=3, e+=4 ) + { + encode3to4( source, d+off, 3, outBuff, e, options ); + + lineLength += 4; + if( breakLines && lineLength == MAX_LINE_LENGTH ) + { + outBuff[e+4] = NEW_LINE; + e++; + lineLength = 0; + } // end if: end of line + } // en dfor: each piece of array + + if( d < len ) + { + encode3to4( source, d+off, len - d, outBuff, e, options ); + e += 4; + } // end if: some padding needed + + + // Return value according to relevant encoding. + try + { + return new String( outBuff, 0, e, PREFERRED_ENCODING ); + } // end try + catch (java.io.UnsupportedEncodingException uue) + { + return new String( outBuff, 0, e ); + } // end catch + + } // end else: don't compress + + } // end encodeBytes + + + + + +/* ******** D E C O D I N G M E T H O D S ******** */ + + + /** + * Decodes four bytes from array source + * and writes the resulting bytes (up to three of them) + * to destination. + * The source and destination arrays can be manipulated + * anywhere along their length by specifying + * srcOffset and destOffset. + * This method does not check to make sure your arrays + * are large enough to accomodate srcOffset + 4 for + * the source array or destOffset + 3 for + * the destination array. + * This method returns the actual number of bytes that + * were converted from the Base64 encoding. + *

This is the lowest level of the decoding methods with + * all possible parameters.

+ * + * + * @param source the array to convert + * @param srcOffset the index where conversion begins + * @param destination the array to hold the conversion + * @param destOffset the index where output will be put + * @param options alphabet type is pulled from this (standard, url-safe, ordered) + * @return the number of decoded bytes converted + * @since 1.3 + */ + private static int decode4to3( byte[] source, int srcOffset, byte[] destination, int destOffset, int options ) + { + byte[] DECODABET = getDecodabet( options ); + + // Example: Dk== + if( source[ srcOffset + 2] == EQUALS_SIGN ) + { + // Two ways to do the same thing. Don't know which way I like best. + //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 ) + // | ( ( DECODABET[ source[ srcOffset + 1] ] << 24 ) >>> 12 ); + int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 ) + | ( ( DECODABET[ source[ srcOffset + 1] ] & 0xFF ) << 12 ); + + destination[ destOffset ] = (byte)( outBuff >>> 16 ); + return 1; + } + + // Example: DkL= + else if( source[ srcOffset + 3 ] == EQUALS_SIGN ) + { + // Two ways to do the same thing. Don't know which way I like best. + //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 ) + // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 ) + // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 ); + int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 ) + | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF ) << 12 ) + | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF ) << 6 ); + + destination[ destOffset ] = (byte)( outBuff >>> 16 ); + destination[ destOffset + 1 ] = (byte)( outBuff >>> 8 ); + return 2; + } + + // Example: DkLE + else + { + try{ + // Two ways to do the same thing. Don't know which way I like best. + //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 ) + // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 ) + // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 ) + // | ( ( DECODABET[ source[ srcOffset + 3 ] ] << 24 ) >>> 24 ); + int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 ) + | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF ) << 12 ) + | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF ) << 6) + | ( ( DECODABET[ source[ srcOffset + 3 ] ] & 0xFF ) ); + + + destination[ destOffset ] = (byte)( outBuff >> 16 ); + destination[ destOffset + 1 ] = (byte)( outBuff >> 8 ); + destination[ destOffset + 2 ] = (byte)( outBuff ); + + return 3; + }catch( Exception e){ + System.out.println(""+source[srcOffset]+ ": " + ( DECODABET[ source[ srcOffset ] ] ) ); + System.out.println(""+source[srcOffset+1]+ ": " + ( DECODABET[ source[ srcOffset + 1 ] ] ) ); + System.out.println(""+source[srcOffset+2]+ ": " + ( DECODABET[ source[ srcOffset + 2 ] ] ) ); + System.out.println(""+source[srcOffset+3]+ ": " + ( DECODABET[ source[ srcOffset + 3 ] ] ) ); + return -1; + } // end catch + } + } // end decodeToBytes + + + + + /** + * Very low-level access to decoding ASCII characters in + * the form of a byte array. Does not support automatically + * gunzipping or any other "fancy" features. + * + * @param source The Base64 encoded data + * @param off The offset of where to begin decoding + * @param len The length of characters to decode + * @param options alphabet type is pulled from this (standard, url-safe, ordered) + * @return decoded data + * @since 1.3 + */ + public static byte[] decode( byte[] source, int off, int len, int options ) + { + byte[] DECODABET = getDecodabet( options ); + + int len34 = len * 3 / 4; + byte[] outBuff = new byte[ len34 ]; // Upper limit on size of output + int outBuffPosn = 0; + + byte[] b4 = new byte[4]; + int b4Posn = 0; + int i; + byte sbiCrop; + byte sbiDecode; + for( i = off; i < off+len; i++ ) + { + sbiCrop = (byte)(source[i] & 0x7f); // Only the low seven bits + sbiDecode = DECODABET[ sbiCrop ]; + + if( sbiDecode >= WHITE_SPACE_ENC ) // White space, Equals sign or better + { + if( sbiDecode >= EQUALS_SIGN_ENC ) + { + b4[ b4Posn++ ] = sbiCrop; + if( b4Posn > 3 ) + { + outBuffPosn += decode4to3( b4, 0, outBuff, outBuffPosn, options ); + b4Posn = 0; + + // If that was the equals sign, break out of 'for' loop + if( sbiCrop == EQUALS_SIGN ) + break; + } // end if: quartet built + + } // end if: equals sign or better + + } // end if: white space, equals sign or better + else + { + System.err.println( "Bad Base64 input character at " + i + ": " + source[i] + "(decimal)" ); + return null; + } // end else: + } // each input character + + byte[] out = new byte[ outBuffPosn ]; + System.arraycopy( outBuff, 0, out, 0, outBuffPosn ); + return out; + } // end decode + + + + + /** + * Decodes data from Base64 notation, automatically + * detecting gzip-compressed data and decompressing it. + * + * @param s the string to decode + * @return the decoded data + * @since 1.4 + */ + public static byte[] decode( String s ) + { + return decode( s, NO_OPTIONS ); + } + + + /** + * Decodes data from Base64 notation, automatically + * detecting gzip-compressed data and decompressing it. + * + * @param s the string to decode + * @param options encode options such as URL_SAFE + * @return the decoded data + * @since 1.4 + */ + public static byte[] decode( String s, int options ) + { + byte[] bytes; + try + { + bytes = s.getBytes( PREFERRED_ENCODING ); + } // end try + catch( java.io.UnsupportedEncodingException uee ) + { + bytes = s.getBytes(); + } // end catch + // + + // Decode + bytes = decode( bytes, 0, bytes.length, options ); + + + // Check to see if it's gzip-compressed + // GZIP Magic Two-Byte Number: 0x8b1f (35615) + if( bytes != null && bytes.length >= 4 ) + { + + int head = ((int)bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00); + if( java.util.zip.GZIPInputStream.GZIP_MAGIC == head ) + { + java.io.ByteArrayInputStream bais = null; + java.util.zip.GZIPInputStream gzis = null; + java.io.ByteArrayOutputStream baos = null; + byte[] buffer = new byte[2048]; + int length; + + try + { + baos = new java.io.ByteArrayOutputStream(); + bais = new java.io.ByteArrayInputStream( bytes ); + gzis = new java.util.zip.GZIPInputStream( bais ); + + while( ( length = gzis.read( buffer ) ) >= 0 ) + { + baos.write(buffer,0,length); + } // end while: reading input + + // No error? Get new bytes. + bytes = baos.toByteArray(); + + } // end try + catch( java.io.IOException e ) + { + // Just return originally-decoded bytes + } // end catch + finally + { + try{ baos.close(); } catch( Exception e ){ /* empty */ } + try{ gzis.close(); } catch( Exception e ){ /* empty */ } + try{ bais.close(); } catch( Exception e ){ /* empty */ } + } // end finally + + } // end if: gzipped + } // end if: bytes.length >= 2 + + return bytes; + } // end decode + + + + + /** + * Attempts to decode Base64 data and deserialize a Java + * Object within. Returns null if there was an error. + * + * @param encodedObject The Base64 data to decode + * @return The decoded and deserialized object + * @since 1.5 + */ + public static Object decodeToObject( String encodedObject ) + { + // Decode and gunzip if necessary + byte[] objBytes = decode( encodedObject ); + + java.io.ByteArrayInputStream bais = null; + java.io.ObjectInputStream ois = null; + Object obj = null; + + try + { + bais = new java.io.ByteArrayInputStream( objBytes ); + ois = new java.io.ObjectInputStream( bais ); + + obj = ois.readObject(); + } // end try + catch( java.io.IOException e ) + { + e.printStackTrace(); + obj = null; + } // end catch + catch( java.lang.ClassNotFoundException e ) + { + e.printStackTrace(); + obj = null; + } // end catch + finally + { + if (bais!=null) + try{ bais.close(); } catch( Exception e ){ /* empty */ } + if (ois!=null) + try{ ois.close(); } catch( Exception e ){ /* empty */ } + } // end finally + + return obj; + } // end decodeObject + + + + /** + * Convenience method for encoding data to a file. + * + * @param dataToEncode byte array of data to encode in base64 form + * @param filename Filename for saving encoded data + * @return true if successful, false otherwise + * + * @since 2.1 + */ + public static boolean encodeToFile( byte[] dataToEncode, String filename ) + { + boolean success = false; + Base64.OutputStream bos = null; + try + { + bos = new Base64.OutputStream( + new java.io.FileOutputStream( filename ), Base64.ENCODE ); + bos.write( dataToEncode ); + success = true; + } // end try + catch( java.io.IOException e ) + { + + success = false; + } // end catch: IOException + finally + { + if (bos!=null) + try{ bos.close(); } catch( Exception e ){ /* empty */ } + } // end finally + + return success; + } // end encodeToFile + + + /** + * Convenience method for decoding data to a file. + * + * @param dataToDecode Base64-encoded data as a string + * @param filename Filename for saving decoded data + * @return true if successful, false otherwise + * + * @since 2.1 + */ + public static boolean decodeToFile( String dataToDecode, String filename ) + { + boolean success = false; + Base64.OutputStream bos = null; + try + { + bos = new Base64.OutputStream( + new java.io.FileOutputStream( filename ), Base64.DECODE ); + bos.write( dataToDecode.getBytes( PREFERRED_ENCODING ) ); + success = true; + } // end try + catch( java.io.IOException e ) + { + success = false; + } // end catch: IOException + finally + { + if (bos!=null) + try{ bos.close(); } catch( Exception e ){ /* empty */ } + } // end finally + + return success; + } // end decodeToFile + + + + + /** + * Convenience method for reading a base64-encoded + * file and decoding it. + * + * @param filename Filename for reading encoded data + * @return decoded byte array or null if unsuccessful + * + * @since 2.1 + */ + public static byte[] decodeFromFile( String filename ) + { + byte[] decodedData = null; + Base64.InputStream bis = null; + try + { + // Set up some useful variables + java.io.File file = new java.io.File( filename ); + byte[] buffer; + int length = 0; + int numBytes; + + // Check for size of file + if( file.length() > Integer.MAX_VALUE ) + { + System.err.println( "File is too big for this convenience method (" + file.length() + " bytes)." ); + return null; + } // end if: file too big for int index + buffer = new byte[ (int)file.length() ]; + + // Open a stream + bis = new Base64.InputStream( + new java.io.BufferedInputStream( + new java.io.FileInputStream( file ) ), Base64.DECODE ); + + // Read until done + while( ( numBytes = bis.read( buffer, length, 4096 ) ) >= 0 ) + length += numBytes; + + // Save in a variable to return + decodedData = new byte[ length ]; + System.arraycopy( buffer, 0, decodedData, 0, length ); + + } // end try + catch( java.io.IOException e ) + { + System.err.println( "Error decoding from file " + filename ); + } // end catch: IOException + finally + { + if (bis!=null) + try{ bis.close(); } catch( Exception e) { /* empty */ } + } // end finally + + return decodedData; + } // end decodeFromFile + + + + /** + * Convenience method for reading a binary file + * and base64-encoding it. + * + * @param filename Filename for reading binary data + * @return base64-encoded string or null if unsuccessful + * + * @since 2.1 + */ + public static String encodeFromFile( String filename ) + { + String encodedData = null; + Base64.InputStream bis = null; + try + { + // Set up some useful variables + java.io.File file = new java.io.File( filename ); + byte[] buffer = new byte[ Math.max((int)(file.length() * 1.4),40) ]; // Need max() for math on small files (v2.2.1) + int length = 0; + int numBytes; + + // Open a stream + bis = new Base64.InputStream( + new java.io.BufferedInputStream( + new java.io.FileInputStream( file ) ), Base64.ENCODE ); + + // Read until done + while( ( numBytes = bis.read( buffer, length, 4096 ) ) >= 0 ) + length += numBytes; + + // Save in a variable to return + encodedData = new String( buffer, 0, length, Base64.PREFERRED_ENCODING ); + + } // end try + catch( java.io.IOException e ) + { + System.err.println( "Error encoding from file " + filename ); + } // end catch: IOException + finally + { + if (bis!=null) + try{ bis.close(); } catch( Exception e) { /* empty */ } + } // end finally + + return encodedData; + } // end encodeFromFile + + /** + * Reads infile and encodes it to outfile. + * + * @param infile Input file + * @param outfile Output file + * @since 2.2 + */ + public static void encodeFileToFile( String infile, String outfile ) + { + String encoded = Base64.encodeFromFile( infile ); + java.io.OutputStream out = null; + try{ + out = new java.io.BufferedOutputStream( + new java.io.FileOutputStream( outfile ) ); + out.write( encoded.getBytes("US-ASCII") ); // Strict, 7-bit output. + } // end try + catch( java.io.IOException ex ) { + ex.printStackTrace(); + } // end catch + finally { + if (out!=null) + try { out.close(); } + catch( Exception ex ){ /* empty */ } + } // end finally + } // end encodeFileToFile + + + /** + * Reads infile and decodes it to outfile. + * + * @param infile Input file + * @param outfile Output file + * @since 2.2 + */ + public static void decodeFileToFile( String infile, String outfile ) + { + byte[] decoded = Base64.decodeFromFile( infile ); + java.io.OutputStream out = null; + try{ + out = new java.io.BufferedOutputStream( + new java.io.FileOutputStream( outfile ) ); + out.write( decoded ); + } // end try + catch( java.io.IOException ex ) { + ex.printStackTrace(); + } // end catch + finally { + if (out!=null) + try { out.close(); } + catch( Exception ex ){ /* empty */ } + } // end finally + } // end decodeFileToFile + + + /* ******** I N N E R C L A S S I N P U T S T R E A M ******** */ + + + + /** + * A {@link Base64.InputStream} will read data from another + * java.io.InputStream, given in the constructor, + * and encode/decode to/from Base64 notation on the fly. + * + * @see Base64 + * @since 1.3 + */ + public static class InputStream extends java.io.FilterInputStream + { + private boolean encode; // Encoding or decoding + private int position; // Current position in the buffer + private byte[] buffer; // Small buffer holding converted data + private int bufferLength; // Length of buffer (3 or 4) + private int numSigBytes; // Number of meaningful bytes in the buffer + private int lineLength; + private boolean breakLines; // Break lines at less than 80 characters + private int options; // Record options used to create the stream. + @SuppressWarnings("unused") + private byte[] alphabet; // Local copies to avoid extra method calls + private byte[] decodabet; // Local copies to avoid extra method calls + + + /** + * Constructs a {@link Base64.InputStream} in DECODE mode. + * + * @param in the java.io.InputStream from which to read data. + * @since 1.3 + */ + public InputStream( java.io.InputStream in ) + { + this( in, DECODE ); + } // end constructor + + + /** + * Constructs a {@link Base64.InputStream} in + * either ENCODE or DECODE mode. + *

+ * Valid options:

+         *   ENCODE or DECODE: Encode or Decode as data is read.
+         *   DONT_BREAK_LINES: don't break lines at 76 characters
+         *     (only meaningful when encoding)
+         *     Note: Technically, this makes your encoding non-compliant.
+         * 
+ *

+ * Example: new Base64.InputStream( in, Base64.DECODE ) + * + * + * @param in the java.io.InputStream from which to read data. + * @param options Specified options + * @see Base64#ENCODE + * @see Base64#DECODE + * @see Base64#DONT_BREAK_LINES + * @since 2.0 + */ + public InputStream( java.io.InputStream in, int options ) + { + super( in ); + this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES; + this.encode = (options & ENCODE) == ENCODE; + this.bufferLength = encode ? 4 : 3; + this.buffer = new byte[ bufferLength ]; + this.position = -1; + this.lineLength = 0; + this.options = options; // Record for later, mostly to determine which alphabet to use + this.alphabet = getAlphabet(options); + this.decodabet = getDecodabet(options); + } // end constructor + + /** + * Reads enough of the input stream to convert + * to/from Base64 and returns the next byte. + * + * @return next byte + * @since 1.3 + */ + public int read() throws java.io.IOException + { + // Do we need to get data? + if( position < 0 ) + { + if( encode ) + { + byte[] b3 = new byte[3]; + int numBinaryBytes = 0; + for( int i = 0; i < 3; i++ ) + { + try + { + int b = in.read(); + + // If end of stream, b is -1. + if( b >= 0 ) + { + b3[i] = (byte)b; + numBinaryBytes++; + } // end if: not end of stream + + } // end try: read + catch( java.io.IOException e ) + { + // Only a problem if we got no data at all. + if( i == 0 ) + throw e; + + } // end catch + } // end for: each needed input byte + + if( numBinaryBytes > 0 ) + { + encode3to4( b3, 0, numBinaryBytes, buffer, 0, options ); + position = 0; + numSigBytes = 4; + } // end if: got data + else + { + return -1; + } // end else + } // end if: encoding + + // Else decoding + else + { + byte[] b4 = new byte[4]; + int i; + for( i = 0; i < 4; i++ ) + { + // Read four "meaningful" bytes: + int b; + do{ b = in.read(); } + while( b >= 0 && decodabet[ b & 0x7f ] <= WHITE_SPACE_ENC ); + + if( b < 0 ) + break; // Reads a -1 if end of stream + + b4[i] = (byte)b; + } // end for: each needed input byte + + if( i == 4 ) + { + numSigBytes = decode4to3( b4, 0, buffer, 0, options ); + position = 0; + } // end if: got four characters + else if( i == 0 ){ + return -1; + } // end else if: also padded correctly + else + { + // Must have broken out from above. + throw new java.io.IOException( "Improperly padded Base64 input." ); + } // end + + } // end else: decode + } // end else: get data + + // Got data? + if( position >= 0 ) + { + // End of relevant data? + if( /*!encode &&*/ position >= numSigBytes ) + return -1; + + if( encode && breakLines && lineLength >= MAX_LINE_LENGTH ) + { + lineLength = 0; + return '\n'; + } // end if + else + { + lineLength++; // This isn't important when decoding + // but throwing an extra "if" seems + // just as wasteful. + + int b = buffer[ position++ ]; + + if( position >= bufferLength ) + position = -1; + + return b & 0xFF; // This is how you "cast" a byte that's + // intended to be unsigned. + } // end else + } // end if: position >= 0 + + // Else error + else + { + // When JDK1.4 is more accepted, use an assertion here. + throw new java.io.IOException( "Error in Base64 code reading stream." ); + } // end else + } // end read + + + /** + * Calls {@link #read()} repeatedly until the end of stream + * is reached or len bytes are read. + * Returns number of bytes read into array or -1 if + * end of stream is encountered. + * + * @param dest array to hold values + * @param off offset for array + * @param len max number of bytes to read into array + * @return bytes read into array or -1 if end of stream is encountered. + * @since 1.3 + */ + public int read( byte[] dest, int off, int len ) throws java.io.IOException + { + int i; + int b; + for( i = 0; i < len; i++ ) + { + b = read(); + + //if( b < 0 && i == 0 ) + // return -1; + + if( b >= 0 ) + dest[off + i] = (byte)b; + else if( i == 0 ) + return -1; + else + break; // Out of 'for' loop + } // end for: each byte read + return i; + } // end read + + } // end inner class InputStream + + + + + + + /* ******** I N N E R C L A S S O U T P U T S T R E A M ******** */ + + + + /** + * A {@link Base64.OutputStream} will write data to another + * java.io.OutputStream, given in the constructor, + * and encode/decode to/from Base64 notation on the fly. + * + * @see Base64 + * @since 1.3 + */ + public static class OutputStream extends java.io.FilterOutputStream + { + private boolean encode; + private int position; + private byte[] buffer; + private int bufferLength; + private int lineLength; + private boolean breakLines; + private byte[] b4; // Scratch used in a few places + private boolean suspendEncoding; + private int options; // Record for later + @SuppressWarnings("unused") + private byte[] alphabet; // Local copies to avoid extra method calls + private byte[] decodabet; // Local copies to avoid extra method calls + + /** + * Constructs a {@link Base64.OutputStream} in ENCODE mode. + * + * @param out the java.io.OutputStream to which data will be written. + * @since 1.3 + */ + public OutputStream( java.io.OutputStream out ) + { + this( out, ENCODE ); + } // end constructor + + + /** + * Constructs a {@link Base64.OutputStream} in + * either ENCODE or DECODE mode. + *

+ * Valid options:

+         *   ENCODE or DECODE: Encode or Decode as data is read.
+         *   DONT_BREAK_LINES: don't break lines at 76 characters
+         *     (only meaningful when encoding)
+         *     Note: Technically, this makes your encoding non-compliant.
+         * 
+ *

+ * Example: new Base64.OutputStream( out, Base64.ENCODE ) + * + * @param out the java.io.OutputStream to which data will be written. + * @param options Specified options. + * @see Base64#ENCODE + * @see Base64#DECODE + * @see Base64#DONT_BREAK_LINES + * @since 1.3 + */ + public OutputStream( java.io.OutputStream out, int options ) + { + super( out ); + this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES; + this.encode = (options & ENCODE) == ENCODE; + this.bufferLength = encode ? 3 : 4; + this.buffer = new byte[ bufferLength ]; + this.position = 0; + this.lineLength = 0; + this.suspendEncoding = false; + this.b4 = new byte[4]; + this.options = options; + this.alphabet = getAlphabet(options); + this.decodabet = getDecodabet(options); + } // end constructor + + + /** + * Writes the byte to the output stream after + * converting to/from Base64 notation. + * When encoding, bytes are buffered three + * at a time before the output stream actually + * gets a write() call. + * When decoding, bytes are buffered four + * at a time. + * + * @param theByte the byte to write + * @since 1.3 + */ + public void write(int theByte) throws java.io.IOException + { + // Encoding suspended? + if( suspendEncoding ) + { + super.out.write( theByte ); + return; + } // end if: supsended + + // Encode? + if( encode ) + { + buffer[ position++ ] = (byte)theByte; + if( position >= bufferLength ) // Enough to encode. + { + out.write( encode3to4( b4, buffer, bufferLength, options ) ); + + lineLength += 4; + if( breakLines && lineLength >= MAX_LINE_LENGTH ) + { + out.write( NEW_LINE ); + lineLength = 0; + } // end if: end of line + + position = 0; + } // end if: enough to output + } // end if: encoding + + // Else, Decoding + else + { + // Meaningful Base64 character? + if( decodabet[ theByte & 0x7f ] > WHITE_SPACE_ENC ) + { + buffer[ position++ ] = (byte)theByte; + if( position >= bufferLength ) // Enough to output. + { + int len = Base64.decode4to3( buffer, 0, b4, 0, options ); + out.write( b4, 0, len ); + //out.write( Base64.decode4to3( buffer ) ); + position = 0; + } // end if: enough to output + } // end if: meaningful base64 character + else if( decodabet[ theByte & 0x7f ] != WHITE_SPACE_ENC ) + { + throw new java.io.IOException( "Invalid character in Base64 data." ); + } // end else: not white space either + } // end else: decoding + } // end write + + + + /** + * Calls {@link #write(int)} repeatedly until len + * bytes are written. + * + * @param theBytes array from which to read bytes + * @param off offset for array + * @param len max number of bytes to read into array + * @since 1.3 + */ + public void write( byte[] theBytes, int off, int len ) throws java.io.IOException + { + // Encoding suspended? + if( suspendEncoding ) + { + super.out.write( theBytes, off, len ); + return; + } // end if: supsended + + for( int i = 0; i < len; i++ ) + { + write( theBytes[ off + i ] ); + } // end for: each byte written + + } // end write + + + + /** + * Method added by PHIL. [Thanks, PHIL. -Rob] + * This pads the buffer without closing the stream. + */ + public void flushBase64() throws java.io.IOException + { + if( position > 0 ) + { + if( encode ) + { + out.write( encode3to4( b4, buffer, position, options ) ); + position = 0; + } // end if: encoding + else + { + throw new java.io.IOException( "Base64 input not properly padded." ); + } // end else: decoding + } // end if: buffer partially full + + } // end flush + + + /** + * Flushes and closes (I think, in the superclass) the stream. + * + * @since 1.3 + */ + public void close() throws java.io.IOException + { + // 1. Ensure that pending characters are written + flushBase64(); + + // 2. Actually close the stream + // Base class both flushes and closes. + super.close(); + + buffer = null; + out = null; + } // end close + + + + /** + * Suspends encoding of the stream. + * May be helpful if you need to embed a piece of + * base640-encoded data in a stream. + * + * @since 1.5.1 + */ + public void suspendEncoding() throws java.io.IOException + { + flushBase64(); + this.suspendEncoding = true; + } // end suspendEncoding + + + /** + * Resumes encoding of the stream. + * May be helpful if you need to embed a piece of + * base640-encoded data in a stream. + * + * @since 1.5.1 + */ + public void resumeEncoding() + { + this.suspendEncoding = false; + } // end resumeEncoding + + + + } // end inner class OutputStream + + +} // end class Base64 diff --git a/test/src/com/cloud/sample/UserCloudAPIExecutor.java b/test/src/com/cloud/sample/UserCloudAPIExecutor.java new file mode 100644 index 00000000000..c282a20040e --- /dev/null +++ b/test/src/com/cloud/sample/UserCloudAPIExecutor.java @@ -0,0 +1,194 @@ +package com.cloud.sample; + +import java.io.FileInputStream; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Properties; +import java.util.StringTokenizer; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.methods.GetMethod; + +import com.cloud.utils.encoding.Base64; + +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +/** + * Sample CloudStack Management User API Executor. + * + * Prerequisites: - Edit usercloud.properties to include your host, apiUrl, apiKey, and secretKey - Use ./executeUserAPI.sh to + * execute this test class + * + * @author will + * + */ +public class UserCloudAPIExecutor { + public static void main(String[] args) { + // Host + String host = null; + + // Fully qualified URL with http(s)://host:port + String apiUrl = null; + + // ApiKey and secretKey as given by your CloudStack vendor + String apiKey = null; + String secretKey = null; + + try { + Properties prop = new Properties(); + prop.load(new FileInputStream("usercloud.properties")); + + // host + host = prop.getProperty("host"); + if (host == null) { + System.out.println("Please specify a valid host in the format of http(s)://:/client/api in your usercloud.properties file."); + } + + // apiUrl + apiUrl = prop.getProperty("apiUrl"); + if (apiUrl == null) { + System.out.println("Please specify a valid API URL in the format of command=¶m1=¶m2=... in your usercloud.properties file."); + } + + // apiKey + apiKey = prop.getProperty("apiKey"); + if (apiKey == null) { + System.out.println("Please specify your API Key as provided by your CloudStack vendor in your usercloud.properties file."); + } + + // secretKey + secretKey = prop.getProperty("secretKey"); + if (secretKey == null) { + System.out.println("Please specify your secret Key as provided by your CloudStack vendor in your usercloud.properties file."); + } + + if (apiUrl == null || apiKey == null || secretKey == null) { + return; + } + + System.out.println("Constructing API call to host = '" + host + "' with API command = '" + apiUrl + "' using apiKey = '" + apiKey + "' and secretKey = '" + secretKey + "'"); + + // Step 1: Make sure your APIKey is URL encoded + String encodedApiKey = URLEncoder.encode(apiKey, "UTF-8"); + + // Step 2: URL encode each parameter value, then sort the parameters and apiKey in + // alphabetical order, and then toLowerCase all the parameters, parameter values and apiKey. + // Please note that if any parameters with a '&' as a value will cause this test client to fail since we are using + // '&' to delimit + // the string + List sortedParams = new ArrayList(); + sortedParams.add("apikey=" + encodedApiKey.toLowerCase()); + StringTokenizer st = new StringTokenizer(apiUrl, "&"); + String url = null; + boolean first = true; + while (st.hasMoreTokens()) { + String paramValue = st.nextToken(); + String param = paramValue.substring(0, paramValue.indexOf("=")); + String value = URLEncoder.encode(paramValue.substring(paramValue.indexOf("=") + 1, paramValue.length()), "UTF-8"); + if (first) { + url = param + "=" + value; + first = false; + } else { + url = url + "&" + param + "=" + value; + } + sortedParams.add(param.toLowerCase() + "=" + value.toLowerCase()); + } + Collections.sort(sortedParams); + + System.out.println("Sorted Parameters: " + sortedParams); + + // Step 3: Construct the sorted URL and sign and URL encode the sorted URL with your secret key + String sortedUrl = null; + first = true; + for (String param : sortedParams) { + if (first) { + sortedUrl = param; + first = false; + } else { + sortedUrl = sortedUrl + "&" + param; + } + } + System.out.println("sorted URL : " + sortedUrl); + String encodedSignature = signRequest(sortedUrl, secretKey); + + // Step 4: Construct the final URL we want to send to the CloudStack Management Server + // Final result should look like: + // http(s)://://client/api?&apiKey=&signature= + String finalUrl = host + "?" + url + "&apiKey=" + apiKey + "&signature=" + encodedSignature; + System.out.println("final URL : " + finalUrl); + + // Step 5: Perform a HTTP GET on this URL to execute the command + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(finalUrl); + int responseCode = client.executeMethod(method); + if (responseCode == 200) { + // SUCCESS! + System.out.println("Successfully executed command"); + } else { + // FAILED! + System.out.println("Unable to execute command with response code: " + responseCode); + } + + } catch (Throwable t) { + System.out.println(t); + } + } + + /** + * 1. Signs a string with a secret key using SHA-1 2. Base64 encode the result 3. URL encode the final result + * + * @param request + * @param key + * @return + */ + public static String signRequest(String request, String key) { + try { + Mac mac = Mac.getInstance("HmacSHA1"); + SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacSHA1"); + mac.init(keySpec); + mac.update(request.getBytes()); + byte[] encryptedBytes = mac.doFinal(); + return URLEncoder.encode(Base64.encodeBytes(encryptedBytes), "UTF-8"); + } catch (Exception ex) { + System.out.println(ex); + } + return null; + } +} diff --git a/test/src/com/cloud/test/longrun/BuildGuestNetwork.java b/test/src/com/cloud/test/longrun/BuildGuestNetwork.java new file mode 100644 index 00000000000..2eb3360cde3 --- /dev/null +++ b/test/src/com/cloud/test/longrun/BuildGuestNetwork.java @@ -0,0 +1,131 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.longrun; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Random; + + +import org.apache.log4j.Logger; + + +public class BuildGuestNetwork { + + public static final Logger s_logger= Logger.getLogger(BuildGuestNetwork.class.getClass()); + private static final int _apiPort=8096; + private static final int _developerPort=8080; + private static final String _apiUrl = "/client/api"; + private static int numVM=1; + private static long zoneId=-1L; + private static long templateId=3; + private static long serviceOfferingId=1; + + + + public static void main (String[] args){ + + List argsList = Arrays.asList(args); + Iterator iter = argsList.iterator(); + String host = "http://localhost"; + int numThreads = 1; + + while (iter.hasNext()){ + String arg = iter.next(); + if (arg.equals("-h")){ + host="http://"+iter.next(); + } + if (arg.equals("-t")){ + numThreads=Integer.parseInt(iter.next()); + } + if (arg.equals("-n")){ + numVM=Integer.parseInt(iter.next()); + } + if (arg.equals("-z")){ + zoneId=Integer.parseInt(iter.next()); + } + + if (arg.equals("-e")){ + templateId=Integer.parseInt(iter.next()); + } + + if (arg.equals("-s")){ + serviceOfferingId=Integer.parseInt(iter.next()); + } + } + + final String server = host + ":" + _apiPort + "/"; + final String developerServer = host + ":" + _developerPort + _apiUrl; + s_logger.info("Starting test in "+numThreads+" thread(s). Each thread is launching "+numVM+" VMs"); + + for (int i=0; i. + * + */ + +package com.cloud.test.longrun; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URLEncoder; +import java.util.Arrays; +import java.util.List; +import java.util.Iterator; +import java.util.Map; +import java.util.Random; + + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.log4j.Logger; + +import com.cloud.test.stress.TestClientWithAPI; + + + +public class PerformanceWithAPI { + +public static final Logger s_logger= Logger.getLogger(PerformanceWithAPI.class.getClass()); +private static final int _retry=10; +private static final int _apiPort=8096; +private static int numVM=2; +private static final long _zoneId=-1L; +private static final long _templateId=3; +private static final long _serviceOfferingId=1; +private static final String _apiUrl = "/client/api"; +private static final int _developerPort=8080; + + + + public static void main (String[] args){ + + List argsList = Arrays.asList(args); + Iterator iter = argsList.iterator(); + String host = "http://localhost"; + int numThreads = 1; + + while (iter.hasNext()){ + String arg = iter.next(); + if (arg.equals("-h")){ + host="http://"+iter.next(); + } + if (arg.equals("-t")){ + numThreads=Integer.parseInt(iter.next()); + } + if (arg.equals("-n")){ + numVM=Integer.parseInt(iter.next()); + } + } + + final String server = host + ":" + _apiPort + "/"; + final String developerServer = host + ":" + _developerPort + _apiUrl; + + s_logger.info("Starting test in "+numThreads+" thread(s). Each thread is launching "+numVM+" VMs"); + + for (int i=0; i errorInfo = TestClientWithAPI.getSingleValueFromXML(is, + new String[] { "errorCode", "description" }); + s_logger + .error("create ip forwarding rule (linux) test failed with errorCode: " + + errorInfo.get("errorCode") + + " and description: " + + errorInfo.get("description")); + } else { + s_logger.error("internal error processing request: " + + method.getStatusText()); + } + return responseCode; + } + + +} \ No newline at end of file diff --git a/test/src/com/cloud/test/longrun/User.java b/test/src/com/cloud/test/longrun/User.java new file mode 100644 index 00000000000..d8fe46f47a2 --- /dev/null +++ b/test/src/com/cloud/test/longrun/User.java @@ -0,0 +1,241 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.longrun; +import java.util.ArrayList; +import java.util.Map; +import java.io.InputStream; +import java.io.IOException; +import java.net.URLEncoder; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.log4j.Logger; + +import com.cloud.test.stress.TestClientWithAPI; + + + +public class User { + public static final Logger s_logger= Logger.getLogger(User.class.getClass()); + + private ArrayList virtualMachines; + private ArrayList publicIp; + private String server; + private String developerServer; + private String userName; + private String userId; + private String apiKey; + private String secretKey; + private String password; + private String encryptedPassword; + + + public User(String userName, String password, String server, String developerServer) + { + this.server=server; + this.developerServer=developerServer; + this.userName=userName; + this.password=password; + this.virtualMachines = new ArrayList(); + this.publicIp = new ArrayList(); + } + + public ArrayList getVirtualMachines() { + return virtualMachines; + } + + + public void setVirtualMachines(ArrayList virtualMachines) { + this.virtualMachines = virtualMachines; + } + + + public String getUserId() { + return userId; + } + + + public void setUserId(String userId) { + this.userId = userId; + } + + + public ArrayList getPublicIp() { + return publicIp; + } + + + public void setPublicIp(ArrayList publicIp) { + this.publicIp = publicIp; + } + + + + public String getServer() { + return server; + } + + + + public void setServer(String server) { + this.server = server; + } + + + + public String getUserName() { + return userName; + } + + + + public void setUserName(String userName) { + this.userName = userName; + } + + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getSecretKey() { + return secretKey; + } + + public void setSecretKey(String secretKey) { + this.secretKey = secretKey; + } + + + + public String getDeveloperServer() { + return developerServer; + } + + public void setDeveloperServer(String developerServer) { + this.developerServer = developerServer; + } + + public void launchUser() throws IOException { + String encodedUsername = URLEncoder.encode(this.getUserName(), "UTF-8"); + this.encryptedPassword=TestClientWithAPI.createMD5Password(this.getPassword()); + String encodedPassword = URLEncoder.encode(this.encryptedPassword, "UTF-8"); + String url = this.server + "?command=createUser&username=" + encodedUsername + + "&password=" + encodedPassword + + "&firstname=Test&lastname=Test&email=alena@vmops.com&domainId=1"; + String userIdStr=null; + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + int responseCode = client.executeMethod(method); + + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map userIdValues = TestClientWithAPI.getSingleValueFromXML(is, + new String[] { "id" }); + userIdStr = userIdValues.get("id"); + if ((userIdStr != null) && (Long.parseLong(userIdStr)!=-1)) { + this.setUserId(userIdStr); + } + } + } + + public void retrievePublicIp(long zoneId) throws IOException{ + + String encodedApiKey = URLEncoder.encode(this.apiKey, "UTF-8"); + String encodedZoneId=URLEncoder.encode(""+zoneId,"UTF-8"); + String requestToSign = "apiKey=" + encodedApiKey + + "&command=associateIpAddress" + "&zoneId="+encodedZoneId; + requestToSign = requestToSign.toLowerCase(); + String signature = TestClientWithAPI.signRequest(requestToSign, this.secretKey); + String encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + String url = this.developerServer + "?command=associateIpAddress" + "&apiKey=" + + encodedApiKey + "&zoneId="+encodedZoneId+"&signature=" + + encodedSignature; + + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + int responseCode=client.executeMethod(method); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map values = TestClientWithAPI.getSingleValueFromXML(is, + new String[] { "ipaddress" }); + this.getPublicIp().add(values.get("ipaddress")); + s_logger.info("Ip address is " + values.get("ipaddress")); + } else if (responseCode == 500) { + InputStream is = method.getResponseBodyAsStream(); + Map errorInfo = TestClientWithAPI.getSingleValueFromXML(is, + new String[] { "errorcode", "description" }); + s_logger.error("associate ip test failed with errorCode: " + + errorInfo.get("errorCode") + " and description: " + + errorInfo.get("description")); + } else { + s_logger.error("internal error processing request: " + + method.getStatusText()); + } + + } + + public void registerUser()throws HttpException, IOException{ + + String encodedUsername = URLEncoder.encode(this.userName, "UTF-8"); + String encodedPassword = URLEncoder.encode(this.password, "UTF-8"); + String url = server + "?command=register&username=" + encodedUsername + + "&domainid=1"; + s_logger.info("registering: " + this.userName+" with url "+url); + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + int responseCode = client.executeMethod(method); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map requestKeyValues = TestClientWithAPI.getSingleValueFromXML(is, + new String[] { "apikey", "secretkey" }); + this.setApiKey(requestKeyValues.get("apikey")); + this.setSecretKey(requestKeyValues.get("secretkey")); + } else if (responseCode == 500) { + InputStream is = method.getResponseBodyAsStream(); + Map errorInfo = TestClientWithAPI.getSingleValueFromXML(is, + new String[] { "errorcode", "description" }); + s_logger.error("registration failed with errorCode: " + + errorInfo.get("errorCode") + " and description: " + + errorInfo.get("description")); + } else { + s_logger.error("internal error processing request: " + + method.getStatusText()); + } + } + +} + + diff --git a/test/src/com/cloud/test/longrun/VirtualMachine.java b/test/src/com/cloud/test/longrun/VirtualMachine.java new file mode 100644 index 00000000000..b5ba4d38bbf --- /dev/null +++ b/test/src/com/cloud/test/longrun/VirtualMachine.java @@ -0,0 +1,119 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.longrun; + +import java.io.InputStream; +import java.net.URLEncoder; +import java.util.Map; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.log4j.Logger; + +import com.cloud.test.stress.TestClientWithAPI; + + +import java.io.IOException; + + +public class VirtualMachine { + public static final Logger s_logger= Logger.getLogger(VirtualMachine.class.getClass()); + + private String privateIp; + private String userId; + + + public VirtualMachine(String userId){ + this.userId=userId; + } + + + public String getPrivateIp() { + return privateIp; + } + + + public void setPrivateIp(String privateIp) { + this.privateIp = privateIp; + } + + + public String getUserId() { + return userId; + } + + + public void setUserId(String userId) { + this.userId = userId; + } + + + public void deployVM(long zoneId, long serviceOfferingId, long templateId, String server, String apiKey, String secretKey) throws IOException{ + + String encodedZoneId = URLEncoder.encode("" + zoneId, "UTF-8"); + String encodedServiceOfferingId = URLEncoder.encode("" + + serviceOfferingId, "UTF-8"); + String encodedTemplateId = URLEncoder.encode("" + templateId, + "UTF-8"); + String encodedApiKey=URLEncoder.encode(apiKey, "UTF-8"); + String requestToSign = "apiKey=" + encodedApiKey + + "&command=deployVirtualMachine&serviceOfferingId=" + + encodedServiceOfferingId + "&templateId=" + + encodedTemplateId + "&zoneId=" + encodedZoneId; + + requestToSign = requestToSign.toLowerCase(); + String signature = TestClientWithAPI.signRequest(requestToSign, secretKey); + String encodedSignature = URLEncoder.encode(signature, "UTF-8"); + String url = server + "?command=deployVirtualMachine" + + "&zoneId=" + encodedZoneId + "&serviceOfferingId=" + + encodedServiceOfferingId + "&templateId=" + + encodedTemplateId + "&apiKey=" + encodedApiKey + + "&signature=" + encodedSignature; + + s_logger.info("Sending this request to deploy a VM: "+url); + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + int responseCode = client.executeMethod(method); + s_logger.info("deploy linux vm response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map values = TestClientWithAPI.getSingleValueFromXML(is, + new String[] { "id", "ipaddress" }); + long linuxVMId = Long.parseLong(values.get("id")); + s_logger.info("got linux virtual machine id: " + linuxVMId); + this.setPrivateIp(values.get("ipaddress")); + + } else if (responseCode == 500) { + InputStream is = method.getResponseBodyAsStream(); + Map errorInfo = TestClientWithAPI.getSingleValueFromXML(is, + new String[] { "errorcode", "description" }); + s_logger.error("deploy linux vm test failed with errorCode: " + + errorInfo.get("errorCode") + " and description: " + + errorInfo.get("description")); + } else { + s_logger.error("internal error processing request: " + + method.getStatusText()); + } + } + + + +} diff --git a/test/src/com/cloud/test/longrun/guestNetwork.java b/test/src/com/cloud/test/longrun/guestNetwork.java new file mode 100644 index 00000000000..46eef116fed --- /dev/null +++ b/test/src/com/cloud/test/longrun/guestNetwork.java @@ -0,0 +1,110 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.longrun; +import java.util.ArrayList; +import java.util.Random; +import org.apache.log4j.Logger; +import org.apache.log4j.NDC; +import com.trilead.ssh2.Connection; +import com.trilead.ssh2.Session; + + +public class guestNetwork implements Runnable{ + public static final Logger s_logger= Logger.getLogger(guestNetwork.class.getClass()); + + private String publicIp; + private ArrayList virtualMachines; + private int retryNum; + + public guestNetwork(String publicIp, int retryNum){ + this.publicIp=publicIp; + this.retryNum=retryNum; + } + + public ArrayList getVirtualMachines() { + return virtualMachines; + } + + public void setVirtualMachines(ArrayList virtualMachines) { + this.virtualMachines = virtualMachines; + } + + public void run(){ + NDC.push("Following thread has started"+Thread.currentThread().getName()); + int retry = 0; + + //Start copying files between machines in the network + s_logger.info("The size of the array is " + this.virtualMachines.size()); + while (true) { + try { + if (retry > 0) { + s_logger.info("Retry attempt : " + retry + + " ...sleeping 120 seconds before next attempt"); + Thread.sleep(120000); + } + for (VirtualMachine vm: this.virtualMachines ){ + + s_logger.info("Attempting to SSH into linux host " + this.publicIp + + " with retry attempt: " + retry); + Connection conn = new Connection(this.publicIp); + conn.connect(null, 600000, 600000); + + s_logger.info("SSHed successfully into linux host " + this.publicIp); + + boolean isAuthenticated = conn.authenticateWithPassword("root", + "password"); + + if (isAuthenticated == false) { + s_logger.info("Authentication failed"); + } + //execute copy command + Session sess = conn.openSession(); + String fileName; + Random ran = new Random(); + fileName=Math.abs(ran.nextInt())+"-file"; + String copyCommand = new String ("./scpScript "+vm.getPrivateIp()+" "+fileName); + s_logger.info("Executing " + copyCommand); + sess.execCommand(copyCommand); + Thread.sleep(120000); + sess.close(); + + //execute wget command + sess = conn.openSession(); + String downloadCommand = new String ("wget http://172.16.0.220/scripts/checkDiskSpace.sh; chmod +x *sh; ./checkDiskSpace.sh; rm -rf checkDiskSpace.sh"); + s_logger.info("Executing " + downloadCommand); + sess.execCommand(downloadCommand); + Thread.sleep(120000); + sess.close(); + + //close the connection + conn.close(); + } + }catch (Exception ex) { + s_logger.error(ex); + retry++; + if (retry == retryNum) { + s_logger.info("Performance Guest Network test failed with error " + + ex.getMessage()) ; + } + } + } + + } +} diff --git a/test/src/com/cloud/test/regression/ApiCommand.java b/test/src/com/cloud/test/regression/ApiCommand.java new file mode 100644 index 00000000000..9358b888af0 --- /dev/null +++ b/test/src/com/cloud/test/regression/ApiCommand.java @@ -0,0 +1,865 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.regression; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.net.URLEncoder; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Properties; +import java.util.Random; +import java.util.Set; +import java.util.TreeMap; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.log4j.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import com.cloud.test.utils.UtilsForTest; + +public class ApiCommand{ + public static final Logger s_logger = Logger.getLogger(ApiCommand.class.getName()); + public static enum CommandType{ + HTTP, MYSQL, SCRIPT; + } + + public static enum ResponseType{ + ERROR, EMPTY; + } + + private Element xmlCommand; + private String commandName; + private String testCaseInfo; + private boolean isUserCommand; + private boolean isAsync = false; + private CommandType commandType; + private ResponseType responseType; + + + private TreeMap urlParam; + private HashMap verifyParam = new HashMap();; + private HashMap setParam = new HashMap();; + private int responseCode; + private Element responseBody; + + private String command; + private String host; + private boolean list; + private Element listName; + private Element listId; + private boolean required = false; + private ResultSet result; + + + public ApiCommand(Element fstElmnt, HashMap param, HashMap commands){ + this.setXmlCommand(fstElmnt); + this.setCommandName(); + this.setResponseType(); + this.setUserCommand(); + this.setCommandType(); + this.setTestCaseInfo(); + this.setUrlParam(param); + this.setVerifyParam(param); + this.setHost("http://" + param.get("hostip")); + this.setCommand(param); + String async = commands.get(this.getName()); + if (async != null && async.equals("yes")) { + this.isAsync = true; + } + } + + public Element getXmlCommand() { + return xmlCommand; + } + + public void setXmlCommand(Element xmlCommand) { + this.xmlCommand = xmlCommand; + } + + //================FOLLOWING METHODS USE INPUT XML FILE=======================// + public void setCommandName() { + NodeList commandName = this.xmlCommand.getElementsByTagName("name"); + Element commandElmnt = (Element) commandName.item(0); + NodeList commandNm = commandElmnt.getChildNodes(); + this.commandName = (((Node) commandNm.item(0)).getNodeValue()); + } + + public String getName() { + return commandName; + } + + public void setTestCaseInfo() { + this.testCaseInfo = getElementByName("testcase"); + } + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public void setResponseType() { + boolean result = verifyTagValue("error", "true"); + if (result) { + this.responseType = ResponseType.ERROR; + return; + } + result = verifyTagValue("empty", "true"); + if (result) { + this.responseType = ResponseType.EMPTY; + } + } + + public void setResponseType(ResponseType responseType) { + this.responseType = responseType; + } + + public ResponseType getResponseType() { + return responseType; + } + + public void setUserCommand() { + boolean result = verifyTagValue("usercommand", "true"); + this.isUserCommand = result; + } + + public void setCommandType() { + boolean result = verifyTagValue("mysql", "true"); + if (result) { + this.commandType = CommandType.MYSQL; + return; + } + result = verifyTagValue("script", "true"); + if (result) { + this.commandType = CommandType.SCRIPT; + return; + } + this.commandType = CommandType.HTTP; + } + + public CommandType getCommandType() { + return commandType; + } + + public String getTestCaseInfo() { + return testCaseInfo; + } + + public Boolean getRequired() { + return required; + } + + public void setUrlParam(HashMap param) { + this.urlParam = new TreeMap(); + NodeList parameterLst= this.xmlCommand.getElementsByTagName("parameters"); + if (parameterLst != null ) { + for (int j=0; j param) { + + if (this.getCommandType() == CommandType.SCRIPT) { + String temp = "bash xen/" + this.commandName; + Set c = this.urlParam.entrySet(); + Iterator it = c.iterator(); + while (it.hasNext()) { + Map.Entry me = (Map.Entry)it.next(); + String key = (String) me.getKey(); + String value = (String) me.getValue(); + try { + temp = temp + " -" + key + " " + value; + } catch (Exception ex) { + s_logger.error("Unable to set parameter " + key + " for the command " + this.getName()); + } + } + this.command = temp; + } else if (this.getCommandType() == CommandType.MYSQL) { + String temp = this.commandName + " where "; + Set c = this.urlParam.entrySet(); + Iterator it = c.iterator(); + while (it.hasNext()) { + Map.Entry me = (Map.Entry)it.next(); + String key = (String) me.getKey(); + String value = (String) me.getValue(); + try { + temp = temp + key + "=" + value; + } catch (Exception ex) { + s_logger.error("Unable to set parameter " + key + " for the command " + this.getName()); + } + } + this.command = temp; + s_logger.info("The command is " + this.command); + + } else { + if ((param.get("apikey") == null) || (param.get("secretkey")==null) || (this.isUserCommand == false)) { + String temp = this.host + ":8096/?command="+ this.commandName; + Set c = this.urlParam.entrySet(); + Iterator it = c.iterator(); + while (it.hasNext()) { + Map.Entry me = (Map.Entry)it.next(); + String key = (String) me.getKey(); + String value = (String) me.getValue(); + try { + temp = temp + "&" + key + "=" + URLEncoder.encode(value, "UTF-8"); + } catch (Exception ex) { + s_logger.error("Unable to set parameter " + key + " for the command " + this.getName()); + } + } + this.command = temp; + } + else if (isUserCommand == true) { + String apiKey = param.get("apikey"); + String secretKey = param.get("secretkey"); + + String temp = ""; + this.urlParam.put("apikey", apiKey); + this.urlParam.put("command", this.commandName); + + //sort url hash map by key + Set c = this.urlParam.entrySet(); + Iterator it = c.iterator(); + while (it.hasNext()) { + Map.Entry me = (Map.Entry)it.next(); + String key = (String) me.getKey(); + String value = (String) me.getValue(); + try { + temp = temp + key + "=" + URLEncoder.encode(value, "UTF-8") + "&"; + } catch (Exception ex) { + s_logger.error("Unable to set parameter " + value + " for the command " + this.getName()); + } + + } + temp = temp.substring(0, temp.length()-1 ); + String requestToSign = temp.toLowerCase(); + String signature = UtilsForTest.signRequest(requestToSign, secretKey); + String encodedSignature = ""; + try { + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + } catch (Exception ex) { + s_logger.error(ex); + } + this.command = this.host + ":8080/client/api/?" + temp + "&signature=" + encodedSignature; + } + } + } + + public void setVerifyParam(HashMap param) { + NodeList returnLst= this.xmlCommand.getElementsByTagName("returnvalue"); + if (returnLst != null ) { + for (int m=0; m param) { + if ((this.responseBody == null) && (this.commandType == CommandType.HTTP)) { + s_logger.error("Response body is empty"); + return false; + } + Boolean result = true; + + if (this.getCommandType() == CommandType.MYSQL) { + Set set = this.setParam.entrySet(); + Iterator it = set.iterator(); + while (it.hasNext()) { + Map.Entry me = (Map.Entry)it.next(); + String key = (String) me.getKey(); + String value = (String) me.getValue(); + try { + String itemName = null; + while (this.result.next()) { + itemName = this.result.getString(value); + } + if (itemName != null) { + param.put(key, itemName); + } + else { + s_logger.error("Following return parameter is missing: " + value); + result = false; + } + } catch (Exception ex) { + s_logger.error("Unable to set parameter " + value, ex); + } + } + } else if (this.getCommandType() == CommandType.HTTP) { + if (this.list == false) { + Set set = this.setParam.entrySet(); + Iterator it = set.iterator(); + + while (it.hasNext()) { + Map.Entry me = (Map.Entry)it.next(); + String key = (String) me.getKey(); + String value = (String) me.getValue(); + //set parameters needed for the future use + NodeList itemName = this.responseBody.getElementsByTagName(value); + if ((itemName != null) && (itemName.getLength() != 0)) { + for (int i=0; i < itemName.getLength(); i++) { + Element itemNameElement = (Element) itemName.item(i); + if (itemNameElement.getChildNodes().getLength() <= 1) { + param.put(key, itemNameElement.getTextContent()); + break; + } + } + } + else { + s_logger.error("Following return parameter is missing: " + value); + result = false; + } + } + } else { + Set set = this.setParam.entrySet(); + Iterator it = set.iterator(); + NodeList returnLst = this.responseBody.getElementsByTagName(this.listName.getTextContent()); + Node requiredNode = returnLst.item(Integer.parseInt(this.listId.getTextContent())); + + if (requiredNode.getNodeType() == Node.ELEMENT_NODE) { + Element fstElmnt = (Element) requiredNode; + + while (it.hasNext()) { + Map.Entry me = (Map.Entry)it.next(); + String key = (String) me.getKey(); + String value = (String) me.getValue(); + NodeList itemName = fstElmnt.getElementsByTagName(value); + if ((itemName != null) && (itemName.getLength() != 0)) { + Element itemNameElement = (Element) itemName.item(0); + if (itemNameElement.getChildNodes().getLength() <= 1) { + param.put(key, itemNameElement.getTextContent()); + } + } + else { + s_logger.error("Following return parameter is missing: " + value); + result = false; + } + } + } + } + } + return result; + } + + public String getUrl() { + return command; + } + + public boolean verifyParam() { + boolean result = true; + if (this.getCommandType() == CommandType.HTTP) { + if (this.list == false) { + Set set = verifyParam.entrySet(); + Iterator it = set.iterator(); + + while (it.hasNext()) { + Map.Entry me = (Map.Entry)it.next(); + String key = (String) me.getKey(); + String value = (String) me.getValue(); + if (value == null) { + s_logger.error("Parameter " + key + " is missing in the list of global parameters"); + return false; + } + + NodeList itemName = this.responseBody.getElementsByTagName(key); + if ((itemName.getLength() != 0) && (itemName != null)) { + Element itemNameElement = (Element) itemName.item(0); + if (itemNameElement.hasChildNodes()) { + continue; + } + if ( !(verifyParam.get(key).equals("no value")) && !(itemNameElement.getTextContent().equals(verifyParam.get(key)))){ + s_logger.error("Incorrect value for the following tag: " + key + ". Expected value is " + verifyParam.get(key) + " while actual value is " + itemNameElement.getTextContent()); + result = false; + } + } else { + s_logger.error("Following xml element is missing in the response: " + key); + result=false; + } + } + } + //for multiple elements + else { + Set set = verifyParam.entrySet(); + Iterator it = set.iterator(); + //get list element specified by id + NodeList returnLst = this.responseBody.getElementsByTagName(this.listName.getTextContent()); + Node requiredNode = returnLst.item(Integer.parseInt(this.listId.getTextContent())); + + if (requiredNode.getNodeType() == Node.ELEMENT_NODE) { + Element fstElmnt = (Element) requiredNode; + + while (it.hasNext()) { + Map.Entry me = (Map.Entry)it.next(); + String key = (String) me.getKey(); + String value = (String) me.getValue(); + if (value == null) { + s_logger.error("Parameter " + key + " is missing in the list of global parameters"); + return false; + } + NodeList itemName = fstElmnt.getElementsByTagName(key); + if ((itemName.getLength() != 0) && (itemName != null)) { + Element itemNameElement = (Element) itemName.item(0); + if ( !(verifyParam.get(key).equals("no value")) && !(itemNameElement.getTextContent().equals(verifyParam.get(key)))){ + s_logger.error("Incorrect value for the following tag: " + key + ". Expected value is " + verifyParam.get(key) + " while actual value is " + itemNameElement.getTextContent()); + result = false; + } + } else { + s_logger.error("Following xml element is missing in the response: " + key); + result = false; + } + } + } + } + } else if (this.getCommandType() == CommandType.MYSQL) { + Set set = verifyParam.entrySet(); + Iterator it = set.iterator(); + + while (it.hasNext()) { + Map.Entry me = (Map.Entry)it.next(); + String key = (String) me.getKey(); + String value = (String) me.getValue(); + if (value == null) { + s_logger.error("Parameter " + key + " is missing in the list of global parameters"); + return false; + } + + String itemName = null; + try { + while(this.result.next()) { + itemName = this.result.getString(key); + } + } catch (Exception ex) { + s_logger.error("Unable to get element from result set " + key); + } + + if ( !(value.equals("no value")) && !(itemName.equals(verifyParam.get(key)))){ + s_logger.error("Incorrect value for the following tag: " + key + ". Expected value is " + verifyParam.get(key) + " while actual value is " + itemName); + result = false; + } + } + } + return result; + } + + public static boolean verifyEvents (String fileName, String level, String host, String account) { + boolean result=false; + HashMap expectedEvents = new HashMap (); + HashMap actualEvents = new HashMap (); + String key = ""; + + File file = new File(fileName); + if (file.exists()) { + Properties pro = new Properties(); + try { + //get expected events + FileInputStream in = new FileInputStream(file); + pro.load(in); + Enumeration en = pro.propertyNames(); + while (en.hasMoreElements()) { + key = (String) en.nextElement(); + expectedEvents.put(key, Integer.parseInt(pro.getProperty(key))); + } + + //get actual events + String url = host + "/?command=listEvents&account=" + account + "&level=" + level + "&domainid=1&pagesize=100"; + s_logger.info("Getting events with the following url " + url); + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + int responseCode = client.executeMethod(method); + if (responseCode == 200 ) { + InputStream is = method.getResponseBodyAsStream(); + ArrayList> eventValues = UtilsForTest.parseMulXML( + is, new String[] { "event" }); + + for (int i=0; i< eventValues.size(); i++) { + HashMap element = eventValues.get(i); + if (element.get("level").equals(level)) { + if (actualEvents.containsKey(element.get("type")) == true){ + actualEvents.put(element.get("type"), actualEvents.get(element.get("type"))+1); + } + else { + actualEvents.put(element.get("type"), 1); + } + } + } + } + method.releaseConnection(); + + //compare actual events with expected events + + //compare expected result and actual result + Iterator iterator = expectedEvents.keySet().iterator(); + Integer expected; + Integer actual; + int fail=0; + while (iterator.hasNext()) { + expected=null; + actual=null; + String type = iterator.next().toString(); + expected = expectedEvents.get(type); + actual = actualEvents.get(type); + if (actual == null ) { + s_logger.error("Event of type " + type + " and level " + level + " is missing in the listEvents response. Expected number of these events is " + expected); + fail++; + } else if (expected.compareTo(actual) != 0){ + fail++; + s_logger.info("Amount of events of " + type + " type and level " + level + " is incorrect. Expected number of these events is " + expected + ", actual number is " + actual); + } + } + if (fail == 0) { + result = true; + } + } catch (Exception ex) { + s_logger.error(ex); + } + }else { + s_logger.info("File " + fileName + " not found"); + } + return result; + } + + + public static boolean verifyEvents (HashMap expectedEvents, String level, String host, String parameters) { + boolean result=false; + HashMap actualEvents = new HashMap (); + try { + //get actual events + String url = host + "/?command=listEvents&" + parameters; + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + int responseCode = client.executeMethod(method); + if (responseCode == 200 ) { + InputStream is = method.getResponseBodyAsStream(); + ArrayList> eventValues = UtilsForTest.parseMulXML( + is, new String[] { "event" }); + + for (int i=0; i< eventValues.size(); i++) { + HashMap element = eventValues.get(i); + if (element.get("level").equals(level)) { + if (actualEvents.containsKey(element.get("type")) == true){ + actualEvents.put(element.get("type"), actualEvents.get(element.get("type"))+1); + } + else { + actualEvents.put(element.get("type"), 1); + } + } + } + } + method.releaseConnection(); + }catch (Exception ex) { + s_logger.error(ex); + } + + //compare actual events with expected events + Iterator iterator = expectedEvents.keySet().iterator(); + Integer expected; + Integer actual; + int fail=0; + while (iterator.hasNext()) { + expected=null; + actual=null; + String type = iterator.next().toString(); + expected = expectedEvents.get(type); + actual = actualEvents.get(type); + if (actual == null ) { + s_logger.error("Event of type " + type + " and level " + level + " is missing in the listEvents response. Expected number of these events is " + expected); + fail++; + } + else if (expected.compareTo(actual) != 0){ + fail++; + s_logger.info("Amount of events of " + type + " type and level " + level + " is incorrect. Expected number of these events is " + expected + ", actual number is " + actual); + } + } + + if (fail == 0) { + result = true; + } + + return result; + } + + + public Element queryAsyncJobResult (String jobId) { + Element returnBody = null; + int code = 400; + String resultUrl = this.host + ":8096/?command=queryAsyncJobResult&jobid=" + jobId; + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(resultUrl); + while (true) { + try { + code = client.executeMethod(method); + if (code == 200) { + InputStream is = method.getResponseBodyAsStream(); + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document doc = builder.parse(is); + doc.getDocumentElement().normalize(); + returnBody = doc.getDocumentElement(); + Element jobStatusTag = (Element) returnBody.getElementsByTagName("jobstatus").item(0); + String jobStatus = jobStatusTag.getTextContent(); + if(jobStatus.equals("0")) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + } else { + break; + } + method.releaseConnection(); + } + else { + s_logger.error("Error during queryJobAsync. Error code is " + code); + this.responseCode = code; + return null; + } + } catch (Exception ex) { + s_logger.error(ex); + } + } + return returnBody; + } + + private String getElementByName(String elementName){ + NodeList commandName = this.xmlCommand.getElementsByTagName(elementName); + if (commandName.getLength() != 0) { + Element commandElmnt = (Element) commandName.item(0); + NodeList commandNm = commandElmnt.getChildNodes(); + return ((Node) commandNm.item(0)).getNodeValue(); + } + else { + return null; + } + } + + private boolean verifyTagValue(String elementName, String expectedValue){ + NodeList tag = this.xmlCommand.getElementsByTagName(elementName); + if (tag.getLength() != 0) { + Element commandElmnt = (Element) tag.item(0); + NodeList commandNm = commandElmnt.getChildNodes(); + if (((Node) commandNm.item(0)).getNodeValue().equals(expectedValue)) { + return true; + } else { + return false; + } + } else { + return false; + } + } +} diff --git a/test/src/com/cloud/test/regression/ConfigTest.java b/test/src/com/cloud/test/regression/ConfigTest.java new file mode 100644 index 00000000000..4321b432765 --- /dev/null +++ b/test/src/com/cloud/test/regression/ConfigTest.java @@ -0,0 +1,134 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.regression; + +import java.util.HashMap; + +import org.apache.log4j.Logger; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + + +import com.cloud.test.regression.ApiCommand.ResponseType; +import com.trilead.ssh2.Connection; +import com.trilead.ssh2.Session; + +public class ConfigTest extends TestCase{ + public static final Logger s_logger = Logger.getLogger(ConfigTest.class.getName()); + + public ConfigTest(){ + this.setClient(); + this.setParam(new HashMap()); + } + + public boolean executeTest(){ + + int error=0; + Element rootElement = this.getInputFile().get(0).getDocumentElement(); + NodeList commandLst = rootElement.getElementsByTagName("command"); + + //Analyze each command, send request and build the array list of api commands + for (int i=0; i. + * + */ + +package com.cloud.test.regression; + + +import java.util.HashMap; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import com.cloud.test.regression.ApiCommand.ResponseType; + +public class DelegatedAdminTest extends TestCase{ + +public static final Logger s_logger = Logger.getLogger(DelegatedAdminTest.class.getName()); + + public DelegatedAdminTest(){ + this.setClient(); + this.setParam(new HashMap()); + } + + public boolean executeTest(){ + int error=0; + + for (Document eachElement: this.getInputFile()) { + + Element rootElement = eachElement.getDocumentElement(); + NodeList commandLst = rootElement.getElementsByTagName("command"); + + //Analyze each command, send request and build the array list of api commands + for (int i=0; i. + * + */ + +package com.cloud.test.regression; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +import org.apache.log4j.Logger; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class Deploy extends TestCase{ + public static final Logger s_logger = Logger.getLogger(Deploy.class.getName()); + + public Deploy(){ + this.setClient(); + this.setParam(new HashMap()); + } + + + public boolean executeTest() { + int error=0; + Element rootElement = this.getInputFile().get(0).getDocumentElement(); + NodeList commandLst = rootElement.getElementsByTagName("command"); + + //Analyze each command, send request and build the array list of api commands + for (int i=0; i argsList = Arrays.asList(args); + Iterator iter = argsList.iterator(); + String host = null; + String file = null; + + while (iter.hasNext()) { + String arg = iter.next(); + // management server host + if (arg.equals("-h")) { + host = iter.next(); + } + if (arg.equals("-f")) { + file = iter.next(); + } + } + + Deploy deploy = new Deploy (); + + ArrayList inputFile = new ArrayList(); + inputFile.add(file); + deploy.setInputFile(inputFile); + deploy.setTestCaseName("Management server deployment"); + deploy.getParam().put("hostip", host); + deploy.getParam().put("apicommands", "../metadata/func/commands"); + deploy.setCommands(); + + s_logger.info("Starting deployment against host " + host); + + boolean result = deploy.executeTest(); + if (result == false) { + s_logger.error("DEPLOYMENT FAILED"); + System.exit(1); + } + else { + s_logger.info("DEPLOYMENT IS SUCCESSFUL"); + } + + } + +} + diff --git a/test/src/com/cloud/test/regression/EventsApiTest.java b/test/src/com/cloud/test/regression/EventsApiTest.java new file mode 100644 index 00000000000..2289da7b8af --- /dev/null +++ b/test/src/com/cloud/test/regression/EventsApiTest.java @@ -0,0 +1,181 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.regression; + +import java.sql.Statement; +import java.util.HashMap; + +import org.apache.log4j.Logger; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import com.cloud.test.regression.ApiCommand.ResponseType; +import com.trilead.ssh2.Connection; +import com.trilead.ssh2.Session; + +public class EventsApiTest extends TestCase{ +public static final Logger s_logger = Logger.getLogger(EventsApiTest.class.getName()); + + + public EventsApiTest(){ + this.setClient(); + this.setParam(new HashMap()); + } + + public boolean executeTest(){ + int error=0; + Element rootElement = this.getInputFile().get(0).getDocumentElement(); + NodeList commandLst = rootElement.getElementsByTagName("command"); + + + //Analyze each command, send request and build the array list of api commands + for (int i=0; i expectedEvents = new HashMap(); + expectedEvents.put("VM.START", 1); + boolean eventResult = ApiCommand.verifyEvents(expectedEvents, "INFO", "http://" + this.getParam().get("hostip") + ":8096", "userid=" + this.getParam().get("userid1") + "&type=VM.START"); + s_logger.info("Test case 97 - listEvent command verification result is " + eventResult); + + //verify error events + eventResult = ApiCommand.verifyEvents("../metadata/error_events.properties", "ERROR", "http://" + this.getParam().get("hostip") + ":8096", this.getParam().get("erroruseraccount")); + s_logger.info("listEvent command verification result is " + eventResult); + + + if (error != 0) + return false; + else + return true; + } +} diff --git a/test/src/com/cloud/test/regression/HA.java b/test/src/com/cloud/test/regression/HA.java new file mode 100644 index 00000000000..355464f6c5b --- /dev/null +++ b/test/src/com/cloud/test/regression/HA.java @@ -0,0 +1,81 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.regression; + +import org.apache.log4j.Logger; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import com.cloud.test.regression.ApiCommand.ResponseType; + +public class HA extends TestCase{ + + public static final Logger s_logger = Logger.getLogger(HA.class.getName()); + + public HA(){ + this.setClient(); + } + + public boolean executeTest(){ + int error=0; + Element rootElement = this.getInputFile().get(0).getDocumentElement(); + NodeList commandLst = rootElement.getElementsByTagName("command"); + + //Analyze each command, send request and build the array list of api commands + for (int i=0; i. + * + */ + +package com.cloud.test.regression; + +import java.util.HashMap; + +import org.apache.log4j.Logger; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import com.cloud.test.regression.ApiCommand.ResponseType; + + +public class LoadBalancingTest extends TestCase{ + + public static final Logger s_logger = Logger.getLogger(LoadBalancingTest.class.getName()); + + public LoadBalancingTest(){ + this.setClient(); + this.setParam(new HashMap()); + } + + public boolean executeTest(){ + + int error=0; + Element rootElement = this.getInputFile().get(0).getDocumentElement(); + NodeList commandLst = rootElement.getElementsByTagName("command"); + + //Analyze each command, send request and build the array list of api commands + for (int i=0; i port = new ArrayList(); +// for (int i=1; i<65536; i++){ +// port.add(Integer.toString(i)); +// } +// +// //try all public ports +// for (String portValue : port) { +// try { +// String url = this.getHost() + ":8096/?command=createOrUpdateLoadBalancerRule&account=" + this.getParam().get("accountname") + "&publicip=" + this.getParam().get("boundaryip") + +// "&privateip=" + this.getParam().get("vmipaddress") + "&privateport=22&protocol=tcp&publicport=" + portValue; +// HttpClient client = new HttpClient(); +// HttpMethod method = new GetMethod(url); +// int responseCode = client.executeMethod(method); +// if (responseCode != 200 ) { +// error++; +// s_logger.error("Can't create LB rule for the public port " + portValue + ". Request was sent with url " + url); +// } +// }catch (Exception ex) { +// s_logger.error(ex); +// } +// } +// +// //try all private ports +// for (String portValue : port) { +// try { +// String url = this.getHost() + ":8096/?command=createOrUpdateLoadBalancerRule&account=" + this.getParam().get("accountname") + "&publicip=" + this.getParam().get("boundaryip") + +// "&privateip=" + this.getParam().get("vmipaddress") + "&publicport=22&protocol=tcp&privateport=" + portValue; +// HttpClient client = new HttpClient(); +// HttpMethod method = new GetMethod(url); +// int responseCode = client.executeMethod(method); +// if (responseCode != 200 ) { +// error++; +// s_logger.error("Can't create LB rule for the private port " + portValue + ". Request was sent with url " + url); +// } +// }catch (Exception ex) { +// s_logger.error(ex); +// } +// } + + + if (error != 0) + return false; + else + return true; + } + +} diff --git a/test/src/com/cloud/test/regression/PortForwardingTest.java b/test/src/com/cloud/test/regression/PortForwardingTest.java new file mode 100644 index 00000000000..55af20ca577 --- /dev/null +++ b/test/src/com/cloud/test/regression/PortForwardingTest.java @@ -0,0 +1,149 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.regression; + +import java.util.HashMap; + +import org.apache.log4j.Logger; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import com.cloud.test.regression.ApiCommand.ResponseType; + +public class PortForwardingTest extends TestCase{ + public static final Logger s_logger = Logger.getLogger(PortForwardingTest.class.getName()); + + public PortForwardingTest(){ + this.setClient(); + this.setParam(new HashMap()); + } + + public boolean executeTest(){ + + int error=0; + Element rootElement = this.getInputFile().get(0).getDocumentElement(); + NodeList commandLst = rootElement.getElementsByTagName("command"); + + //Analyze each command, send request and build the array list of api commands + for (int i=0; i port = new ArrayList(); +// for (int i=1; i<65536; i++){ +// port.add(Integer.toString(i)); +// } +// +// //try all public ports +// for (String portValue : port) { +// try { +// s_logger.info("public port is " + portValue); +// String url = this.getHost() + ":8096/?command=createOrUpdateIpForwardingRule&account=" + this.getParam().get("accountname") + "&publicip=" + this.getParam().get("boundaryip") + +// "&privateip=" + this.getParam().get("vmipaddress") + "&privateport=22&protocol=tcp&publicport=" + portValue; +// HttpClient client = new HttpClient(); +// HttpMethod method = new GetMethod(url); +// int responseCode = client.executeMethod(method); +// if (responseCode != 200 ) { +// error++; +// s_logger.error("Can't create portForwarding rule for the public port " + portValue + ". Request was sent with url " + url); +// } +// }catch (Exception ex) { +// s_logger.error(ex); +// } +// } +// +// //try all private ports +// for (String portValue : port) { +// try { +// String url = this.getHost() + ":8096/?command=createOrUpdateIpForwardingRule&account=" + this.getParam().get("accountname") + "&publicip=" + this.getParam().get("boundaryip") + +// "&privateip=" + this.getParam().get("vmipaddress") + "&publicport=22&protocol=tcp&privateport=" + portValue; +// HttpClient client = new HttpClient(); +// HttpMethod method = new GetMethod(url); +// int responseCode = client.executeMethod(method); +// if (responseCode != 200 ) { +// error++; +// s_logger.error("Can't create portForwarding rule for the private port " + portValue + ". Request was sent with url " + url); +// } +// }catch (Exception ex) { +// s_logger.error(ex); +// } +// } + + + if (error != 0) + return false; + else + return true; + } + +} diff --git a/test/src/com/cloud/test/regression/SanityTest.java b/test/src/com/cloud/test/regression/SanityTest.java new file mode 100644 index 00000000000..aeea44ebfef --- /dev/null +++ b/test/src/com/cloud/test/regression/SanityTest.java @@ -0,0 +1,90 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.regression; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.apache.log4j.Logger; + +public class SanityTest extends TestCase{ + + public static final Logger s_logger = Logger.getLogger(SanityTest.class.getName()); + + public SanityTest(){ + this.setClient(); + } + + public boolean executeTest(){ + int error=0; + Element rootElement = this.getInputFile().get(0).getDocumentElement(); + NodeList commandLst = rootElement.getElementsByTagName("command"); + //Analyze each command, send request and build the array list of api commands + for (int i=0; i. + * + */ + +package com.cloud.test.regression; + +import java.util.ArrayList; +import java.util.HashMap; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.log4j.Logger; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class Test extends TestCase{ + public static final Logger s_logger = Logger.getLogger(Test.class.getName()); + + public Test(){ + this.setClient(); + this.setParam(new HashMap()); + } + + public boolean executeTest(){ + + int error=0; + Element rootElement = this.getInputFile().get(0).getDocumentElement(); + NodeList commandLst = rootElement.getElementsByTagName("command"); + + //Analyze each command, send request and build the array list of api commands + for (int i=0; i port = new ArrayList(); + for (int j=1; j<1000; j++){ + port.add(Integer.toString(j)); + } + + //try all public ports + for (String portValue : port) { + try { + s_logger.info("public port is " + portValue); + String url = "http://" + this.getParam().get("hostip") + ":8096/?command=createNetworkRule&publicPort=" + portValue + "&privatePort=22&protocol=tcp&isForward=true&securityGroupId=1&account=admin"; + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + int responseCode = client.executeMethod(method); + if (responseCode != 200 ) { + error++; + s_logger.error("Can't create portForwarding network rule for the public port " + portValue + ". Request was sent with url " + url); + } + }catch (Exception ex) { + s_logger.error(ex); + } + } + + + if (error != 0) + return false; + else + return true; + } +} diff --git a/test/src/com/cloud/test/regression/TestCase.java b/test/src/com/cloud/test/regression/TestCase.java new file mode 100644 index 00000000000..3822275c2e0 --- /dev/null +++ b/test/src/com/cloud/test/regression/TestCase.java @@ -0,0 +1,143 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.regression; + +import java.io.File; +import java.io.FileInputStream; +import java.sql.Connection; +import java.sql.DriverManager; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Properties; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.log4j.Logger; +import org.w3c.dom.Document; + + +public abstract class TestCase{ + + public static Logger s_logger = Logger.getLogger(TestCase.class.getName()); + private Connection conn; + private ArrayList inputFile = new ArrayList (); + private HttpClient client; + private String testCaseName; + private HashMap param = new HashMap (); + private HashMap commands = new HashMap (); + + public HashMap getParam() { + return param; + } + + public void setParam(HashMap param) { + this.param = param; + } + + + public HashMap getCommands() { + return commands; + } + + public void setCommands() { + File asyncCommands = null; + if (param.get("apicommands") == null) { + s_logger.info("Unable to get the list of commands, exiting"); + System.exit(1); + } else { + asyncCommands = new File(param.get("apicommands")); + } + try { + Properties pro = new Properties(); + FileInputStream in = new FileInputStream(asyncCommands); + pro.load(in); + Enumeration en = pro.propertyNames(); + while (en.hasMoreElements()) { + String key = (String) en.nextElement(); + commands.put(key, pro.getProperty(key)); + } + } catch (Exception ex) { + s_logger.info("Unable to find the file " + param.get("apicommands") + " due to following exception " + ex); + } + + } + + public Connection getConn() { + return conn; + } + + public void setConn(String dbPassword) { + this.conn = null; + try { + Class.forName("com.mysql.jdbc.Driver"); + this.conn=DriverManager.getConnection("jdbc:mysql://" + param.get("db") + "/cloud", "root", dbPassword); + if (!this.conn.isValid(0)) { + s_logger.error("Connection to DB failed to establish"); + } + + }catch (Exception ex) { + s_logger.error(ex); + } + } + + public void setInputFile (ArrayList fileNameInput) { + for (String fileName: fileNameInput) { + File file = new File(fileName); + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + Document doc = null; + try { + DocumentBuilder builder = factory.newDocumentBuilder(); + doc = builder.parse(file); + doc.getDocumentElement().normalize(); + } catch (Exception ex) { + s_logger.error("Unable to load " + fileName + " due to ", ex); + } + this.inputFile.add(doc); + } + } + + public ArrayList getInputFile() { + return inputFile; + } + + public void setTestCaseName(String testCaseName) { + this.testCaseName = testCaseName; + } + + public String getTestCaseName(){ + return this.testCaseName; + } + + public void setClient() { + HttpClient client = new HttpClient(); + this.client = client; + } + + public HttpClient getClient() { + return this.client; + } + + //abstract methods + public abstract boolean executeTest(); + +} diff --git a/test/src/com/cloud/test/regression/TestCaseEngine.java b/test/src/com/cloud/test/regression/TestCaseEngine.java new file mode 100644 index 00000000000..42d1d177c01 --- /dev/null +++ b/test/src/com/cloud/test/regression/TestCaseEngine.java @@ -0,0 +1,291 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.regression; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class TestCaseEngine { + + public static final Logger s_logger = Logger.getLogger(TestCaseEngine.class + .getName()); + public static String fileName = "../metadata/adapter.xml"; + public static HashMap globalParameters = new HashMap(); + protected static HashMap _componentMap = new HashMap(); + protected static HashMap> _inputFile = new HashMap>(); + protected static String testCaseName = new String(); + protected static ArrayList _keys = new ArrayList(); + private static ThreadLocal result = new ThreadLocal(); + public static int _numThreads = 1; + public static boolean _repeat = false; + public static boolean _printUrl = false; + public static String type = "All"; + public static boolean isSanity = false; + public static boolean isRegression = false; + private static int failure = 0; + + public static void main(String args[]) { + + // Parameters + List argsList = Arrays.asList(args); + Iterator iter = argsList.iterator(); + while (iter.hasNext()) { + String arg = iter.next(); + // is stress? + if (arg.equals("-t")) { + _numThreads = Integer.parseInt(iter.next()); + } + // do you want to print url for all commands? + if (arg.equals("-p")) { + _printUrl = true; + } + + //type of the test: sanity, regression, all (default) + if (arg.equals("-type")) { + type = iter.next(); + } + + if (arg.equals("-repeat")) { + _repeat = Boolean.valueOf(iter.next()); + } + + if (arg.equals("-filename")) { + fileName = iter.next(); + } + } + + if (type.equalsIgnoreCase("sanity")) + isSanity = true; + else if (type.equalsIgnoreCase("regression")) + isRegression = true; + + try { + // parse adapter.xml file to get list of tests to execute + File file = new File(fileName); + DocumentBuilderFactory factory = DocumentBuilderFactory + .newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document doc = builder.parse(file); + doc.getDocumentElement().normalize(); + Element root = doc.getDocumentElement(); + + // set global parameters + setGlobalParams(root); + + // populate _componentMap + setComponent(root); + + // set error to 0 by default + + // execute test + for (int i = 0; i < _numThreads; i++) { + if (_numThreads > 1) { + s_logger.info("STARTING STRESS TEST IN " + + _numThreads + " THREADS"); + } else { + s_logger.info("STARTING FUNCTIONAL TEST"); + } + new Thread(new Runnable() { + public void run() { + do { + if (_numThreads == 1) { + try { + for (String key : _keys) { + Class c = Class.forName(_componentMap.get(key)); + TestCase component = (TestCase) c.newInstance(); + executeTest(key, c, component); + } + } catch (Exception ex1) { + s_logger.error(ex1); + } finally { + if (failure > 0) { + System.exit(1); + } + } + } else { + Random ran = new Random(); + Integer randomNumber = (Integer) Math.abs(ran + .nextInt(_keys.size())); + try { + String key = _keys.get(randomNumber); + Class c = Class.forName(_componentMap + .get(key)); + TestCase component = (TestCase) c + .newInstance(); + executeTest(key, c, component); + } catch (Exception e) { + s_logger.error("Error in thread ", e); + } + } + } while (_repeat); + } + }).start(); + } + + } catch (Exception exc) { + s_logger.error(exc); + } + } + + public static void setGlobalParams(Element rootElement) { + NodeList globalParam = rootElement.getElementsByTagName("globalparam"); + Element parameter = (Element) globalParam.item(0); + NodeList paramLst = parameter.getElementsByTagName("param"); + + for (int i = 0; i < paramLst.getLength(); i++) { + Element paramElement = (Element) paramLst.item(i); + + if (paramElement.getNodeType() == Node.ELEMENT_NODE) { + Element itemElement = (Element) paramElement; + NodeList itemName = itemElement.getElementsByTagName("name"); + Element itemNameElement = (Element) itemName.item(0); + NodeList itemVariable = itemElement + .getElementsByTagName("variable"); + Element itemVariableElement = (Element) itemVariable.item(0); + globalParameters.put(itemVariableElement.getTextContent(), + itemNameElement.getTextContent()); + } + } + } + + public static void setComponent(Element rootElement) { + NodeList testLst = rootElement.getElementsByTagName("test"); + for (int j = 0; j < testLst.getLength(); j++) { + Element testElement = (Element) testLst.item(j); + + if (testElement.getNodeType() == Node.ELEMENT_NODE) { + Element itemElement = (Element) testElement; + + // get test case name + NodeList testCaseNameList = itemElement + .getElementsByTagName("testname"); + if (testCaseNameList != null) { + testCaseName = ((Element) testCaseNameList.item(0)) + .getTextContent(); + } + + if (isSanity == true && !testCaseName.equals("SANITY TEST")) + continue; + else if (isRegression == true && !(testCaseName.equals("SANITY TEST") || testCaseName.equals("REGRESSION TEST"))) + continue; + + // set class name + NodeList className = itemElement.getElementsByTagName("class"); + if ((className.getLength() == 0) || (className == null)) { + _componentMap.put(testCaseName, + "com.cloud.test.regression.VMApiTest"); + } else { + String name = ((Element) className.item(0)) + .getTextContent(); + _componentMap.put(testCaseName, name); + } + + // set input file name + NodeList inputFileNameLst = itemElement + .getElementsByTagName("filename"); + _inputFile.put(testCaseName, new ArrayList()); + for (int k = 0; k < inputFileNameLst.getLength(); k++) { + String inputFileName = ((Element) inputFileNameLst.item(k)) + .getTextContent(); + _inputFile.get(testCaseName).add(inputFileName); + } + } + } + + //If sanity test required, make sure that SANITY TEST componennt got loaded + if (isSanity == true && _componentMap.size() == 0) { + s_logger.error("FAILURE!!! Failed to load SANITY TEST component. Verify that the test is uncommented in adapter.xml"); + System.exit(1); + } + + if (isRegression == true && _componentMap.size() != 2) { + s_logger.error("FAILURE!!! Failed to load SANITY TEST or REGRESSION TEST components. Verify that these tests are uncommented in adapter.xml"); + System.exit(1); + } + + // put all keys from _componentMap to the ArrayList + Set set = _componentMap.entrySet(); + Iterator it = set.iterator(); + while (it.hasNext()) { + Map.Entry me = (Map.Entry) it.next(); + String key = (String) me.getKey(); + _keys.add(key); + } + + } + + public static boolean executeTest(String key, Class c, TestCase component) { + boolean finalResult = false; + try { + s_logger.info("Starting \"" + key + "\" test...\n\n"); + + // set global parameters + HashMap updateParam = new HashMap(); + updateParam.putAll(globalParameters); + component.setParam(updateParam); + + // set DB ip address + component.setConn(globalParameters.get("dbPassword")); + + // set commands list + component.setCommands(); + + // set input file + if (_inputFile.get(key) != null) { + component.setInputFile(_inputFile.get(key)); + } + + // set test case name + if (key != null) { + component.setTestCaseName(testCaseName); + } + + // execute method + result.set(component.executeTest()); + if (result.get().toString().equals("false")) { + s_logger.error("FAILURE!!! Test \"" + key + "\" failed\n\n\n"); + failure++; + } else { + finalResult = true; + s_logger.info("SUCCESS!!! Test \"" + key + "\" passed\n\n\n"); + } + + } catch (Exception ex) { + s_logger.error("error during test execution ", ex); + } + return finalResult; + } +} diff --git a/test/src/com/cloud/test/regression/VMApiTest.java b/test/src/com/cloud/test/regression/VMApiTest.java new file mode 100644 index 00000000000..db47df546b4 --- /dev/null +++ b/test/src/com/cloud/test/regression/VMApiTest.java @@ -0,0 +1,98 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.regression; + +import java.util.HashMap; + +import org.apache.log4j.Logger; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import com.cloud.test.regression.ApiCommand.ResponseType; + + +public class VMApiTest extends TestCase{ +public static final Logger s_logger = Logger.getLogger(VMApiTest.class.getName()); + + + public VMApiTest(){ + this.setClient(); + this.setParam(new HashMap()); + } + + public boolean executeTest(){ + int error=0; + Element rootElement = this.getInputFile().get(0).getDocumentElement(); + NodeList commandLst = rootElement.getElementsByTagName("command"); + + //Analyze each command, send request and build the array list of api commands + for (int i=0; i. + * + */ + +package com.cloud.test.stress; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import org.apache.log4j.Logger; + +import com.trilead.ssh2.Connection; +import com.trilead.ssh2.Session; + +public class SshTest { + + public static final Logger s_logger = Logger.getLogger(SshTest.class.getName()); + public static String host = ""; + public static String password = "password"; + public static String url = "http://google.com"; + + public static void main (String[] args) { + + // Parameters + List argsList = Arrays.asList(args); + Iterator iter = argsList.iterator(); + while (iter.hasNext()) { + String arg = iter.next(); + if (arg.equals("-h")) { + host = iter.next(); + } + if (arg.equals("-p")) { + password = iter.next(); + } + + if (arg.equals("-u")) { + url = iter.next(); + } + } + + if (host == null || host.equals("")) { + s_logger.info("Did not receive a host back from test, ignoring ssh test"); + System.exit(2); + } + + if (password == null){ + s_logger.info("Did not receive a password back from test, ignoring ssh test"); + System.exit(2); + } + + try { + s_logger.info("Attempting to SSH into host " + host); + Connection conn = new Connection(host); + conn.connect(null, 60000, 60000); + + s_logger.info("User + ssHed successfully into host " + host); + + boolean isAuthenticated = conn.authenticateWithPassword("root", password); + + if (isAuthenticated == false) { + s_logger.info("Authentication failed for root with password" + password); + System.exit(2); + } + + String linuxCommand = "wget " + url; + Session sess = conn.openSession(); + sess.execCommand(linuxCommand); + sess.close(); + conn.close(); + + } catch (Exception e) { + s_logger.error("SSH test fail with error", e); + System.exit(2); + } + } + +} diff --git a/test/src/com/cloud/test/stress/StressTestDirectAttach.java b/test/src/com/cloud/test/stress/StressTestDirectAttach.java new file mode 100644 index 00000000000..5ac21a02848 --- /dev/null +++ b/test/src/com/cloud/test/stress/StressTestDirectAttach.java @@ -0,0 +1,1531 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.stress; + +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; +import java.net.URLEncoder; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.log4j.Logger; +import org.apache.log4j.NDC; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + + +import com.cloud.utils.encoding.Base64; +import com.cloud.utils.exception.CloudRuntimeException; +import com.trilead.ssh2.ChannelCondition; +import com.trilead.ssh2.Connection; +import com.trilead.ssh2.SCPClient; +import com.trilead.ssh2.Session; + +public class StressTestDirectAttach { + private static long sleepTime = 180000L; // default 0 + private static boolean cleanUp = true; + public static final Logger s_logger = Logger + .getLogger(TestClientWithAPI.class.getName()); + private static boolean repeat = true; + private static String[] users = null; + private static boolean internet = false; + private static ThreadLocal _linuxIP = new ThreadLocal(); + private static ThreadLocal _linuxVmId = new ThreadLocal(); + private static ThreadLocal _linuxVmId1 = new ThreadLocal(); + private static ThreadLocal _linuxPassword = new ThreadLocal(); + private static ThreadLocal _windowsIP = new ThreadLocal(); + private static ThreadLocal _secretKey = new ThreadLocal(); + private static ThreadLocal _apiKey = new ThreadLocal(); + private static ThreadLocal _userId = new ThreadLocal(); + private static ThreadLocal _account = new ThreadLocal(); + private static ThreadLocal _domainRouterId = new ThreadLocal(); + private static ThreadLocal _newVolume = new ThreadLocal(); + private static ThreadLocal _newVolume1 = new ThreadLocal(); + private static DocumentBuilderFactory factory = DocumentBuilderFactory + .newInstance(); + private static int usageIterator = 1; + private static int numThreads = 1; + private static int wait = 5000; + private static String accountName = null; + private static String zoneId = "1"; + private static String serviceOfferingId = "13"; + private static String diskOfferingId="11"; + private static String diskOfferingId1="12"; + + private static final int MAX_RETRY_LINUX = 10; + private static final int MAX_RETRY_WIN = 10; + + + public static void main(String[] args) { + String host = "http://localhost"; + String port = "8092"; + String devPort = "8080"; + String apiUrl = "/client/api"; + + try { + // Parameters + List argsList = Arrays.asList(args); + Iterator iter = argsList.iterator(); + while (iter.hasNext()) { + String arg = iter.next(); + // host + if (arg.equals("-h")) { + host = "http://" + iter.next(); + } + + if (arg.equals("-p")) { + port = iter.next(); + } + if (arg.equals("-dp")) { + devPort = iter.next(); + } + + if (arg.equals("-t")) { + numThreads = Integer.parseInt(iter.next()); + } + + if (arg.equals("-s")) { + sleepTime = Long.parseLong(iter.next()); + } + if (arg.equals("-a")) { + accountName = iter.next(); + } + + if (arg.equals("-c")) { + cleanUp = Boolean.parseBoolean(iter.next()); + if (!cleanUp) + sleepTime = 0L; // no need to wait if we don't ever + // cleanup + } + + if (arg.equals("-r")) { + repeat = Boolean.parseBoolean(iter.next()); + } + + if (arg.equals("-i")) { + internet = Boolean.parseBoolean(iter.next()); + } + + if (arg.equals("-w")) { + wait = Integer.parseInt(iter.next()); + } + + if (arg.equals("-z")) { + zoneId = iter.next(); + } + + if (arg.equals("-so")) { + serviceOfferingId = iter.next(); + } + + } + + final String server = host + ":" + port + "/"; + final String developerServer = host + ":" + devPort + apiUrl; + s_logger.info("Starting test against server: " + server + " with " + + numThreads + " thread(s)"); + if (cleanUp) + s_logger.info("Clean up is enabled, each test will wait " + + sleepTime + " ms before cleaning up"); + + + + for (int i = 0; i < numThreads; i++) { + new Thread(new Runnable() { + public void run() { + do { + String username = null; + try { + long now = System.currentTimeMillis(); + Random ran = new Random(); + username = Math.abs(ran.nextInt())+ "-user"; + NDC.push(username); + + s_logger.info("Starting test for the user " + username); + int response = executeDeployment(server, + developerServer, username); + boolean success = false; + String reason = null; + + + + + if (response == 200) { + success = true; + if (internet) { + s_logger + .info("Deploy successful...waiting 5 minute before SSH tests"); + Thread.sleep(300000L); // Wait 60 + // seconds so + // the windows VM + // can boot up and do a sys prep. + + s_logger.info("Begin Linux SSH test for account " + _account.get()); + reason = sshTest(_linuxIP.get(), _linuxPassword.get()); + + + if (reason == null) { + s_logger + .info("Linux SSH test successful for account " + _account.get()); + } + } + if (reason == null) { + if (internet) { + s_logger + .info("Windows SSH test successful for account " + _account.get()); + } else { + s_logger + .info("deploy test successful....now cleaning up"); + if (cleanUp) { + s_logger + .info("Waiting " + + sleepTime + + " ms before cleaning up vms"); + Thread.sleep(sleepTime); + } else { + success = true; + } + } + + if (usageIterator >= numThreads) { + int eventsAndBillingResponseCode = + executeEventsAndBilling(server, developerServer); + s_logger.info("events and usage records command finished with response code: " + + eventsAndBillingResponseCode); + usageIterator = 1; + + } + else { + s_logger.info("Skipping events and usage records for this user: usageIterator " + usageIterator+ " and number of Threads " + numThreads); + usageIterator++; + } + + if ((users == null) && (accountName == null)) { + s_logger + .info("Sending cleanup command"); + int cleanupResponseCode = executeCleanup( + server, developerServer, username); + s_logger + .info("cleanup command finished with response code: " + + cleanupResponseCode); + success = (cleanupResponseCode == 200); + } else { + s_logger + .info("Sending stop DomR / destroy VM command"); + int stopResponseCode = executeStop( + server, developerServer, + username); + s_logger + .info("stop(destroy) command finished with response code: " + + stopResponseCode); + success = (stopResponseCode == 200); + } + + } else { + // Just stop but don't destroy the + // VMs/Routers + s_logger + .info("SSH test failed for account " + _account.get() + "with reason '" + + reason + + "', stopping VMs"); + int stopResponseCode = executeStop( + server, developerServer, + username); + s_logger + .info("stop command finished with response code: " + + stopResponseCode); + success = false; // since the SSH test + // failed, mark the + // whole test as + // failure + } + } else { + // Just stop but don't destroy the + // VMs/Routers + s_logger + .info("Deploy test failed with reason '" + + reason + + "', stopping VMs"); + int stopResponseCode = executeStop(server, + developerServer, username); + s_logger + .info("stop command finished with response code: " + + stopResponseCode); + success = false; // since the deploy test + // failed, mark the + // whole test as failure + } + + if (success) { + s_logger + .info("***** Completed test for user : " + + username + + " in " + + ((System + .currentTimeMillis() - now) / 1000L) + + " seconds"); + + } else { + s_logger + .info("##### FAILED test for user : " + + username + + " in " + + ((System + .currentTimeMillis() - now) / 1000L) + + " seconds with reason : " + + reason); + } + s_logger.info("Sleeping for " + wait + " seconds before starting next iteration"); + Thread.sleep(wait); + } catch (Exception e) { + s_logger.warn("Error in thread", e); + try { + int stopResponseCode = executeStop(server, + developerServer, username); + s_logger.info("stop response code: " + + stopResponseCode); + } catch (Exception e1) { + } + } finally { + NDC.clear(); + } + } while (repeat); + } + }).start(); + } + } catch (Exception e) { + s_logger.error(e); + } + } + + + public static Map> getMultipleValuesFromXML( + InputStream is, String[] tagNames) { + Map> returnValues = new HashMap>(); + try { + DocumentBuilder docBuilder = factory.newDocumentBuilder(); + Document doc = docBuilder.parse(is); + Element rootElement = doc.getDocumentElement(); + for (int i = 0; i < tagNames.length; i++) { + NodeList targetNodes = rootElement + .getElementsByTagName(tagNames[i]); + if (targetNodes.getLength() <= 0) { + s_logger.error("no " + tagNames[i] + + " tag in XML response...returning null"); + } else { + List valueList = new ArrayList(); + for (int j = 0; j < targetNodes.getLength(); j++) { + Node node = targetNodes.item(j); + valueList.add(node.getTextContent()); + } + returnValues.put(tagNames[i], valueList); + } + } + } catch (Exception ex) { + s_logger.error(ex); + } + return returnValues; + } + + public static Map getSingleValueFromXML(InputStream is, + String[] tagNames) { + Map returnValues = new HashMap(); + try { + DocumentBuilder docBuilder = factory.newDocumentBuilder(); + Document doc = docBuilder.parse(is); + Element rootElement = doc.getDocumentElement(); + + for (int i = 0; i < tagNames.length; i++) { + NodeList targetNodes = rootElement + .getElementsByTagName(tagNames[i]); + if (targetNodes.getLength() <= 0) { + s_logger.error("no " + tagNames[i] + + " tag in XML response...returning null"); + } else { + returnValues.put(tagNames[i], targetNodes.item(0) + .getTextContent()); + } + } + } catch (Exception ex) { + s_logger.error("error processing XML", ex); + } + return returnValues; + } + + public static Map getSingleValueFromXML(Element rootElement, + String[] tagNames) { + Map returnValues = new HashMap(); + if (rootElement == null) { + s_logger.error("Root element is null, can't get single value from xml"); + return null; + } + try { + for (int i = 0; i < tagNames.length; i++) { + NodeList targetNodes = rootElement + .getElementsByTagName(tagNames[i]); + if (targetNodes.getLength() <= 0) { + s_logger.error("no " + tagNames[i] + + " tag in XML response...returning null"); + } else { + returnValues.put(tagNames[i], targetNodes.item(0) + .getTextContent()); + } + } + } catch (Exception ex) { + s_logger.error("error processing XML", ex); + } + return returnValues; + } + + + private static List getNonSourceNatIPs(InputStream is) { + List returnValues = new ArrayList(); + try { + DocumentBuilder docBuilder = factory.newDocumentBuilder(); + Document doc = docBuilder.parse(is); + Element rootElement = doc.getDocumentElement(); + NodeList allocatedIpAddrNodes = rootElement + .getElementsByTagName("publicipaddress"); + for (int i = 0; i < allocatedIpAddrNodes.getLength(); i++) { + Node allocatedIpAddrNode = allocatedIpAddrNodes.item(i); + NodeList childNodes = allocatedIpAddrNode.getChildNodes(); + String ipAddress = null; + boolean isSourceNat = true; // assume it's source nat until we + // find otherwise + for (int j = 0; j < childNodes.getLength(); j++) { + Node n = childNodes.item(j); + if ("ipaddress".equals(n.getNodeName())) { + ipAddress = n.getTextContent(); + } else if ("issourcenat".equals(n.getNodeName())) { + isSourceNat = Boolean.parseBoolean(n.getTextContent()); + } + } + if ((ipAddress != null) && !isSourceNat) { + returnValues.add(ipAddress); + } + } + } catch (Exception ex) { + s_logger.error(ex); + } + return returnValues; + } + + private static List getSourceNatIPs(InputStream is) { + List returnValues = new ArrayList(); + try { + DocumentBuilder docBuilder = factory.newDocumentBuilder(); + Document doc = docBuilder.parse(is); + Element rootElement = doc.getDocumentElement(); + NodeList allocatedIpAddrNodes = rootElement + .getElementsByTagName("publicipaddress"); + for (int i = 0; i < allocatedIpAddrNodes.getLength(); i++) { + Node allocatedIpAddrNode = allocatedIpAddrNodes.item(i); + NodeList childNodes = allocatedIpAddrNode.getChildNodes(); + String ipAddress = null; + boolean isSourceNat = false; // assume it's *not* source nat until we find otherwise + for (int j = 0; j < childNodes.getLength(); j++) { + Node n = childNodes.item(j); + if ("ipaddress".equals(n.getNodeName())) { + ipAddress = n.getTextContent(); + } else if ("issourcenat".equals(n.getNodeName())) { + isSourceNat = Boolean.parseBoolean(n.getTextContent()); + } + } + if ((ipAddress != null) && isSourceNat) { + returnValues.add(ipAddress); + } + } + } catch (Exception ex) { + s_logger.error(ex); + } + return returnValues; + } + + private static String executeRegistration(String server, String username, + String password) throws HttpException, IOException { + String url = server + "?command=registerUserKeys&id=" + _userId.get().toString(); + s_logger.info("registering: " + username); + String returnValue = null; + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + int responseCode = client.executeMethod(method); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map requestKeyValues = getSingleValueFromXML(is, + new String[] { "apikey", "secretkey" }); + _apiKey.set(requestKeyValues.get("apikey")); + returnValue = requestKeyValues.get("secretkey"); + } else { + s_logger.error("registration failed with error code: " + responseCode); + } + return returnValue; + } + + private static Integer executeDeployment(String server, String developerServer, + String username) throws HttpException, IOException { + // test steps: + // - create user + // - deploy Windows VM + // - deploy Linux VM + // - associate IP address + // - create two IP forwarding rules + // - create load balancer rule + // - list IP forwarding rules + // - list load balancer rules + + // ----------------------------- + // CREATE USER + // ----------------------------- + String encodedUsername = URLEncoder.encode(username, "UTF-8"); + String encryptedPassword = createMD5Password(username); + String encodedPassword = URLEncoder.encode(encryptedPassword, "UTF-8"); + + String url = server + "?command=createUser&username=" + encodedUsername + + "&password=" + encodedPassword + + "&firstname=Test&lastname=Test&email=test@vmops.com&domainId=1&accounttype=0"; + if (accountName != null ) { + url = server + "?command=createUser&username=" + encodedUsername + + "&password=" + encodedPassword + + "&firstname=Test&lastname=Test&email=test@vmops.com&domainId=1&accounttype=0&account=" + accountName; + } + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + int responseCode = client.executeMethod(method); + long userId = -1; + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map userIdValues = getSingleValueFromXML(is, + new String[] { "id", "account" }); + String userIdStr = userIdValues.get("id"); + s_logger.info("created user " + username + " with id "+ userIdStr); + if (userIdStr != null) { + userId = Long.parseLong(userIdStr); + _userId.set(userId); + _account.set(userIdValues.get("account")); + if (userId == -1) { + s_logger + .error("create user (" + username + ") failed to retrieve a valid user id, aborting depolyment test"); + return -1; + } + } + } else { + s_logger.error("create user test failed for user " + username + " with error code :" + responseCode); + return responseCode; + } + + _secretKey.set(executeRegistration(server, username, username)); + + if (_secretKey.get() == null) { + s_logger + .error("FAILED to retrieve secret key during registration, skipping user: " + + username); + return -1; + } else { + s_logger.info("got secret key: " + _secretKey.get()); + s_logger.info("got api key: " + _apiKey.get()); + } + + + // --------------------------------- + // CREATE NETWORK GROUP AND ADD INGRESS RULE TO IT + // --------------------------------- + String networkAccount = null; + if (accountName != null) { + networkAccount = accountName; + } + else { + networkAccount = encodedUsername; + } + String encodedApiKey = URLEncoder.encode(_apiKey.get(), "UTF-8"); + String requestToSign = "apikey=" + encodedApiKey + + "&command=createSecurityGroup&name=" + encodedUsername; + requestToSign = requestToSign.toLowerCase(); + String signature = signRequest(requestToSign, _secretKey.get()); + String encodedSignature = URLEncoder.encode(signature, "UTF-8"); + url = developerServer + "?command=createSecurityGroup&name=" + encodedUsername + "&apikey=" + encodedApiKey + + "&signature=" + encodedSignature; + method = new GetMethod(url); + responseCode = client.executeMethod(method); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map values = getSingleValueFromXML(is, + new String[] { "id" }); + + if (values.get("id") == null) { + s_logger.info("Create network rule response code: 401"); + return 401; + } + else { + s_logger.info("Create security group response code: " + responseCode); + } + } else { + s_logger.error("Create security group failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + + String encodedCidr = URLEncoder.encode("192.168.1.143/32", "UTF-8"); + url = server + "?command=authorizeSecurityGroupIngress&cidrlist=" + encodedCidr + "&endport=22&" + + "securitygroupname=" + encodedUsername +"&protocol=tcp&startport=22&account=" + networkAccount + "&domainid=1"; + + method = new GetMethod(url); + responseCode = client.executeMethod(method); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + Map values = getSingleValueFromXML(el, + new String[] { "id" }); + + if (values.get("id") == null) { + s_logger.info("Authorise security group ingress response code: 401"); + return 401; + } + else { + s_logger.info("Authorise security group ingress response code: " + responseCode); + } + } else { + s_logger.error("Authorise security group ingress failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + + + // --------------------------------- + // DEPLOY LINUX VM + // --------------------------------- + { + long templateId = 2; + String encodedZoneId = URLEncoder.encode("" + zoneId, "UTF-8"); + String encodedServiceOfferingId = URLEncoder.encode("" + + serviceOfferingId, "UTF-8"); + String encodedTemplateId = URLEncoder.encode("" + templateId, + "UTF-8"); + encodedApiKey = URLEncoder.encode(_apiKey.get(), "UTF-8"); + requestToSign = "apikey=" + encodedApiKey + + "&command=deployVirtualMachine&securitygrouplist=" + encodedUsername + "&serviceofferingid=" + + encodedServiceOfferingId + "&templateid=" + + encodedTemplateId + "&zoneid=" + encodedZoneId; + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + url = developerServer + "?command=deployVirtualMachine&securitygrouplist=" + encodedUsername + "&zoneid=" + encodedZoneId + "&serviceofferingid=" + + encodedServiceOfferingId + "&templateid=" + + encodedTemplateId + "&apikey=" + encodedApiKey + + "&signature=" + encodedSignature; + + method = new GetMethod(url); + responseCode = client.executeMethod(method); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + Map values = getSingleValueFromXML(el, + new String[] { "id", "ipaddress" }); + + if ((values.get("ipaddress") == null) || (values + .get("id") == null)) { + s_logger.info("deploy linux vm response code: 401"); + return 401; + } + else { + s_logger.info("deploy linux vm response code: " + responseCode); + long linuxVMId = Long.parseLong(values.get("id")); + s_logger.info("got linux virtual machine id: " + linuxVMId); + _linuxVmId.set(values.get("id")); + _linuxIP.set(values.get("ipaddress")); + _linuxPassword.set("rs-ccb35ea5"); + } + } else { + s_logger.error("deploy linux vm failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + + + + //Create a new volume + { + url = server + "?command=createVolume&diskofferingid=" + diskOfferingId + "&zoneid=" + zoneId + "&name=newvolume&account=" + _account.get() + "&domainid=1"; + s_logger.info("Creating volume...."); + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + Map values = getSingleValueFromXML(el, + new String[] { "id" }); + + if (values.get("id") == null) { + s_logger.info("create volume response code: 401"); + return 401; + } + else { + s_logger.info("create volume response code: " + responseCode); + String volumeId = values.get("id"); + s_logger.info("got volume id: " + volumeId); + _newVolume.set(volumeId); + } + } else { + s_logger.error("create volume failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + + //attach a new volume to the vm + { + url = server + "?command=attachVolume&id=" + _newVolume.get() + "&virtualmachineid=" + _linuxVmId.get(); + s_logger.info("Attaching volume with id " + _newVolume.get() + " to the vm " + _linuxVmId.get()); + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("Attach data volume response code: " + responseCode); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + Map values = getSingleValueFromXML(el, + new String[] { "id" }); + + if (values.get("id") == null) { + s_logger.info("Attach volume response code: 401"); + return 401; + } + else { + s_logger.info("Attach volume response code: " + responseCode); + } + } else { + s_logger.error("Attach volume failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + + //DEPLOY SECOND VM, ADD VOLUME TO IT + + // --------------------------------- + // DEPLOY another linux vm + // --------------------------------- + { + long templateId = 2; + String encodedZoneId = URLEncoder.encode("" + zoneId, "UTF-8"); + String encodedServiceOfferingId = URLEncoder.encode("" + + serviceOfferingId, "UTF-8"); + String encodedTemplateId = URLEncoder.encode("" + templateId, + "UTF-8"); + encodedApiKey = URLEncoder.encode(_apiKey.get(), "UTF-8"); + requestToSign = "apikey=" + encodedApiKey + + "&command=deployVirtualMachine&securitygrouplist=" + encodedUsername + "&serviceofferingid=" + + encodedServiceOfferingId + "&templateid=" + + encodedTemplateId + "&zoneid=" + encodedZoneId; + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + url = developerServer + "?command=deployVirtualMachine&securitygrouplist=" + encodedUsername + "&zoneid=" + encodedZoneId + "&serviceofferingid=" + + encodedServiceOfferingId + "&templateid=" + + encodedTemplateId + "&apikey=" + encodedApiKey + + "&signature=" + encodedSignature; + + method = new GetMethod(url); + responseCode = client.executeMethod(method); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + Map values = getSingleValueFromXML(el, + new String[] { "id", "ipaddress" }); + + if ((values.get("ipaddress") == null) || (values + .get("id") == null)) { + s_logger.info("deploy linux vm response code: 401"); + return 401; + } + else { + s_logger.info("deploy linux vm response code: " + responseCode); + long linuxVMId = Long.parseLong(values.get("id")); + s_logger.info("got linux virtual machine id: " + linuxVMId); + _linuxVmId1.set(values.get("id")); + } + } else { + s_logger.error("deploy linux vm failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + + + + //Create a new volume + { + url = server + "?command=createVolume&diskofferingid=" + diskOfferingId1 + "&zoneid=" + zoneId + "&name=newvolume1&account=" + _account.get() + "&domainid=1"; + s_logger.info("Creating volume...."); + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + Map values = getSingleValueFromXML(el, + new String[] { "id" }); + + if (values.get("id") == null) { + s_logger.info("create volume response code: 401"); + return 401; + } + else { + s_logger.info("create volume response code: " + responseCode); + String volumeId = values.get("id"); + s_logger.info("got volume id: " + volumeId); + _newVolume1.set(volumeId); + } + } else { + s_logger.error("create volume failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + + //attach a new volume to the vm + { + url = server + "?command=attachVolume&id=" + _newVolume1.get() + "&virtualmachineid=" + _linuxVmId1.get(); + s_logger.info("Attaching volume with id " + _newVolume1.get() + " to the vm " + _linuxVmId1.get()); + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("Attach data volume response code: " + responseCode); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + Map values = getSingleValueFromXML(el, + new String[] { "id" }); + + if (values.get("id") == null) { + s_logger.info("Attach volume response code: 401"); + return 401; + } + else { + s_logger.info("Attach volume response code: " + responseCode); + } + } else { + s_logger.error("Attach volume failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + return 200; + } + + + + + private static int executeCleanup(String server, String developerServer, String username) + throws HttpException, IOException { + // test steps: + // - get user + // - delete user + + // ----------------------------- + // GET USER + // ----------------------------- + String userId = _userId.get().toString(); + String encodedUserId = URLEncoder.encode(userId, "UTF-8"); + String url = server + "?command=listUsers&id=" + encodedUserId; + s_logger.info("Cleaning up resources for user: " + userId + " with url " + url); + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + int responseCode = client.executeMethod(method); + s_logger.info("get user response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map userInfo = getSingleValueFromXML(is, + new String[] { "username", "id", "account" }); + if (!username.equals(userInfo.get("username"))) { + s_logger + .error("get user failed to retrieve requested user, aborting cleanup test" + ". Following URL was sent: " + url); + return -1; + } + + } else { + s_logger.error("get user failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + // ----------------------------- + // UPDATE USER + // ----------------------------- + { + url = server + "?command=updateUser&id=" + userId + + "&firstname=delete&lastname=me"; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("update user response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map success = getSingleValueFromXML(is, + new String[] { "success" }); + s_logger + .info("update user..success? " + success.get("success")); + } else { + s_logger.error("update user failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + + // ----------------------------- + // Execute reboot/stop/start commands for the VMs before deleting the account - made to exercise xen + // ----------------------------- + + //Reboot centos VM + String encodedApiKey = URLEncoder.encode(_apiKey.get(), "UTF-8"); + String requestToSign = "apikey=" + encodedApiKey + "&command=rebootVirtualMachine&id=" + _linuxVmId.get(); + requestToSign = requestToSign.toLowerCase(); + String signature = signRequest(requestToSign, _secretKey.get()); + String encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=rebootVirtualMachine&id=" + _linuxVmId.get() + "&apikey=" + + encodedApiKey + "&signature=" + encodedSignature; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("Reboot VM response code: " + + responseCode); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + Map success = getSingleValueFromXML(el, + new String[] { "success" }); + s_logger.info("VM was rebooted with the status: " + + success.get("success")); + } else { + s_logger.error(" VM test failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + //Stop centos VM + requestToSign = "apikey=" + encodedApiKey + "&command=stopVirtualMachine&id=" + _linuxVmId.get(); + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=stopVirtualMachine&id=" + _linuxVmId.get() + "&apikey=" + + encodedApiKey + "&signature=" + encodedSignature; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("Stop VM response code: " + + responseCode); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + Map success = getSingleValueFromXML(el, + new String[] { "success" }); + s_logger.info("VM was stopped with the status: " + + success.get("success")); + } else { + s_logger.error("Stop VM test failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + //Start centos VM + requestToSign = "apikey=" + encodedApiKey + "&command=startVirtualMachine&id=" + _linuxVmId.get(); + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=startVirtualMachine&id=" + _linuxVmId.get() + "&apikey=" + + encodedApiKey + "&signature=" + encodedSignature; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("Start VM response code: " + + responseCode); + + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + Map success = getSingleValueFromXML(el, + new String[] { "id" }); + + if (success.get("id") == null) { + s_logger.info("Start linux vm response code: 401"); + return 401; + } + else { + s_logger.info("Start vm response code: " + responseCode); + } + + s_logger.info("VM was started with the status: " + + success.get("success")); + } else { + s_logger.error("Start VM test failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + +//// // ----------------------------- +//// // DISABLE USER +//// // ----------------------------- +// { +// url = server + "?command=disableUser&id=" + userId; +// client = new HttpClient(); +// method = new GetMethod(url); +// responseCode = client.executeMethod(method); +// s_logger.info("disable user response code: " + responseCode); +// if (responseCode == 200) { +// InputStream input = method.getResponseBodyAsStream(); +// Element el = queryAsyncJobResult(server, input); +// s_logger +// .info("Disabled user successfully"); +// } else { +// s_logger.error("disable user failed with error code: " + responseCode + ". Following URL was sent: " + url); +// return responseCode; +// } +// } + + // ----------------------------- + // DELETE USER + // ----------------------------- + { + url = server + "?command=deleteUser&id=" + userId; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("delete user response code: " + responseCode); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + s_logger + .info("Deleted user successfully"); + } else { + s_logger.error("delete user failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + return responseCode; + } + + private static int executeEventsAndBilling(String server, String developerServer) + throws HttpException, IOException { + // test steps: + // - get all the events in the system for all users in the system + // - generate all the usage records in the system + // - get all the usage records in the system + + // ----------------------------- + // GET EVENTS + // ----------------------------- + String url =server+"?command=listEvents&page=1&account=" + _account.get(); + + s_logger.info("Getting events for the account " + _account.get()); + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + int responseCode = client.executeMethod(method); + s_logger.info("get events response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map> eventDescriptions = getMultipleValuesFromXML( + is, new String[] { "description" }); + List descriptionText = eventDescriptions.get("description"); + if (descriptionText == null) { + s_logger.info("no events retrieved..."); + } else { + for (String text : descriptionText) { + s_logger.info("event: " + text); + } + } + } else { + s_logger.error("list events failed with error code: " + responseCode + ". Following URL was sent: " + url); + + return responseCode; + } + return responseCode; + } + + + private static int executeStop(String server, String developerServer, + String username) throws HttpException, IOException { + // test steps: + // - get userId for the given username + // - list virtual machines for the user + // - stop all virtual machines + // - get ip addresses for the user + // - release ip addresses + + // ----------------------------- + // GET USER + // ----------------------------- + String userId = _userId.get().toString(); + String encodedUserId = URLEncoder.encode(userId, "UTF-8"); + + String url = server + "?command=listUsers&id=" + encodedUserId; + s_logger.info("Stopping resources for user: " + username); + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + int responseCode = client.executeMethod(method); + s_logger.info("get user response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map userIdValues = getSingleValueFromXML(is, + new String[] { "id" }); + String userIdStr = userIdValues.get("id"); + if (userIdStr != null) { + userId = userIdStr; + if (userId == null) { + s_logger + .error("get user failed to retrieve a valid user id, aborting depolyment test" + ". Following URL was sent: " + url); + return -1; + } + } + } else { + s_logger.error("get user failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + { + // ---------------------------------- + // LIST VIRTUAL MACHINES + // ---------------------------------- + String encodedApiKey = URLEncoder.encode(_apiKey.get(), "UTF-8"); + String requestToSign = "apikey=" + encodedApiKey + + "&command=listVirtualMachines"; + requestToSign = requestToSign.toLowerCase(); + String signature = signRequest(requestToSign, _secretKey.get()); + String encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=listVirtualMachines&apikey=" + encodedApiKey + "&signature=" + + encodedSignature; + + s_logger.info("Listing all virtual machines for the user with url " + url); + String[] vmIds = null; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("list virtual machines response code: " + + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map> vmIdValues = getMultipleValuesFromXML( + is, new String[] { "id" }); + if (vmIdValues.containsKey("id")) { + List vmIdList = vmIdValues.get("id"); + if (vmIdList != null) { + vmIds = new String[vmIdList.size()]; + vmIdList.toArray(vmIds); + String vmIdLogStr = ""; + if ((vmIds != null) && (vmIds.length > 0)) { + vmIdLogStr = vmIds[0]; + for (int i = 1; i < vmIds.length; i++) { + vmIdLogStr = vmIdLogStr + "," + vmIds[i]; + } + } + s_logger.info("got virtual machine ids: " + vmIdLogStr); + } + } + + + } else { + s_logger.error("list virtual machines test failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + + // ---------------------------------- + // STOP/DESTROY VIRTUAL MACHINES + // ---------------------------------- + if (vmIds != null) { + for (String vmId : vmIds) { + requestToSign = "apikey=" + encodedApiKey + "&command=stopVirtualMachine&id=" + vmId; + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=stopVirtualMachine&id=" + vmId + "&apikey=" + + encodedApiKey + "&signature=" + encodedSignature; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("StopVirtualMachine" + " [" + vmId + "] response code: " + + responseCode); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + Map success = getSingleValueFromXML(el, + new String[] { "success" }); + s_logger.info("StopVirtualMachine..success? " + + success.get("success")); + } else { + s_logger.error("Stop virtual machine test failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + } + +// { +// url = server + "?command=deleteUser&id=" + userId; +// client = new HttpClient(); +// method = new GetMethod(url); +// responseCode = client.executeMethod(method); +// s_logger.info("delete user response code: " + responseCode); +// if (responseCode == 200) { +// InputStream input = method.getResponseBodyAsStream(); +// Element el = queryAsyncJobResult(server, input); +// s_logger +// .info("Deleted user successfully"); +// } else { +// s_logger.error("delete user failed with error code: " + responseCode + ". Following URL was sent: " + url); +// return responseCode; +// } +// } + + + } + + _linuxIP.set(""); + _linuxVmId.set(""); + _linuxPassword.set(""); + _windowsIP.set(""); + _secretKey.set(""); + _apiKey.set(""); + _userId.set(Long.parseLong("0")); + _account.set(""); + _domainRouterId.set(""); + return responseCode; + } + + public static String signRequest(String request, String key) { + try { + Mac mac = Mac.getInstance("HmacSHA1"); + SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), + "HmacSHA1"); + mac.init(keySpec); + mac.update(request.getBytes()); + byte[] encryptedBytes = mac.doFinal(); + return Base64.encodeBytes(encryptedBytes); + } catch (Exception ex) { + s_logger.error("unable to sign request", ex); + } + return null; + } + + private static String sshWinTest(String host) { + if (host == null) { + s_logger + .info("Did not receive a host back from test, ignoring win ssh test"); + return null; + } + + // We will retry 5 times before quitting + int retry = 1; + + while (true) { + try { + if (retry > 0) { + s_logger.info("Retry attempt : " + retry + + " ...sleeping 300 seconds before next attempt. Account is " + _account.get()); + Thread.sleep(300000); + } + + s_logger.info("Attempting to SSH into windows host " + host + + " with retry attempt: " + retry + " for account " + _account.get()); + + Connection conn = new Connection(host); + conn.connect(null, 60000, 60000); + + s_logger.info("User " + _account.get() + " ssHed successfully into windows host " + host); + boolean success = false; + boolean isAuthenticated = conn.authenticateWithPassword( + "Administrator", "password"); + if (isAuthenticated == false) { + return "Authentication failed"; + } + else { + s_logger.info("Authentication is successfull"); + } + + try { + SCPClient scp = new SCPClient(conn); + scp.put("wget.exe", "wget.exe", "C:\\Users\\Administrator", "0777"); + s_logger.info("Successfully put wget.exe file"); + } catch (Exception ex) { + s_logger.error("Unable to put wget.exe " + ex); + } + + if (conn == null ){ + s_logger.error("Connection is null"); + } + Session sess = conn.openSession(); + + s_logger.info("User + " + _account.get() + " executing : wget http://192.168.1.250/dump.bin"); + sess + .execCommand("wget http://192.168.1.250/dump.bin && dir dump.bin"); + + InputStream stdout = sess.getStdout(); + InputStream stderr = sess.getStderr(); + + byte[] buffer = new byte[8192]; + while (true) { + if ((stdout.available() == 0) && (stderr.available() == 0)) { + int conditions = sess.waitForCondition( + ChannelCondition.STDOUT_DATA + | ChannelCondition.STDERR_DATA + | ChannelCondition.EOF, 120000); + + if ((conditions & ChannelCondition.TIMEOUT) != 0) { + s_logger + .info("Timeout while waiting for data from peer."); + return null; + } + + if ((conditions & ChannelCondition.EOF) != 0) { + if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) { + break; + } + } + } + + while (stdout.available() > 0) { + success = true; + int len = stdout.read(buffer); + if (len > 0) // this check is somewhat paranoid + s_logger.info(new String(buffer, 0, len)); + } + + while (stderr.available() > 0) { + /* int len = */stderr.read(buffer); + } + } + sess.close(); + conn.close(); + + if (success) { + Thread.sleep(120000); + return null; + } else { + retry++; + if (retry == MAX_RETRY_WIN) { + return "SSH Windows Network test fail for account " + _account.get(); + } + } + } catch (Exception e) { + s_logger.error(e); + retry++; + if (retry == MAX_RETRY_WIN) { + return "SSH Windows Network test fail with error " + + e.getMessage(); + } + } + } + } + + private static String sshTest(String host, String password) { + int i = 0; + if (host == null) { + s_logger + .info("Did not receive a host back from test, ignoring ssh test"); + return null; + } + + if (password == null){ + s_logger.info("Did not receive a password back from test, ignoring ssh test"); + return null; + } + + // We will retry 5 times before quitting + String result = null; + int retry = 0; + + while (true) { + try { + if (retry > 0) { + s_logger.info("Retry attempt : " + retry + + " ...sleeping 120 seconds before next attempt. Account is " + _account.get()); + Thread.sleep(120000); + } + + s_logger.info("Attempting to SSH into linux host " + host + + " with retry attempt: " + retry + ". Account is " + _account.get()); + + Connection conn = new Connection(host); + conn.connect(null, 60000, 60000); + + s_logger.info("User + " + _account.get() + " ssHed successfully into linux host " + host); + + boolean isAuthenticated = conn.authenticateWithPassword("root", + password); + + if (isAuthenticated == false) { + s_logger.info("Authentication failed for root with password" + password); + return "Authentication failed"; + + } + + boolean success = false; + String linuxCommand = null; + + if (i % 10 == 0) + linuxCommand = "rm -rf *; wget http://192.168.1.250/dump.bin && ls -al dump.bin"; + else + linuxCommand = "wget http://192.168.1.250/dump.bin && ls -al dump.bin"; + + Session sess = conn.openSession(); + s_logger.info("User " + _account.get() + " executing : " + linuxCommand); + sess.execCommand(linuxCommand); + + InputStream stdout = sess.getStdout(); + InputStream stderr = sess.getStderr(); + + + byte[] buffer = new byte[8192]; + while (true) { + if ((stdout.available() == 0) && (stderr.available() == 0)) { + int conditions = sess.waitForCondition( + ChannelCondition.STDOUT_DATA + | ChannelCondition.STDERR_DATA + | ChannelCondition.EOF, 120000); + + if ((conditions & ChannelCondition.TIMEOUT) != 0) { + s_logger + .info("Timeout while waiting for data from peer."); + return null; + } + + if ((conditions & ChannelCondition.EOF) != 0) { + if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) { + break; + } + } + } + + while (stdout.available() > 0) { + success = true; + int len = stdout.read(buffer); + if (len > 0) // this check is somewhat paranoid + s_logger.info(new String(buffer, 0, len)); + } + + while (stderr.available() > 0) { + /* int len = */stderr.read(buffer); + } + } + + sess.close(); + conn.close(); + + if (!success) { + retry++; + if (retry == MAX_RETRY_LINUX) { + result = "SSH Linux Network test fail"; + } + } + + return result; + } catch (Exception e) { + retry++; + s_logger.error("SSH Linux Network test fail with error"); + if (retry == MAX_RETRY_LINUX) { + return "SSH Linux Network test fail with error " + + e.getMessage(); + } + } + i++; + } + } + + public static String createMD5Password(String password) { + MessageDigest md5; + + try { + md5 = MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException e) { + throw new CloudRuntimeException("Error", e); + } + + md5.reset(); + BigInteger pwInt = new BigInteger(1, md5.digest(password.getBytes())); + + // make sure our MD5 hash value is 32 digits long... + StringBuffer sb = new StringBuffer(); + String pwStr = pwInt.toString(16); + int padding = 32 - pwStr.length(); + for (int i = 0; i < padding; i++) { + sb.append('0'); + } + sb.append(pwStr); + return sb.toString(); + } + + + public static Element queryAsyncJobResult (String host, InputStream inputStream) { + Element returnBody = null; + + Map values = getSingleValueFromXML(inputStream, + new String[] { "jobid" }); + String jobId = values.get("jobid"); + + if (jobId == null) { + s_logger.error("Unable to get a jobId"); + return null; + } + + //s_logger.info("Job id is " + jobId); + String resultUrl = host + "?command=queryAsyncJobResult&jobid=" + jobId; + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(resultUrl); + while (true) { + try { + client.executeMethod(method); + //s_logger.info("Method is executed successfully. Following url was sent " + resultUrl); + InputStream is = method.getResponseBodyAsStream(); + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document doc = builder.parse(is); + returnBody = doc.getDocumentElement(); + doc.getDocumentElement().normalize(); + Element jobStatusTag = (Element) returnBody.getElementsByTagName("jobstatus").item(0); + String jobStatus = jobStatusTag.getTextContent(); + if(jobStatus.equals("0")) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + } else { + break; + } + + } catch (Exception ex) { + s_logger.error(ex); + } + } + return returnBody; + } + +} diff --git a/test/src/com/cloud/test/stress/TestClientWithAPI.java b/test/src/com/cloud/test/stress/TestClientWithAPI.java new file mode 100644 index 00000000000..80f01b27583 --- /dev/null +++ b/test/src/com/cloud/test/stress/TestClientWithAPI.java @@ -0,0 +1,2265 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.stress; + +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; +import java.net.URLEncoder; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.log4j.Logger; +import org.apache.log4j.NDC; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import com.cloud.utils.encoding.Base64; +import com.cloud.utils.exception.CloudRuntimeException; +import com.trilead.ssh2.ChannelCondition; +import com.trilead.ssh2.Connection; +import com.trilead.ssh2.SCPClient; +import com.trilead.ssh2.Session; + +public class TestClientWithAPI { + private static long sleepTime = 180000L; // default 0 + private static boolean cleanUp = true; + public static final Logger s_logger = Logger.getLogger(TestClientWithAPI.class); + private static boolean repeat = true; + private static int numOfUsers = 0; + private static String[] users = null; + private static boolean internet = false; + private static ThreadLocal _linuxIP = new ThreadLocal(); + private static ThreadLocal _linuxIpId = new ThreadLocal(); + private static ThreadLocal _linuxVmId = new ThreadLocal(); + private static ThreadLocal _linuxPassword = new ThreadLocal(); + private static ThreadLocal _windowsIP = new ThreadLocal(); + private static ThreadLocal _windowsIpId = new ThreadLocal(); + private static ThreadLocal _windowsVmId = new ThreadLocal(); + private static ThreadLocal _secretKey = new ThreadLocal(); + private static ThreadLocal _apiKey = new ThreadLocal(); + private static ThreadLocal _userId = new ThreadLocal(); + private static ThreadLocal _accountId = new ThreadLocal(); + private static ThreadLocal _account = new ThreadLocal(); + private static ThreadLocal _domainRouterId = new ThreadLocal(); + private static ThreadLocal _pfGroupId = new ThreadLocal(); + private static ThreadLocal _windowsLb = new ThreadLocal(); + private static ThreadLocal _linuxLb = new ThreadLocal(); + private static ThreadLocal _dataVolume = new ThreadLocal(); + private static ThreadLocal _rootVolume = new ThreadLocal(); + private static ThreadLocal _newVolume = new ThreadLocal(); + private static ThreadLocal _snapshot = new ThreadLocal(); + private static ThreadLocal _volumeFromSnapshot = new ThreadLocal(); + private static ThreadLocal _networkId = new ThreadLocal(); + private static ThreadLocal _publicIpId = new ThreadLocal(); + private static ThreadLocal _winipfwdid = new ThreadLocal(); + private static ThreadLocal _linipfwdid = new ThreadLocal(); + private static DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + private static int usageIterator = 1; + private static int numThreads = 1; + private static int wait = 5000; + private static String accountName = null; + private static String zoneId = "1"; + private static String snapshot_test = "no"; + private static String serviceOfferingId = "1"; + private static String diskOfferingId = "4"; + private static String networkOfferingId = "6"; + private static String vmPassword = "rs-ccb35ea5"; + private static String downloadUrl = "192.168.1.250/dump.bin"; + + private static final int MAX_RETRY_LINUX = 10; + private static final int MAX_RETRY_WIN = 10; + + public static void main(String[] args) { + String host = "http://localhost"; + String port = "8092"; + String devPort = "8080"; + String apiUrl = "/client/api"; + + try { + // Parameters + List argsList = Arrays.asList(args); + Iterator iter = argsList.iterator(); + while (iter.hasNext()) { + String arg = iter.next(); + // host + if (arg.equals("-h")) { + host = "http://" + iter.next(); + } + + if (arg.equals("-p")) { + port = iter.next(); + } + if (arg.equals("-dp")) { + devPort = iter.next(); + } + + if (arg.equals("-t")) { + numThreads = Integer.parseInt(iter.next()); + } + + if (arg.equals("-s")) { + sleepTime = Long.parseLong(iter.next()); + } + if (arg.equals("-a")) { + accountName = iter.next(); + } + + if (arg.equals("-c")) { + cleanUp = Boolean.parseBoolean(iter.next()); + if (!cleanUp) + sleepTime = 0L; // no need to wait if we don't ever + // cleanup + } + + if (arg.equals("-r")) { + repeat = Boolean.parseBoolean(iter.next()); + } + + if (arg.equals("-u")) { + numOfUsers = Integer.parseInt(iter.next()); + } + + if (arg.equals("-i")) { + internet = Boolean.parseBoolean(iter.next()); + } + + if (arg.equals("-w")) { + wait = Integer.parseInt(iter.next()); + } + + if (arg.equals("-z")) { + zoneId = iter.next(); + } + + if (arg.equals("-snapshot")) { + snapshot_test = "yes"; + } + + if (arg.equals("-so")) { + serviceOfferingId = iter.next(); + } + + if (arg.equals("-do")) { + diskOfferingId = iter.next(); + } + + if (arg.equals("-no")) { + networkOfferingId = iter.next(); + } + + if (arg.equals("-pass")) { + vmPassword = iter.next(); + } + + if (arg.equals("-url")) { + downloadUrl = iter.next(); + } + + } + + final String server = host + ":" + port + "/"; + final String developerServer = host + ":" + devPort + apiUrl; + s_logger.info("Starting test against server: " + server + " with " + numThreads + " thread(s)"); + if (cleanUp) + s_logger.info("Clean up is enabled, each test will wait " + sleepTime + " ms before cleaning up"); + + if (numOfUsers > 0) { + s_logger.info("Pre-generating users for test of size : " + numOfUsers); + users = new String[numOfUsers]; + Random ran = new Random(); + for (int i = 0; i < numOfUsers; i++) { + users[i] = Math.abs(ran.nextInt()) + "-user"; + } + } + + for (int i = 0; i < numThreads; i++) { + new Thread(new Runnable() { + public void run() { + do { + String username = null; + try { + long now = System.currentTimeMillis(); + Random ran = new Random(); + if (users != null) { + username = users[Math.abs(ran.nextInt()) % numOfUsers]; + } else { + username = Math.abs(ran.nextInt()) + "-user"; + } + NDC.push(username); + + s_logger.info("Starting test for the user " + username); + int response = executeDeployment(server, developerServer, username, snapshot_test); + boolean success = false; + String reason = null; + + if (response == 200) { + success = true; + if (internet) { + s_logger.info("Deploy successful...waiting 5 minute before SSH tests"); + Thread.sleep(300000L); // Wait 60 + // seconds so + // the windows VM + // can boot up and do a sys prep. + + if (accountName == null) { + s_logger.info("Begin Linux SSH test for account " + _account.get()); + reason = sshTest(_linuxIP.get(), _linuxPassword.get(), snapshot_test); + } + + if (reason == null) { + s_logger.info("Linux SSH test successful for account " + _account.get()); + s_logger.info("Begin WindowsSSH test for account " + _account.get()); + + reason = sshTest(_linuxIP.get(), _linuxPassword.get(), snapshot_test); + // reason = sshWinTest(_windowsIP.get()); + } + + // release the linux IP now... + _linuxIP.set(null); + // release the Windows IP now + _windowsIP.set(null); + } + + // sleep for 3 min before getting the latest network stat + // s_logger.info("Sleeping for 5 min before getting the lates network stat for the account"); + // Thread.sleep(300000); + // verify that network stat is correct for the user; if it's not - stop all the resources + // for the user + // if ((reason == null) && (getNetworkStat(server) == false) ) { + // s_logger.error("Stopping all the resources for the account " + _account.get() + + // " as network stat is incorrect"); + // int stopResponseCode = executeStop( + // server, developerServer, + // username, false); + // s_logger + // .info("stop command finished with response code: " + // + stopResponseCode); + // success = false; // since the SSH test + // + // } else + if (reason == null) { + if (internet) { + s_logger.info("Windows SSH test successful for account " + _account.get()); + } else { + s_logger.info("deploy test successful....now cleaning up"); + if (cleanUp) { + s_logger.info("Waiting " + sleepTime + " ms before cleaning up vms"); + Thread.sleep(sleepTime); + } else { + success = true; + } + } + + if (usageIterator >= numThreads) { + int eventsAndBillingResponseCode = executeEventsAndBilling(server, developerServer); + s_logger.info("events and usage records command finished with response code: " + eventsAndBillingResponseCode); + usageIterator = 1; + + } else { + s_logger.info("Skipping events and usage records for this user: usageIterator " + usageIterator + " and number of Threads " + numThreads); + usageIterator++; + } + + if ((users == null) && (accountName == null)) { + s_logger.info("Sending cleanup command"); + int cleanupResponseCode = executeCleanup(server, developerServer, username); + s_logger.info("cleanup command finished with response code: " + cleanupResponseCode); + success = (cleanupResponseCode == 200); + } else { + s_logger.info("Sending stop DomR / destroy VM command"); + int stopResponseCode = executeStop(server, developerServer, username, true); + s_logger.info("stop(destroy) command finished with response code: " + stopResponseCode); + success = (stopResponseCode == 200); + } + + } else { + // Just stop but don't destroy the + // VMs/Routers + s_logger.info("SSH test failed for account " + _account.get() + "with reason '" + reason + "', stopping VMs"); + int stopResponseCode = executeStop(server, developerServer, username, false); + s_logger.info("stop command finished with response code: " + stopResponseCode); + success = false; // since the SSH test + // failed, mark the + // whole test as + // failure + } + } else { + // Just stop but don't destroy the + // VMs/Routers + s_logger.info("Deploy test failed with reason '" + reason + "', stopping VMs"); + int stopResponseCode = executeStop(server, developerServer, username, true); + s_logger.info("stop command finished with response code: " + stopResponseCode); + success = false; // since the deploy test + // failed, mark the + // whole test as failure + } + + if (success) { + s_logger.info("***** Completed test for user : " + username + " in " + ((System.currentTimeMillis() - now) / 1000L) + " seconds"); + + } else { + s_logger.info("##### FAILED test for user : " + username + " in " + ((System.currentTimeMillis() - now) / 1000L) + " seconds with reason : " + reason); + } + s_logger.info("Sleeping for " + wait + " seconds before starting next iteration"); + Thread.sleep(wait); + } catch (Exception e) { + s_logger.warn("Error in thread", e); + try { + int stopResponseCode = executeStop(server, developerServer, username, true); + s_logger.info("stop response code: " + stopResponseCode); + } catch (Exception e1) { + } + } finally { + NDC.clear(); + } + } while (repeat); + } + }).start(); + } + } catch (Exception e) { + s_logger.error(e); + } + } + + public static Map> getMultipleValuesFromXML(InputStream is, String[] tagNames) { + Map> returnValues = new HashMap>(); + try { + DocumentBuilder docBuilder = factory.newDocumentBuilder(); + Document doc = docBuilder.parse(is); + Element rootElement = doc.getDocumentElement(); + for (int i = 0; i < tagNames.length; i++) { + NodeList targetNodes = rootElement.getElementsByTagName(tagNames[i]); + if (targetNodes.getLength() <= 0) { + s_logger.error("no " + tagNames[i] + " tag in XML response...returning null"); + } else { + List valueList = new ArrayList(); + for (int j = 0; j < targetNodes.getLength(); j++) { + Node node = targetNodes.item(j); + valueList.add(node.getTextContent()); + } + returnValues.put(tagNames[i], valueList); + } + } + } catch (Exception ex) { + s_logger.error(ex); + } + return returnValues; + } + + public static Map getSingleValueFromXML(InputStream is, String[] tagNames) { + Map returnValues = new HashMap(); + try { + DocumentBuilder docBuilder = factory.newDocumentBuilder(); + Document doc = docBuilder.parse(is); + Element rootElement = doc.getDocumentElement(); + + for (int i = 0; i < tagNames.length; i++) { + NodeList targetNodes = rootElement.getElementsByTagName(tagNames[i]); + if (targetNodes.getLength() <= 0) { + s_logger.error("no " + tagNames[i] + " tag in XML response...returning null"); + } else { + returnValues.put(tagNames[i], targetNodes.item(0).getTextContent()); + } + } + } catch (Exception ex) { + s_logger.error("error processing XML", ex); + } + return returnValues; + } + + public static Map getSingleValueFromXML(Element rootElement, String[] tagNames) { + Map returnValues = new HashMap(); + if (rootElement == null) { + s_logger.error("Root element is null, can't get single value from xml"); + return null; + } + try { + for (int i = 0; i < tagNames.length; i++) { + NodeList targetNodes = rootElement.getElementsByTagName(tagNames[i]); + if (targetNodes.getLength() <= 0) { + s_logger.error("no " + tagNames[i] + " tag in XML response...returning null"); + } else { + returnValues.put(tagNames[i], targetNodes.item(0).getTextContent()); + } + } + } catch (Exception ex) { + s_logger.error("error processing XML", ex); + } + return returnValues; + } + + private static List getNonSourceNatIPs(InputStream is) { + List returnValues = new ArrayList(); + try { + DocumentBuilder docBuilder = factory.newDocumentBuilder(); + Document doc = docBuilder.parse(is); + Element rootElement = doc.getDocumentElement(); + NodeList allocatedIpAddrNodes = rootElement.getElementsByTagName("publicipaddress"); + for (int i = 0; i < allocatedIpAddrNodes.getLength(); i++) { + Node allocatedIpAddrNode = allocatedIpAddrNodes.item(i); + NodeList childNodes = allocatedIpAddrNode.getChildNodes(); + String ipAddress = null; + boolean isSourceNat = true; // assume it's source nat until we + // find otherwise + for (int j = 0; j < childNodes.getLength(); j++) { + Node n = childNodes.item(j); + if ("id".equals(n.getNodeName())) { + // if ("ipaddress".equals(n.getNodeName())) { + ipAddress = n.getTextContent(); + } else if ("issourcenat".equals(n.getNodeName())) { + isSourceNat = Boolean.parseBoolean(n.getTextContent()); + } + } + if ((ipAddress != null) && !isSourceNat) { + returnValues.add(ipAddress); + } + } + } catch (Exception ex) { + s_logger.error(ex); + } + return returnValues; + } + + private static List getIPs(InputStream is, boolean sourceNat) { + List returnValues = new ArrayList(); + try { + DocumentBuilder docBuilder = factory.newDocumentBuilder(); + Document doc = docBuilder.parse(is); + Element rootElement = doc.getDocumentElement(); + NodeList allocatedIpAddrNodes = rootElement.getElementsByTagName("publicipaddress"); + for (int i = 0; i < allocatedIpAddrNodes.getLength(); i++) { + Node allocatedIpAddrNode = allocatedIpAddrNodes.item(i); + NodeList childNodes = allocatedIpAddrNode.getChildNodes(); + String ipAddress = null; + String ipAddressId = null; + boolean isSourceNat = false; // assume it's *not* source nat until we find otherwise + for (int j = 0; j < childNodes.getLength(); j++) { + Node n = childNodes.item(j); + //Id is being used instead of ipaddress. Changes need to done later to ipaddress variable + if ("id".equals(n.getNodeName())) + { + ipAddressId = n.getTextContent(); + } + else if("ipaddress".equals(n.getNodeName())) + { + ipAddress = n.getTextContent(); + } + else if ("issourcenat".equals(n.getNodeName())) { + isSourceNat = Boolean.parseBoolean(n.getTextContent()); + } + } + if ((ipAddress != null) && isSourceNat == sourceNat) { + returnValues.add(ipAddressId); + returnValues.add(ipAddress); + } + } + } catch (Exception ex) { + s_logger.error(ex); + } + return returnValues; + } + + private static String executeRegistration(String server, String username, String password) throws HttpException, IOException { + String url = server + "?command=registerUserKeys&id=" + _userId.get().toString(); + s_logger.info("registering: " + username); + String returnValue = null; + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + int responseCode = client.executeMethod(method); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map requestKeyValues = getSingleValueFromXML(is, new String[] { "apikey", "secretkey" }); + _apiKey.set(requestKeyValues.get("apikey")); + returnValue = requestKeyValues.get("secretkey"); + } else { + s_logger.error("registration failed with error code: " + responseCode); + } + return returnValue; + } + + private static Integer executeDeployment(String server, String developerServer, String username, String snapshot_test) throws HttpException, IOException { + // test steps: + // - create user + // - deploy Windows VM + // - deploy Linux VM + // - associate IP address + // - create two IP forwarding rules + // - create load balancer rule + // - list IP forwarding rules + // - list load balancer rules + + // ----------------------------- + // CREATE ACCOUNT + // ----------------------------- + String encodedUsername = URLEncoder.encode(username, "UTF-8"); + String encryptedPassword = createMD5Password(username); + String encodedPassword = URLEncoder.encode(encryptedPassword, "UTF-8"); + + String url = server + "?command=createAccount&username=" + encodedUsername + "&account=" + encodedUsername + "&password=" + encodedPassword + "&firstname=Test&lastname=Test&email=test@vmops.com&domainId=1&accounttype=0"; + + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + int responseCode = client.executeMethod(method); + long accountId = -1; + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map accountValues = getSingleValueFromXML(is, new String[] { "id", "name" }); + String accountIdStr = accountValues.get("id"); + s_logger.info("created account " + username + " with id " + accountIdStr); + if (accountIdStr != null) { + accountId = Long.parseLong(accountIdStr); + _accountId.set(accountId); + _account.set(accountValues.get("name")); + if (accountId == -1) { + s_logger.error("create account (" + username + ") failed to retrieve a valid user id, aborting depolyment test"); + return -1; + } + } + } else { + s_logger.error("create account test failed for account " + username + " with error code :" + responseCode + ", aborting deployment test. The command was sent with url " + url); + return -1; + } + + // LIST JUST CREATED USER TO GET THE USER ID + url = server + "?command=listUsers&username=" + encodedUsername + "&account=" + encodedUsername + "&domainId=1"; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + long userId = -1; + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map userIdValues = getSingleValueFromXML(is, new String[] { "id" }); + String userIdStr = userIdValues.get("id"); + s_logger.info("listed user " + username + " with id " + userIdStr); + if (userIdStr != null) { + userId = Long.parseLong(userIdStr); + _userId.set(userId); + if (userId == -1) { + s_logger.error("list user by username " + username + ") failed to retrieve a valid user id, aborting depolyment test"); + return -1; + } + } + } else { + s_logger.error("list user test failed for account " + username + " with error code :" + responseCode + ", aborting deployment test. The command was sent with url " + url); + return -1; + } + + _secretKey.set(executeRegistration(server, username, username)); + + if (_secretKey.get() == null) { + s_logger.error("FAILED to retrieve secret key during registration, skipping user: " + username); + return -1; + } else { + s_logger.info("got secret key: " + _secretKey.get()); + s_logger.info("got api key: " + _apiKey.get()); + } + + // --------------------------------- + // CREATE VIRTUAL NETWORK + // --------------------------------- + url = server + "?command=createNetwork&networkofferingid=" + networkOfferingId + "&account=" + encodedUsername + "&domainId=1" + "&zoneId=" + zoneId + "&name=virtualnetwork-" + encodedUsername + "&displaytext=virtualnetwork-" + encodedUsername; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map networkValues = getSingleValueFromXML(is, new String[] { "id" }); + String networkIdStr = networkValues.get("id"); + s_logger.info("Created virtual network with name virtualnetwork-" + encodedUsername + " and id " + networkIdStr); + if (networkIdStr != null) { + _networkId.set(networkIdStr); + } + } else { + s_logger.error("Create virtual network failed for account " + username + " with error code :" + responseCode + ", aborting deployment test. The command was sent with url " + url); + return -1; + } +/* + // --------------------------------- + // CREATE DIRECT NETWORK + // --------------------------------- + url = server + "?command=createNetwork&networkofferingid=" + networkOfferingId_dir + "&account=" + encodedUsername + "&domainId=1" + "&zoneId=" + zoneId + "&name=directnetwork-" + encodedUsername + "&displaytext=directnetwork-" + encodedUsername; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map networkValues = getSingleValueFromXML(is, new String[] { "id" }); + String networkIdStr = networkValues.get("id"); + s_logger.info("Created direct network with name directnetwork-" + encodedUsername + " and id " + networkIdStr); + if (networkIdStr != null) { + _networkId_dir.set(networkIdStr); + } + } else { + s_logger.error("Create direct network failed for account " + username + " with error code :" + responseCode + ", aborting deployment test. The command was sent with url " + url); + return -1; + } +*/ + + + // --------------------------------- + // DEPLOY LINUX VM + // --------------------------------- + String linuxVMPrivateIP = null; + { + // long templateId = 3; + long templateId = 4; + String encodedZoneId = URLEncoder.encode("" + zoneId, "UTF-8"); + String encodedServiceOfferingId = URLEncoder.encode("" + serviceOfferingId, "UTF-8"); + String encodedTemplateId = URLEncoder.encode("" + templateId, "UTF-8"); + String encodedApiKey = URLEncoder.encode(_apiKey.get(), "UTF-8"); + String encodedNetworkIds = URLEncoder.encode(_networkId.get()+",206","UTF-8"); + String requestToSign = "apikey=" + encodedApiKey + "&command=deployVirtualMachine&diskofferingid=" + diskOfferingId + "&networkids=" + encodedNetworkIds + "&serviceofferingid=" + encodedServiceOfferingId + "&templateid=" + encodedTemplateId + + "&zoneid=" + encodedZoneId; + requestToSign = requestToSign.toLowerCase(); + String signature = signRequest(requestToSign, _secretKey.get()); + String encodedSignature = URLEncoder.encode(signature, "UTF-8"); + url = developerServer + "?command=deployVirtualMachine" + "&zoneid=" + encodedZoneId + "&serviceofferingid=" + encodedServiceOfferingId + "&diskofferingid=" + diskOfferingId + "&networkids=" + encodedNetworkIds + "&templateid=" + encodedTemplateId + + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; + + method = new GetMethod(url); + responseCode = client.executeMethod(method); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + Map values = getSingleValueFromXML(el, new String[] { "id", "ipaddress" }); + + if ((values.get("ipaddress") == null) || (values.get("id") == null)) { + s_logger.info("deploy linux vm response code: 401, the command was sent with url " + url); + return 401; + } else { + s_logger.info("deploy linux vm response code: " + responseCode); + long linuxVMId = Long.parseLong(values.get("id")); + s_logger.info("got linux virtual machine id: " + linuxVMId); + _linuxVmId.set(values.get("id")); + linuxVMPrivateIP = values.get("ipaddress"); + // _linuxPassword.set(values.get("password")); + _linuxPassword.set(vmPassword); + s_logger.info("got linux virtual machine password: " + _linuxPassword.get()); + } + } else { + s_logger.error("deploy linux vm failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + + { + // --------------------------------- + // ASSOCIATE IP for windows + // --------------------------------- + String ipAddr = null; + + String encodedApiKey = URLEncoder.encode(_apiKey.get(), "UTF-8"); + String requestToSign = "apikey=" + encodedApiKey + "&command=associateIpAddress" + "&zoneid=" + zoneId; + requestToSign = requestToSign.toLowerCase(); + String signature = signRequest(requestToSign, _secretKey.get()); + String encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=associateIpAddress" + "&apikey=" + encodedApiKey + "&zoneid=" + zoneId + "&signature=" + encodedSignature; + + method = new GetMethod(url); + responseCode = client.executeMethod(method); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + /*Asynchronous Job - Corresponding Changes Made*/ + Element associpel = queryAsyncJobResult(server, is); + Map values = getSingleValueFromXML(associpel, new String[] {"id", "ipaddress" }); + + if ((values.get("ipaddress") == null)|| (values.get("id") == null)) { + s_logger.info("associate ip for Windows response code: 401, the command was sent with url " + url); + return 401; + } + else + { + s_logger.info("Associate IP Address response code: " + responseCode); + long publicIpId = Long.parseLong(values.get("id")); + s_logger.info("Associate IP's Id: " + publicIpId); + _publicIpId.set(values.get("id")); + } + } else { + s_logger.error("associate ip address for windows vm failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + String encodedPublicIpId = URLEncoder.encode(_publicIpId.get(), "UTF-8"); + requestToSign = "apikey=" + encodedApiKey + "&command=listPublicIpAddresses"+"&id="+ encodedPublicIpId; + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=listPublicIpAddresses&apikey=" + encodedApiKey + "&id=" + encodedPublicIpId + "&signature=" + encodedSignature; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("url is " + url); + s_logger.info("list ip addresses for user " + userId + " response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + // InputStream ips = method.getResponseBodyAsStream(); + List ipAddressValues = getIPs(is, false); + // List ipAddressVals = getIPs(is, false, true); + if ((ipAddressValues != null) && !ipAddressValues.isEmpty()) { + _windowsIpId.set(ipAddressValues.get(0)); + _windowsIP.set(ipAddressValues.get(1)); + s_logger.info("For Windows, using non-sourceNat IP address ID: " + ipAddressValues.get(0)); + s_logger.info("For Windows, using non-sourceNat IP address: " + ipAddressValues.get(1)); + } + } else { + s_logger.error("list ip addresses failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + // --------------------------------- + // Use the SourceNat IP for linux + // --------------------------------- + { + requestToSign = "apikey=" + encodedApiKey + "&command=listPublicIpAddresses"; + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=listPublicIpAddresses&apikey=" + encodedApiKey + "&signature=" + encodedSignature; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("url is " + url); + s_logger.info("list ip addresses for user " + userId + " response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); +// InputStream ips = method.getResponseBodyAsStream(); + List ipAddressValues = getIPs(is, true); +// is = method.getResponseBodyAsStream(); +// List ipAddressVals = getIPs(is, true, true); + if ((ipAddressValues != null) && !ipAddressValues.isEmpty()) { + _linuxIpId.set(ipAddressValues.get(0)); + _linuxIP.set(ipAddressValues.get(1)); + s_logger.info("For linux, using sourceNat IP address ID: " + ipAddressValues.get(0)); + s_logger.info("For linux, using sourceNat IP address: " + ipAddressValues.get(1)); + } + } else { + s_logger.error("list ip addresses failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + + //-------------------------------------------- + // Enable Static NAT for the Source NAT Ip + //-------------------------------------------- + String encodedSourceNatPublicIpId = URLEncoder.encode(_linuxIpId.get(), "UTF-8"); + + /* requestToSign = "apikey=" + encodedApiKey + "&command=enableStaticNat"+"&id=" + encodedSourceNatPublicIpId + "&virtualMachineId=" + encodedVmId;; + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=enableStaticNat&apikey=" + encodedApiKey + "&signature=" + encodedSignature + "&id=" + encodedSourceNatPublicIpId + "&virtualMachineId=" + encodedVmId; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("url is " + url); + s_logger.info("list ip addresses for user " + userId + " response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map success = getSingleValueFromXML(is, new String[] { "success" }); + s_logger.info("Enable Static NAT..success? " + success.get("success")); + } else { + s_logger.error("Enable Static NAT failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + */ + // ------------------------------------------------------------- + // CREATE IP FORWARDING RULE -- Linux VM + // ------------------------------------------------------------- + String encodedVmId = URLEncoder.encode(_linuxVmId.get(), "UTF-8"); + String encodedIpAddress = URLEncoder.encode(_linuxIpId.get(), "UTF-8"); + requestToSign = "apikey=" + encodedApiKey + "&command=createPortForwardingRule&ipaddressid=" + encodedIpAddress + "&privateport=22&protocol=TCP&publicport=22" + "&virtualmachineid=" + encodedVmId ; + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=createPortForwardingRule&apikey=" + encodedApiKey + "&ipaddressid=" + encodedIpAddress + "&privateport=22&protocol=TCP&publicport=22&virtualmachineid=" + encodedVmId + "&signature=" + encodedSignature; + + s_logger.info("Created port forwarding rule with " + url); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + Map values = getSingleValueFromXML(el, new String[] {"id"}); + s_logger.info("Port forwarding rule was assigned successfully to Linux VM"); + long ipfwdid = Long.parseLong(values.get("id")); + s_logger.info("got Port Forwarding Rule's Id:" + ipfwdid); + _linipfwdid.set(values.get("id")); + + } else { + s_logger.error("Port forwarding rule creation failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + // Create snapshot recurring policy if needed; otherwise create windows vm + if (snapshot_test.equals("yes")) { + + // list volumes for linux vm + { + url = server + "?command=listVolumes&virtualMachineId=" + _linuxVmId.get() + "&type=root"; + s_logger.info("Getting rootDisk id of Centos vm"); + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("List volumes response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map success = getSingleValueFromXML(is, new String[] { "id" }); + if (success.get("id") == null) { + s_logger.error("Unable to get root volume for linux vm. Followin url was sent: " + url); + } + s_logger.info("Got rootVolume for linux vm with id " + success.get("id")); + _rootVolume.set(success.get("id")); + } else { + s_logger.error("List volumes for linux vm failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + // Create recurring snapshot policy for linux vm + { + String encodedTimeZone = URLEncoder.encode("America/Los Angeles", "UTF-8"); + url = server + "?command=createSnapshotPolicy&intervaltype=hourly&schedule=10&maxsnaps=4&volumeid=" + _rootVolume.get() + "&timezone=" + encodedTimeZone; + s_logger.info("Creating recurring snapshot policy for linux vm ROOT disk"); + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("Create recurring snapshot policy for linux vm ROOT disk: " + responseCode); + if (responseCode != 200) { + s_logger.error("Create recurring snapshot policy for linux vm ROOT disk failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + } else { + // --------------------------------- + // DEPLOY WINDOWS VM + // --------------------------------- + String windowsVMPrivateIP = null; + { + // long templateId = 6; + long templateId = 4; + String encodedZoneId = URLEncoder.encode("" + zoneId, "UTF-8"); + String encodedServiceOfferingId = URLEncoder.encode("" + serviceOfferingId, "UTF-8"); + String encodedTemplateId = URLEncoder.encode("" + templateId, "UTF-8"); + encodedApiKey = URLEncoder.encode(_apiKey.get(), "UTF-8"); + String encodedNetworkIds = URLEncoder.encode(_networkId.get()+",206","UTF-8"); + + requestToSign = "apikey=" + encodedApiKey + "&command=deployVirtualMachine&diskofferingid=" + diskOfferingId + "&networkids=" + encodedNetworkIds + "&serviceofferingid=" + encodedServiceOfferingId + "&templateid=" + encodedTemplateId + + "&zoneid=" + encodedZoneId; + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=deployVirtualMachine" + "&zoneid=" + encodedZoneId + "&serviceofferingid=" + encodedServiceOfferingId + "&diskofferingid=" + diskOfferingId + "&networkids=" + encodedNetworkIds + "&templateid=" + + encodedTemplateId + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; + + method = new GetMethod(url); + responseCode = client.executeMethod(method); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + Map values = getSingleValueFromXML(el, new String[] { "id", "ipaddress" }); + + if ((values.get("ipaddress") == null) || (values.get("id") == null)) { + s_logger.info("deploy windows vm response code: 401, the command was sent with url " + url); + return 401; + } else { + s_logger.info("deploy windows vm response code: " + responseCode); + windowsVMPrivateIP = values.get("ipaddress"); + long windowsVMId = Long.parseLong(values.get("id")); + s_logger.info("got windows virtual machine id: " + windowsVMId); + _windowsVmId.set(values.get("id")); + } + } else { + s_logger.error("deploy windows vm failes with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + + //-------------------------------------------- + // Enable Static NAT for the Non Source NAT Ip + //-------------------------------------------- + + encodedVmId = URLEncoder.encode(_windowsVmId.get(), "UTF-8"); + encodedPublicIpId = URLEncoder.encode(_publicIpId.get(), "UTF-8"); + requestToSign = "apikey=" + encodedApiKey + "&command=enableStaticNat"+"&ipaddressid="+ encodedPublicIpId + "&virtualMachineId=" + encodedVmId; + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=enableStaticNat&apikey=" + encodedApiKey + "&ipaddressid=" + encodedPublicIpId + "&signature=" + encodedSignature + "&virtualMachineId=" + encodedVmId; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("url is " + url); + s_logger.info("list ip addresses for user " + userId + " response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map success = getSingleValueFromXML(is, new String[] { "success" }); + s_logger.info("Enable Static NAT..success? " + success.get("success")); + } else { + s_logger.error("Enable Static NAT failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + + // ------------------------------------------------------------- + // CREATE IP FORWARDING RULE -- Windows VM + // ------------------------------------------------------------- + + // create port forwarding rule for window vm + encodedIpAddress = URLEncoder.encode(_windowsIpId.get(), "UTF-8"); + //encodedVmId = URLEncoder.encode(_windowsVmId.get(), "UTF-8"); + + requestToSign = "apikey=" + encodedApiKey + "&command=createIpForwardingRule&endPort=22&ipaddressid=" + encodedIpAddress + "&protocol=TCP&startPort=22"; + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=createIpForwardingRule&apikey=" + encodedApiKey + "&endPort=22&ipaddressid=" + encodedIpAddress + "&protocol=TCP&signature=" + encodedSignature + "&startPort=22"; + + s_logger.info("Created Ip forwarding rule with " + url); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + Map values = getSingleValueFromXML(el, new String[] {"id"}); + s_logger.info("Port forwarding rule was assigned successfully to Windows VM"); + long ipfwdid = Long.parseLong(values.get("id")); + s_logger.info("got Ip Forwarding Rule's Id:" + ipfwdid); + _winipfwdid.set(values.get("id")); + } else { + s_logger.error("Port forwarding rule creation failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + } + return responseCode; + } + + private static int executeCleanup(String server, String developerServer, String username) throws HttpException, IOException { + // test steps: + // - get user + // - delete user + + // ----------------------------- + // GET USER + // ----------------------------- + String userId = _userId.get().toString(); + String encodedUserId = URLEncoder.encode(userId, "UTF-8"); + String url = server + "?command=listUsers&id=" + encodedUserId; + s_logger.info("Cleaning up resources for user: " + userId + " with url " + url); + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + int responseCode = client.executeMethod(method); + s_logger.info("get user response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map userInfo = getSingleValueFromXML(is, new String[] { "username", "id", "account" }); + if (!username.equals(userInfo.get("username"))) { + s_logger.error("get user failed to retrieve requested user, aborting cleanup test" + ". Following URL was sent: " + url); + return -1; + } + + } else { + s_logger.error("get user failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + // ----------------------------- + // UPDATE USER + // ----------------------------- + { + url = server + "?command=updateUser&id=" + userId + "&firstname=delete&lastname=me"; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("update user response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map success = getSingleValueFromXML(is, new String[] { "success" }); + s_logger.info("update user..success? " + success.get("success")); + } else { + s_logger.error("update user failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + + // ----------------------------- + // Detach existin dataVolume, create a new volume, attach it to the vm + // ----------------------------- + { + url = server + "?command=listVolumes&virtualMachineId=" + _linuxVmId.get() + "&type=dataDisk"; + s_logger.info("Getting dataDisk id of Centos vm"); + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("List volumes response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map success = getSingleValueFromXML(is, new String[] { "id" }); + s_logger.info("Got dataDiskVolume with id " + success.get("id")); + _dataVolume.set(success.get("id")); + } else { + s_logger.error("List volumes failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + + // Detach volume + { + url = server + "?command=detachVolume&id=" + _dataVolume.get(); + s_logger.info("Detaching volume with id " + _dataVolume.get()); + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("Detach data volume response code: " + responseCode); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + s_logger.info("The volume was detached successfully"); + } else { + s_logger.error("Detach data disk failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + + // Delete a volume + { + url = server + "?command=deleteVolume&id=" + _dataVolume.get(); + s_logger.info("Deleting volume with id " + _dataVolume.get()); + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("Delete data volume response code: " + responseCode); + if (responseCode == 200) { + s_logger.info("The volume was deleted successfully"); + } else { + s_logger.error("Delete volume failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + + // Create a new volume + { + url = server + "?command=createVolume&diskofferingid=" + diskOfferingId + "&zoneid=" + zoneId + "&name=newvolume&account=" + _account.get() + "&domainid=1"; + s_logger.info("Creating volume...."); + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + Map values = getSingleValueFromXML(el, new String[] { "id" }); + + if (values.get("id") == null) { + s_logger.info("create volume response code: 401"); + return 401; + } else { + s_logger.info("create volume response code: " + responseCode); + long volumeId = Long.parseLong(values.get("id")); + s_logger.info("got volume id: " + volumeId); + _newVolume.set(values.get("id")); + } + } else { + s_logger.error("create volume failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + + // attach a new volume to the vm + { + url = server + "?command=attachVolume&id=" + _newVolume.get() + "&virtualmachineid=" + _linuxVmId.get(); + s_logger.info("Attaching volume with id " + _newVolume.get() + " to the vm " + _linuxVmId.get()); + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("Attach data volume response code: " + responseCode); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + s_logger.info("The volume was attached successfully"); + } else { + s_logger.error("Attach volume failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + + // Create a snapshot + // list volumes + { + url = server + "?command=listVolumes&virtualMachineId=" + _linuxVmId.get() + "&type=root"; + s_logger.info("Getting rootDisk id of Centos vm"); + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("List volumes response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map success = getSingleValueFromXML(is, new String[] { "id" }); + if (success.get("id") == null) { + s_logger.error("Unable to get root volume. Followin url was sent: " + url); + } + s_logger.info("Got rootVolume with id " + success.get("id")); + _rootVolume.set(success.get("id")); + } else { + s_logger.error("List volumes failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + + // //Create snapshot from root disk volume + String encodedApiKey = URLEncoder.encode(_apiKey.get(), "UTF-8"); + String requestToSign = "apikey=" + encodedApiKey + "&command=createSnapshot&volumeid=" + _rootVolume.get(); + requestToSign = requestToSign.toLowerCase(); + String signature = signRequest(requestToSign, _secretKey.get()); + String encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=createSnapshot&volumeid=" + _rootVolume.get() + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("Create snapshot response code: " + responseCode); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + Map values = getSingleValueFromXML(el, new String[] { "id" }); + + if (values.get("id") == null) { + s_logger.info("create snapshot response code: 401"); + return 401; + } else { + s_logger.info("create snapshot response code: " + responseCode + ". Got snapshot with id " + values.get("id")); + _snapshot.set(values.get("id")); + } + } else { + s_logger.error("create snapshot failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + // Create volume from the snapshot created on the previous step and attach it to the running vm + /* encodedApiKey = URLEncoder.encode(_apiKey.get(), "UTF-8"); + requestToSign = "apikey=" + encodedApiKey + "&command=createVolume&name=" + _account.get() + "&snapshotid=" + _snapshot.get(); + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=createVolume&name=" + _account.get() + "&snapshotid=" + _snapshot.get() + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("Create volume from snapshot response code: " + responseCode); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + Map values = getSingleValueFromXML(el, new String[] { "id" }); + + if (values.get("id") == null) { + s_logger.info("create volume from snapshot response code: 401"); + return 401; + } else { + s_logger.info("create volume from snapshot response code: " + responseCode + ". Got volume with id " + values.get("id") + ". The command was sent with url " + url); + _volumeFromSnapshot.set(values.get("id")); + } + } else { + s_logger.error("create volume from snapshot failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + { + url = server + "?command=attachVolume&id=" + _volumeFromSnapshot.get() + "&virtualmachineid=" + _linuxVmId.get(); + s_logger.info("Attaching volume with id " + _volumeFromSnapshot.get() + " to the vm " + _linuxVmId.get()); + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("Attach volume from snapshot to linux vm response code: " + responseCode); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + s_logger.info("The volume created from snapshot was attached successfully to linux vm"); + } else { + s_logger.error("Attach volume created from snapshot failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } +*/ + // ----------------------------- + // Execute reboot/stop/start commands for the VMs before deleting the account - made to exercise xen + // ----------------------------- + + // Reboot windows VM + requestToSign = "apikey=" + encodedApiKey + "&command=rebootVirtualMachine&id=" + _windowsVmId.get(); + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=rebootVirtualMachine&id=" + _windowsVmId.get() + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("Reboot windows Vm response code: " + responseCode); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + Map success = getSingleValueFromXML(el, new String[] { "success" }); + s_logger.info("Windows VM was rebooted with the status: " + success.get("success")); + } else { + s_logger.error("Reboot windows VM test failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + // Stop centos VM + requestToSign = "apikey=" + encodedApiKey + "&command=stopVirtualMachine&id=" + _linuxVmId.get(); + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=stopVirtualMachine&id=" + _linuxVmId.get() + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("Stop linux Vm response code: " + responseCode); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + Map success = getSingleValueFromXML(el, new String[] { "success" }); + s_logger.info("Linux VM was stopped with the status: " + success.get("success")); + } else { + s_logger.error("Stop linux VM test failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + // Create private template from root disk volume + requestToSign = "apikey=" + encodedApiKey + "&command=createTemplate" + "&displaytext=" + _account.get() + "&name=" + _account.get() + "&ostypeid=11" + "&snapshotid=" + _snapshot.get(); + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=createTemplate" + "&displaytext=" + _account.get() + "&name=" + _account.get() + "&ostypeid=11" + "&snapshotid=" + _snapshot.get() + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("Create private template response code: " + responseCode); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + Map values = getSingleValueFromXML(el, new String[] { "id" }); + + if (values.get("id") == null) { + s_logger.info("create private template response code: 401"); + return 401; + } else { + s_logger.info("create private template response code: " + responseCode); + } + } else { + s_logger.error("create private template failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + // Start centos VM + requestToSign = "apikey=" + encodedApiKey + "&command=startVirtualMachine&id=" + _windowsVmId.get(); + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=startVirtualMachine&id=" + _windowsVmId.get() + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("Start linux Vm response code: " + responseCode); + if (responseCode != 200) { + s_logger.error("Start linux VM test failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + // get domainRouter id + { + url = server + "?command=listRouters&zoneid=" + zoneId + "&account=" + _account.get() + "&domainid=1"; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("List domain routers response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map success = getSingleValueFromXML(is, new String[] { "id" }); + s_logger.info("Got the domR with id " + success.get("id")); + _domainRouterId.set(success.get("id")); + } else { + s_logger.error("List domain routers failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + + // reboot the domain router + { + url = server + "?command=rebootRouter&id=" + _domainRouterId.get(); + s_logger.info("Rebooting domR with id " + _domainRouterId.get()); + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("Reboot domain router response code: " + responseCode); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + s_logger.info("Domain router was rebooted successfully"); + } else { + s_logger.error("Reboot domain routers failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + + // ----------------------------- + // DELETE ACCOUNT + // ----------------------------- + { + url = server + "?command=deleteAccount&id=" + _accountId.get(); + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("delete account response code: " + responseCode); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + s_logger.info("Deleted account successfully"); + } else { + s_logger.error("delete account failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + return responseCode; + } + + private static int executeEventsAndBilling(String server, String developerServer) throws HttpException, IOException { + // test steps: + // - get all the events in the system for all users in the system + // - generate all the usage records in the system + // - get all the usage records in the system + + // ----------------------------- + // GET EVENTS + // ----------------------------- + String url = server + "?command=listEvents&page=1&pagesize=100&&account=" + _account.get(); + + s_logger.info("Getting events for the account " + _account.get()); + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + int responseCode = client.executeMethod(method); + s_logger.info("get events response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map> eventDescriptions = getMultipleValuesFromXML(is, new String[] { "description" }); + List descriptionText = eventDescriptions.get("description"); + if (descriptionText == null) { + s_logger.info("no events retrieved..."); + } else { + for (String text : descriptionText) { + s_logger.info("event: " + text); + } + } + } else { + s_logger.error("list events failed with error code: " + responseCode + ". Following URL was sent: " + url); + + return responseCode; + } + + // ------------------------------------------------------------------------------------- + // GENERATE USAGE RECORDS (note: typically this is done infrequently) + // ------------------------------------------------------------------------------------- + DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + Date currentDate = new Date(); + String endDate = dateFormat.format(currentDate); + s_logger.info("Generating usage records from September 1st till " + endDate); + url = server + "?command=generateUsageRecords&startdate=2009-09-01&enddate=" + endDate; // generate + // all usage record till today + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("generate usage records response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map successStr = getSingleValueFromXML(is, new String[] { "success" }); + s_logger.info("successfully generated usage records? " + successStr.get("success")); + } else { + s_logger.error("generate usage records failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + // Sleeping for a 2 minutes before getting a usage records from the database + try { + Thread.sleep(120000); + } catch (Exception ex) { + s_logger.error(ex); + } + + // -------------------------------- + // GET USAGE RECORDS + // -------------------------------- + url = server + "?command=listUsageRecords&startdate=2009-09-01&enddate=" + endDate + "&account=" + _account.get() + "&domaindid=1"; + s_logger.info("Getting all usage records with request: " + url); + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("get usage records response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map> usageRecValues = getMultipleValuesFromXML(is, new String[] { "description", "usage" }); + if ((usageRecValues.containsKey("description") == true) && (usageRecValues.containsKey("usage") == true)) { + List descriptions = usageRecValues.get("description"); + List usages = usageRecValues.get("usage"); + for (int i = 0; i < descriptions.size(); i++) { + String desc = descriptions.get(i); + String usage = ""; + if (usages != null) { + if (i < usages.size()) { + usage = ", usage: " + usages.get(i); + } + } + s_logger.info("desc: " + desc + usage); + } + } + + } else { + s_logger.error("list usage records failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + return responseCode; + } + + private static boolean getNetworkStat(String server) { + try { + String url = server + "?command=listAccountStatistics&account=" + _account.get(); + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + int responseCode = client.executeMethod(method); + s_logger.info("listAccountStatistics response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map requestKeyValues = getSingleValueFromXML(is, new String[] { "receivedbytes", "sentbytes" }); + int bytesReceived = Integer.parseInt(requestKeyValues.get("receivedbytes")); + int bytesSent = Integer.parseInt(requestKeyValues.get("sentbytes")); + if ((bytesReceived > 100000000) && (bytesSent > 0)) { + s_logger.info("Network stat is correct for account" + _account.get() + "; bytest received is " + bytesReceived + " and bytes sent is " + bytesSent); + return true; + } else { + s_logger.error("Incorrect value for bytes received/sent for the account " + _account.get() + ". We got " + bytesReceived + " bytes received; " + " and " + bytesSent + " bytes sent"); + return false; + } + + } else { + s_logger.error("listAccountStatistics failed with error code: " + responseCode + ". Following URL was sent: " + url); + return false; + } + } catch (Exception ex) { + s_logger.error("Exception while sending command listAccountStatistics"); + return false; + } + } + + private static int executeStop(String server, String developerServer, String username, boolean destroy) throws HttpException, IOException { + // test steps: + // - get userId for the given username + // - list virtual machines for the user + // - stop all virtual machines + // - get ip addresses for the user + // - release ip addresses + + // ----------------------------- + // GET USER + // ----------------------------- + String userId = _userId.get().toString(); + String encodedUserId = URLEncoder.encode(userId, "UTF-8"); + + String url = server + "?command=listUsers&id=" + encodedUserId; + s_logger.info("Stopping resources for user: " + username); + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + int responseCode = client.executeMethod(method); + s_logger.info("get user response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map userIdValues = getSingleValueFromXML(is, new String[] { "id" }); + String userIdStr = userIdValues.get("id"); + if (userIdStr != null) { + userId = userIdStr; + + } else { + s_logger.error("get user failed to retrieve a valid user id, aborting depolyment test" + ". Following URL was sent: " + url); + return -1; + } + } else { + s_logger.error("get user failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + { + // ---------------------------------- + // LIST VIRTUAL MACHINES + // ---------------------------------- + String encodedApiKey = URLEncoder.encode(_apiKey.get(), "UTF-8"); + String requestToSign = "apikey=" + encodedApiKey + "&command=listVirtualMachines"; + requestToSign = requestToSign.toLowerCase(); + String signature = signRequest(requestToSign, _secretKey.get()); + String encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=listVirtualMachines&apikey=" + encodedApiKey + "&signature=" + encodedSignature; + + s_logger.info("Listing all virtual machines for the user with url " + url); + String[] vmIds = null; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("list virtual machines response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map> vmIdValues = getMultipleValuesFromXML(is, new String[] { "id" }); + if (vmIdValues.containsKey("id")) { + List vmIdList = vmIdValues.get("id"); + if (vmIdList != null) { + vmIds = new String[vmIdList.size()]; + vmIdList.toArray(vmIds); + String vmIdLogStr = ""; + if ((vmIds != null) && (vmIds.length > 0)) { + vmIdLogStr = vmIds[0]; + for (int i = 1; i < vmIds.length; i++) { + vmIdLogStr = vmIdLogStr + "," + vmIds[i]; + } + } + s_logger.info("got virtual machine ids: " + vmIdLogStr); + } + } + + } else { + s_logger.error("list virtual machines test failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + // ---------------------------------- + // LIST USER IP ADDRESSES + // ---------------------------------- + + requestToSign = "apikey=" + encodedApiKey + "&command=listPublicIpAddresses"; + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=listPublicIpAddresses&apikey=" + encodedApiKey + "&signature=" + encodedSignature; + String[] ipAddresses = null; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("list ip addresses for user " + userId + " response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map> ipAddressValues = getMultipleValuesFromXML(is, new String[] { "ipaddress" }); + if (ipAddressValues.containsKey("ipaddress")) { + List ipAddressList = ipAddressValues.get("ipaddress"); + if (ipAddressList != null) { + ipAddresses = new String[ipAddressList.size()]; + ipAddressList.toArray(ipAddresses); + String ipAddressLogStr = ""; + if ((ipAddresses != null) && (ipAddresses.length > 0)) { + ipAddressLogStr = ipAddresses[0]; + for (int i = 1; i < ipAddresses.length; i++) { + ipAddressLogStr = ipAddressLogStr + "," + ipAddresses[i]; + } + } + s_logger.info("got IP addresses: " + ipAddressLogStr); + } + } + + } else { + s_logger.error("list user ip addresses failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + // ---------------------------------- + // LIST ZONES + // ---------------------------------- + + requestToSign = "apikey=" + encodedApiKey + "&command=listZones"; + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=listZones&apikey=" + encodedApiKey + "&signature=" + encodedSignature; + String[] zoneNames = null; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("list zones response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map> zoneNameValues = getMultipleValuesFromXML(is, new String[] { "name" }); + if (zoneNameValues.containsKey("name")) { + List zoneNameList = zoneNameValues.get("name"); + if (zoneNameList != null) { + zoneNames = new String[zoneNameList.size()]; + zoneNameList.toArray(zoneNames); + String zoneNameLogStr = "\n\n"; + if ((zoneNames != null) && (zoneNames.length > 0)) { + zoneNameLogStr += zoneNames[0]; + for (int i = 1; i < zoneNames.length; i++) { + zoneNameLogStr = zoneNameLogStr + "\n" + zoneNames[i]; + } + + } + zoneNameLogStr += "\n\n"; + s_logger.info("got zones names: " + zoneNameLogStr); + } + } + + } else { + s_logger.error("list zones failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + // ---------------------------------- + // LIST ACCOUNT STATISTICS + // ---------------------------------- + + requestToSign = "apikey=" + encodedApiKey + "&command=listAccounts"; + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=listAccounts&apikey=" + encodedApiKey + "&signature=" + encodedSignature; + String[] statNames = null; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("listAccountStatistics response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map> statValues = getMultipleValuesFromXML(is, new String[] { "receivedbytes" }); + if (statValues.containsKey("receivedbytes")) { + List statList = statValues.get("receivedbytes"); + if (statList != null) { + statNames = new String[statList.size()]; + statList.toArray(statNames); + String statLogStr = "\n\n"; + if ((statNames != null) && (zoneNames.length > 0)) { + statLogStr += statNames[0]; + for (int i = 1; i < statNames.length; i++) { + statLogStr = statLogStr + "\n" + zoneNames[i]; + } + + } + statLogStr += "\n\n"; + s_logger.info("got accountstatistics: " + statLogStr); + } + } + + } else { + s_logger.error("listAccountStatistics failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + // ---------------------------------- + // LIST TEMPLATES + // ---------------------------------- + + requestToSign = "apikey=" + encodedApiKey + "&command=listTemplates@templatefilter=self"; + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=listTemplates&apikey=" + encodedApiKey + "&templatefilter=self&signature=" + encodedSignature; + String[] templateNames = null; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("list templates response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map> templateNameValues = getMultipleValuesFromXML(is, new String[] { "name" }); + + if (templateNameValues.containsKey("name")) { + List templateNameList = templateNameValues.get("name"); + if (templateNameList != null) { + templateNames = new String[templateNameList.size()]; + templateNameList.toArray(templateNames); + String templateNameLogStr = "\n\n"; + if ((templateNames != null) && (templateNames.length > 0)) { + templateNameLogStr += templateNames[0]; + for (int i = 1; i < templateNames.length; i++) { + templateNameLogStr = templateNameLogStr + "\n" + templateNames[i]; + } + + } + templateNameLogStr += "\n\n"; + s_logger.info("got template names: " + templateNameLogStr); + } + } + + } else { + s_logger.error("list templates failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + // ---------------------------------- + // LIST SERVICE OFFERINGS + // ---------------------------------- + + requestToSign = "apikey=" + encodedApiKey + "&command=listServiceOfferings"; + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=listServiceOfferings&apikey=" + encodedApiKey + "&signature=" + encodedSignature; + String[] serviceOfferingNames = null; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("list service offerings response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map> serviceOfferingNameValues = getMultipleValuesFromXML(is, new String[] { "name" }); + + if (serviceOfferingNameValues.containsKey("name")) { + List serviceOfferingNameList = serviceOfferingNameValues.get("name"); + if (serviceOfferingNameList != null) { + serviceOfferingNames = new String[serviceOfferingNameList.size()]; + serviceOfferingNameList.toArray(serviceOfferingNames); + String serviceOfferingNameLogStr = ""; + if ((serviceOfferingNames != null) && (serviceOfferingNames.length > 0)) { + serviceOfferingNameLogStr = serviceOfferingNames[0]; + for (int i = 1; i < serviceOfferingNames.length; i++) { + serviceOfferingNameLogStr = serviceOfferingNameLogStr + ", " + serviceOfferingNames[i]; + } + } + s_logger.info("got service offering names: " + serviceOfferingNameLogStr); + } + } + + } else { + s_logger.error("list service offerings failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + // ---------------------------------- + // LIST EVENTS + // --------------------------------- + + url = server + "?command=listEvents&page=1&pagesize=100&&account=" + _account.get(); + String[] eventDescriptions = null; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("list events response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map> eventNameValues = getMultipleValuesFromXML(is, new String[] { "description" }); + + if (eventNameValues.containsKey("description")) { + List eventNameList = eventNameValues.get("description"); + if (eventNameList != null) { + eventDescriptions = new String[eventNameList.size()]; + eventNameList.toArray(eventDescriptions); + String eventNameLogStr = "\n\n"; + if ((eventDescriptions != null) && (eventDescriptions.length > 0)) { + eventNameLogStr += eventDescriptions[0]; + for (int i = 1; i < eventDescriptions.length; i++) { + eventNameLogStr = eventNameLogStr + "\n" + eventDescriptions[i]; + } + } + eventNameLogStr += "\n\n"; + s_logger.info("got event descriptions: " + eventNameLogStr); + } + } + } else { + s_logger.error("list events failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + // ---------------------------------- + // STOP/DESTROY VIRTUAL MACHINES + // ---------------------------------- + if (vmIds != null) { + String cmdName = (destroy ? "destroyVirtualMachine" : "stopVirtualMachine"); + for (String vmId : vmIds) { + requestToSign = "apikey=" + encodedApiKey + "&command=" + cmdName + "&id=" + vmId; + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=" + cmdName + "&id=" + vmId + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info(cmdName + " [" + vmId + "] response code: " + responseCode); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + Map success = getSingleValueFromXML(el, new String[] { "success" }); + s_logger.info(cmdName + "..success? " + success.get("success")); + } else { + s_logger.error(cmdName + "test failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + } + } + + { + String[] ipAddresses = null; + // ----------------------------------------- + // LIST NAT IP ADDRESSES + // ----------------------------------------- + String encodedApiKey = URLEncoder.encode(_apiKey.get(), "UTF-8"); + String requestToSign = "apikey=" + encodedApiKey + "&command=listPublicIpAddresses"; + requestToSign = requestToSign.toLowerCase(); + String signature = signRequest(requestToSign, _secretKey.get()); + String encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=listPublicIpAddresses&apikey=" + encodedApiKey + "&signature=" + encodedSignature; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("list ip addresses for user " + userId + " response code: " + responseCode); + if (responseCode == 200) { + + InputStream is = method.getResponseBodyAsStream(); + List ipAddressList = getNonSourceNatIPs(is); + ipAddresses = new String[ipAddressList.size()]; + ipAddressList.toArray(ipAddresses); + String ipAddrLogStr = ""; + if ((ipAddresses != null) && (ipAddresses.length > 0)) { + ipAddrLogStr = ipAddresses[0]; + for (int i = 1; i < ipAddresses.length; i++) { + ipAddrLogStr = ipAddrLogStr + "," + ipAddresses[i]; + } + } + s_logger.info("got ip addresses: " + ipAddrLogStr); + + } else { + s_logger.error("list nat ip addresses failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + // ------------------------------------------------------------- + // Delete IP FORWARDING RULE -- Windows VM + // ------------------------------------------------------------- + String encodedIpFwdId = URLEncoder.encode(_winipfwdid.get(), "UTF-8"); + + requestToSign = "apikey=" + encodedApiKey + "&command=deleteIpForwardingRule&id=" + encodedIpFwdId; + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=deleteIpForwardingRule&apikey=" + encodedApiKey + "&id=" + encodedIpFwdId + "&signature=" + encodedSignature; + + s_logger.info("Delete Ip forwarding rule with " + url); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + s_logger.info("IP forwarding rule was successfully deleted"); + + } else { + s_logger.error("IP forwarding rule creation failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + //-------------------------------------------- + // Disable Static NAT for the Source NAT Ip + //-------------------------------------------- + encodedApiKey = URLEncoder.encode(_apiKey.get(), "UTF-8"); + String encodedPublicIpId = URLEncoder.encode(_publicIpId.get(), "UTF-8"); + requestToSign = "apikey=" + encodedApiKey + "&command=disableStaticNat"+"&id=" + encodedPublicIpId; + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=disableStaticNat&apikey=" + encodedApiKey + "&id=" + encodedPublicIpId + "&signature=" + encodedSignature ; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("url is " + url); + s_logger.info("list ip addresses for user " + userId + " response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map success = getSingleValueFromXML(is, new String[] { "success" }); + s_logger.info("Disable Static NAT..success? " + success.get("success")); + } else { + s_logger.error("Disable Static NAT failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + + // ----------------------------------------- + // DISASSOCIATE IP ADDRESSES + // ----------------------------------------- + if (ipAddresses != null) { + for (String ipAddress : ipAddresses) { + requestToSign = "apikey=" + encodedApiKey + "&command=disassociateIpAddress&id=" + ipAddress; + requestToSign = requestToSign.toLowerCase(); + signature = signRequest(requestToSign, _secretKey.get()); + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + + url = developerServer + "?command=disassociateIpAddress&apikey=" + encodedApiKey + "&id=" + ipAddress + "&signature=" + encodedSignature; + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + s_logger.info("disassociate ip address [" + userId + "/" + ipAddress + "] response code: " + responseCode); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element disassocipel = queryAsyncJobResult(server, input); + Map success = getSingleValueFromXML(disassocipel, new String[] {"success"}); + // Map success = getSingleValueFromXML(input, new String[] { "success" }); + s_logger.info("disassociate ip address..success? " + success.get("success")); + } else { + s_logger.error("disassociate ip address failed with error code: " + responseCode + ". Following URL was sent: " + url); + return responseCode; + } + } + } + } + _linuxIP.set(""); + _linuxIpId.set(""); + _linuxVmId.set(""); + _linuxPassword.set(""); + _windowsIP.set(""); + _windowsIpId.set(""); + _windowsVmId.set(""); + _secretKey.set(""); + _apiKey.set(""); + _userId.set(Long.parseLong("0")); + _account.set(""); + _domainRouterId.set(""); + return responseCode; + } + + public static String signRequest(String request, String key) { + try { + Mac mac = Mac.getInstance("HmacSHA1"); + SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacSHA1"); + mac.init(keySpec); + mac.update(request.getBytes()); + byte[] encryptedBytes = mac.doFinal(); + return Base64.encodeBytes(encryptedBytes); + } catch (Exception ex) { + s_logger.error("unable to sign request", ex); + } + return null; + } + + private static String sshWinTest(String host) { + if (host == null) { + s_logger.info("Did not receive a host back from test, ignoring win ssh test"); + return null; + } + + // We will retry 5 times before quitting + int retry = 1; + + while (true) { + try { + if (retry > 0) { + s_logger.info("Retry attempt : " + retry + " ...sleeping 300 seconds before next attempt. Account is " + _account.get()); + Thread.sleep(300000); + } + + s_logger.info("Attempting to SSH into windows host " + host + " with retry attempt: " + retry + " for account " + _account.get()); + + Connection conn = new Connection(host); + conn.connect(null, 60000, 60000); + + s_logger.info("User " + _account.get() + " ssHed successfully into windows host " + host); + boolean success = false; + boolean isAuthenticated = conn.authenticateWithPassword("Administrator", "password"); + if (isAuthenticated == false) { + return "Authentication failed"; + } else { + s_logger.info("Authentication is successfull"); + } + + try { + SCPClient scp = new SCPClient(conn); + scp.put("wget.exe", "wget.exe", "C:\\Users\\Administrator", "0777"); + s_logger.info("Successfully put wget.exe file"); + } catch (Exception ex) { + s_logger.error("Unable to put wget.exe " + ex); + } + + if (conn == null) { + s_logger.error("Connection is null"); + } + Session sess = conn.openSession(); + + s_logger.info("User + " + _account.get() + " executing : wget http://" + downloadUrl); + String downloadCommand = "wget http://" + downloadUrl + " && dir dump.bin"; + sess.execCommand(downloadCommand); + + InputStream stdout = sess.getStdout(); + InputStream stderr = sess.getStderr(); + + byte[] buffer = new byte[8192]; + while (true) { + if ((stdout.available() == 0) && (stderr.available() == 0)) { + int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA | ChannelCondition.EOF, 120000); + + if ((conditions & ChannelCondition.TIMEOUT) != 0) { + s_logger.info("Timeout while waiting for data from peer."); + return null; + } + + if ((conditions & ChannelCondition.EOF) != 0) { + if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) { + break; + } + } + } + + while (stdout.available() > 0) { + success = true; + int len = stdout.read(buffer); + if (len > 0) // this check is somewhat paranoid + s_logger.info(new String(buffer, 0, len)); + } + + while (stderr.available() > 0) { + /* int len = */stderr.read(buffer); + } + } + sess.close(); + conn.close(); + + if (success) { + return null; + } else { + retry++; + if (retry == MAX_RETRY_WIN) { + return "SSH Windows Network test fail for account " + _account.get(); + } + } + } catch (Exception e) { + s_logger.error(e); + retry++; + if (retry == MAX_RETRY_WIN) { + return "SSH Windows Network test fail with error " + e.getMessage(); + } + } + } + } + + private static String sshTest(String host, String password, String snapshot_test) { + int i = 0; + if (host == null) { + s_logger.info("Did not receive a host back from test, ignoring ssh test"); + return null; + } + + if (password == null) { + s_logger.info("Did not receive a password back from test, ignoring ssh test"); + return null; + } + + // We will retry 5 times before quitting + String result = null; + int retry = 0; + + while (true) { + try { + if (retry > 0) { + s_logger.info("Retry attempt : " + retry + " ...sleeping 120 seconds before next attempt. Account is " + _account.get()); + Thread.sleep(120000); + } + + s_logger.info("Attempting to SSH into linux host " + host + " with retry attempt: " + retry + ". Account is " + _account.get()); + + Connection conn = new Connection(host); + conn.connect(null, 60000, 60000); + + s_logger.info("User + " + _account.get() + " ssHed successfully into linux host " + host); + + boolean isAuthenticated = conn.authenticateWithPassword("root", password); + + if (isAuthenticated == false) { + s_logger.info("Authentication failed for root with password" + password); + return "Authentication failed"; + + } + + boolean success = false; + String linuxCommand = null; + + if (i % 10 == 0) + linuxCommand = "rm -rf *; wget http://" + downloadUrl + " && ls -al dump.bin"; + else + linuxCommand = "wget http://" + downloadUrl + " && ls -al dump.bin"; + + Session sess = conn.openSession(); + s_logger.info("User " + _account.get() + " executing : " + linuxCommand); + sess.execCommand(linuxCommand); + + InputStream stdout = sess.getStdout(); + InputStream stderr = sess.getStderr(); + + byte[] buffer = new byte[8192]; + while (true) { + if ((stdout.available() == 0) && (stderr.available() == 0)) { + int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA | ChannelCondition.EOF, 120000); + + if ((conditions & ChannelCondition.TIMEOUT) != 0) { + s_logger.info("Timeout while waiting for data from peer."); + return null; + } + + if ((conditions & ChannelCondition.EOF) != 0) { + if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) { + break; + } + } + } + + while (stdout.available() > 0) { + success = true; + int len = stdout.read(buffer); + if (len > 0) // this check is somewhat paranoid + s_logger.info(new String(buffer, 0, len)); + } + + while (stderr.available() > 0) { + /* int len = */stderr.read(buffer); + } + } + + sess.close(); + conn.close(); + + if (!success) { + retry++; + if (retry == MAX_RETRY_LINUX) { + result = "SSH Linux Network test fail"; + } + } + + if (snapshot_test.equals("no")) + return result; + else { + Long sleep = 300000L; + s_logger.info("Sleeping for " + sleep / 1000 / 60 + "minutes before executing next ssh test"); + Thread.sleep(sleep); + } + } catch (Exception e) { + retry++; + s_logger.error("SSH Linux Network test fail with error"); + if ((retry == MAX_RETRY_LINUX) && (snapshot_test.equals("no"))) { + return "SSH Linux Network test fail with error " + e.getMessage(); + } + } + i++; + } + } + + public static String createMD5Password(String password) { + MessageDigest md5; + + try { + md5 = MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException e) { + throw new CloudRuntimeException("Error", e); + } + + md5.reset(); + BigInteger pwInt = new BigInteger(1, md5.digest(password.getBytes())); + + // make sure our MD5 hash value is 32 digits long... + StringBuffer sb = new StringBuffer(); + String pwStr = pwInt.toString(16); + int padding = 32 - pwStr.length(); + for (int i = 0; i < padding; i++) { + sb.append('0'); + } + sb.append(pwStr); + return sb.toString(); + } + + public static Element queryAsyncJobResult(String host, InputStream inputStream) { + Element returnBody = null; + + Map values = getSingleValueFromXML(inputStream, new String[] { "jobid" }); + String jobId = values.get("jobid"); + + if (jobId == null) { + s_logger.error("Unable to get a jobId"); + return null; + } + + // s_logger.info("Job id is " + jobId); + String resultUrl = host + "?command=queryAsyncJobResult&jobid=" + jobId; + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(resultUrl); + while (true) { + try { + client.executeMethod(method); + // s_logger.info("Method is executed successfully. Following url was sent " + resultUrl); + InputStream is = method.getResponseBodyAsStream(); + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document doc = builder.parse(is); + returnBody = doc.getDocumentElement(); + doc.getDocumentElement().normalize(); + Element jobStatusTag = (Element) returnBody.getElementsByTagName("jobstatus").item(0); + String jobStatus = jobStatusTag.getTextContent(); + if (jobStatus.equals("0")) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + } else { + break; + } + + } catch (Exception ex) { + s_logger.error(ex); + } + } + return returnBody; + } + +} diff --git a/test/src/com/cloud/test/stress/WgetTest.java b/test/src/com/cloud/test/stress/WgetTest.java new file mode 100644 index 00000000000..beadcc866b9 --- /dev/null +++ b/test/src/com/cloud/test/stress/WgetTest.java @@ -0,0 +1,164 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.stress; + +import java.io.InputStream; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import org.apache.log4j.Logger; + +import com.trilead.ssh2.ChannelCondition; +import com.trilead.ssh2.Connection; +import com.trilead.ssh2.Session; + +public class WgetTest { + + public static int MAX_RETRY_LINUX = 1; + public static final Logger s_logger = Logger.getLogger(WgetTest.class.getName()); + public static String host = ""; + public static String password = "rs-ccb35ea5"; + + + + public static void main (String[] args) { + + // Parameters + List argsList = Arrays.asList(args); + Iterator iter = argsList.iterator(); + while (iter.hasNext()) { + String arg = iter.next(); + // host + if (arg.equals("-h")) { + host = iter.next(); + } + //password + + if (arg.equals("-p")) { + password = iter.next(); + } + + } + + int i = 0; + if (host == null || host.equals("")) { + s_logger + .info("Did not receive a host back from test, ignoring ssh test"); + System.exit(2); + } + + if (password == null){ + s_logger.info("Did not receive a password back from test, ignoring ssh test"); + System.exit(2); + } + int retry = 0; + + try { + if (retry > 0) { + s_logger.info("Retry attempt : " + retry + + " ...sleeping 120 seconds before next attempt"); + Thread.sleep(120000); + } + + s_logger.info("Attempting to SSH into linux host " + host + + " with retry attempt: " + retry); + + Connection conn = new Connection(host); + conn.connect(null, 60000, 60000); + + s_logger.info("User + ssHed successfully into linux host " + host); + + boolean isAuthenticated = conn.authenticateWithPassword("root", + password); + + if (isAuthenticated == false) { + s_logger.info("Authentication failed for root with password" + password); + System.exit(2); + } + + boolean success = false; + String linuxCommand = null; + + if (i % 10 == 0) + linuxCommand = "rm -rf *; wget http://192.168.1.250/dump.bin && ls -al dump.bin"; + else + linuxCommand = "wget http://192.168.1.250/dump.bin && ls -al dump.bin"; + + Session sess = conn.openSession(); + sess.execCommand(linuxCommand); + + InputStream stdout = sess.getStdout(); + InputStream stderr = sess.getStderr(); + + + byte[] buffer = new byte[8192]; + while (true) { + if ((stdout.available() == 0) && (stderr.available() == 0)) { + int conditions = sess.waitForCondition( + ChannelCondition.STDOUT_DATA + | ChannelCondition.STDERR_DATA + | ChannelCondition.EOF, 120000); + + if ((conditions & ChannelCondition.TIMEOUT) != 0) { + s_logger + .info("Timeout while waiting for data from peer."); + System.exit(2); + } + + if ((conditions & ChannelCondition.EOF) != 0) { + if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) { + break; + } + } + } + + while (stdout.available() > 0) { + success = true; + int len = stdout.read(buffer); + if (len > 0) // this check is somewhat paranoid + s_logger.info(new String(buffer, 0, len)); + } + + while (stderr.available() > 0) { + /* int len = */stderr.read(buffer); + } + } + + sess.close(); + conn.close(); + + if (!success) { + retry++; + if (retry == MAX_RETRY_LINUX) { + System.exit(2); + } + } + } catch (Exception e) { + retry++; + s_logger.error("SSH Linux Network test fail with error"); + if (retry == MAX_RETRY_LINUX) { + s_logger.error("Ssh test failed"); + System.exit(2); + } + } + } + +} diff --git a/test/src/com/cloud/test/ui/AbstractSeleniumTestCase.java b/test/src/com/cloud/test/ui/AbstractSeleniumTestCase.java new file mode 100644 index 00000000000..01f3875db56 --- /dev/null +++ b/test/src/com/cloud/test/ui/AbstractSeleniumTestCase.java @@ -0,0 +1,63 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.ui; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import junit.framework.TestSuite; +import junit.framework.Test; +import junit.framework.JUnit4TestAdapter; +import org.openqa.selenium.server.SeleniumServer; +import org.openqa.selenium.server.RemoteControlConfiguration; +import org.junit.runners.Suite; + +import com.thoughtworks.selenium.DefaultSelenium; + +@RunWith(JUnit4.class) +public abstract class AbstractSeleniumTestCase { + protected static DefaultSelenium selenium; + private static SeleniumServer seleniumServer; + + @BeforeClass + public static void setUp() throws Exception { + System.out.println("*** Starting selenium ... ***"); + RemoteControlConfiguration seleniumConfig = new RemoteControlConfiguration(); + seleniumConfig.setPort(4444); + seleniumServer = new SeleniumServer(seleniumConfig); + seleniumServer.start(); + + String host = System.getProperty("myParam", "localhost"); + selenium = createSeleniumClient("http://" + host + ":" + "8080/client/"); + selenium.start(); + System.out.println("*** Started selenium ***"); + } + + @AfterClass + public static void tearDown() throws Exception { + selenium.stop(); + } + + protected static DefaultSelenium createSeleniumClient(String url) + throws Exception { + return new DefaultSelenium("localhost", 4444, "*firefox", url); + } +} diff --git a/test/src/com/cloud/test/ui/AddAndDeleteAISO.java b/test/src/com/cloud/test/ui/AddAndDeleteAISO.java new file mode 100644 index 00000000000..4224a049f16 --- /dev/null +++ b/test/src/com/cloud/test/ui/AddAndDeleteAISO.java @@ -0,0 +1,120 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.ui; + +import org.junit.Test; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import com.cloud.test.ui.AbstractSeleniumTestCase; +import com.thoughtworks.selenium.SeleniumException; + +public class AddAndDeleteAISO extends AbstractSeleniumTestCase { + + @Test + public void testAddAndDeleteISO() throws Exception { + try { + selenium.open("/client/"); + selenium.type("account_username", "admin"); + selenium.type("account_password", "password"); + selenium.click("loginbutton"); + Thread.sleep(3000); + assertTrue(selenium.isTextPresent("admin")); + selenium.click("//div[@id='leftmenu_templates']/div"); + selenium.click("//div[@id='leftmenu_submenu_my_iso']/div/div[2]"); + Thread.sleep(3000); + selenium.click("label"); + + selenium.type("add_iso_name", "abc"); + selenium.type("add_iso_display_text", "abc"); + String iso_url = System.getProperty("add_iso_url", "http://10.91.28.6/ISO/Fedora-11-i386-DVD.iso"); + selenium.type("add_iso_url", iso_url); + String iso_zone = System.getProperty("add_iso_zone", "All Zones"); + selenium.select("add_iso_zone", "label="+iso_zone); + String iso_os_type = System.getProperty("add_iso_os_type", "Fedora 11"); + selenium.select("add_iso_os_type", "label="+iso_os_type); + selenium.click("//div[28]/div[11]/button[1]"); + Thread.sleep(3000); + int i=1; + try + { + for(;;i++) + { + System.out.println("i= "+i); + selenium.click("//div[" +i+ "]/div/div[2]/span/span"); + } + } + catch(Exception ex) { + } + + for (int second = 0;; second++) { + if (second >= 60) fail("timeout"); + try { if (selenium.isVisible("//div[@id='after_action_info_container_on_top']")) break; } catch (Exception e) {} + Thread.sleep(10000); + } + + assertTrue(selenium.isTextPresent("Adding succeeded")); + Thread.sleep(3000); + int status=1; + while(!selenium.isTextPresent("Ready")) + { + for(int j =1;j<=i;j++) + + { + if (selenium.isTextPresent("Ready")) + { + status=0; + break; + } + selenium.click("//div["+j+"]/div/div[2]/span/span"); + } + if(status==0){ + break; + } + else + { + selenium.click("//div[@id='leftmenu_submenu_featured_iso']/div/div[2]"); + Thread.sleep(3000); + selenium.click("//div[@id='leftmenu_submenu_my_iso']/div/div[2]"); + Thread.sleep(3000); + } + + } + selenium.click("link=Delete ISO"); + selenium.click("//div[28]/div[11]/button[1]"); + for (int second = 0;; second++) { + if (second >= 60) fail("timeout"); + try { if (selenium.isVisible("after_action_info_container_on_top")) break; } catch (Exception e) {} + Thread.sleep(1000); + } + + assertTrue(selenium.isTextPresent("Delete ISO action succeeded")); + selenium.click("main_logout"); + selenium.waitForPageToLoad("30000"); + assertTrue(selenium.isTextPresent("Welcome to Management Console")); + + } catch (SeleniumException ex) { + + System.err.println(ex.getMessage()); + fail(ex.getMessage()); + + throw ex; + } + } +} \ No newline at end of file diff --git a/test/src/com/cloud/test/ui/AddAndDeleteATemplate.java b/test/src/com/cloud/test/ui/AddAndDeleteATemplate.java new file mode 100644 index 00000000000..3dccf197235 --- /dev/null +++ b/test/src/com/cloud/test/ui/AddAndDeleteATemplate.java @@ -0,0 +1,118 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.ui; + +import org.junit.Test; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import com.cloud.test.ui.AbstractSeleniumTestCase; +import com.thoughtworks.selenium.SeleniumException; + +public class AddAndDeleteATemplate extends AbstractSeleniumTestCase { + + @Test + public void testAddAndDeleteTemplate() throws Exception { + try { + selenium.open("/client/"); + selenium.type("account_username", "admin"); + selenium.type("account_password", "password"); + selenium.click("loginbutton"); + Thread.sleep(3000); + assertTrue(selenium.isTextPresent("admin")); + selenium.click("//div[@id='leftmenu_templates']/div"); + selenium.click("//div[@id='leftmenu_submenu_my_template']/div/div[2]"); + Thread.sleep(3000); + selenium.click("label"); + selenium.type("add_template_name", "abc"); + selenium.type("add_template_display_text", "abc"); + String template_url = System.getProperty("add_template_url", "http://10.91.28.6/templates/centos53-x86_64/latest/f59f18fb-ae94-4f97-afd2-f84755767aca.vhd.bz2"); + selenium.type("add_template_url", template_url); + String template_zone = System.getProperty("add_template_zone", "All Zones"); + selenium.select("add_template_zone", "label="+template_zone); + String template_os_type = System.getProperty("add_template_os_type", "CentOS 5.3 (32-bit)"); + selenium.select("add_template_os_type", "label="+template_os_type); + selenium.click("//div[28]/div[11]/button[1]"); + Thread.sleep(3000); + int i=1; + try + { + for(;;i++) + { + System.out.println("i= "+i); + selenium.click("//div[" +i+ "]/div/div[2]/span/span"); + } + } + catch(Exception ex) { + } + + for (int second = 0;; second++) { + if (second >= 60) fail("timeout"); + try { if (selenium.isVisible("//div[@id='after_action_info_container_on_top']")) break; } catch (Exception e) {} + Thread.sleep(10000); + } + + assertTrue(selenium.isTextPresent("Adding succeeded")); + Thread.sleep(3000); + int status=1; + while(!selenium.isTextPresent("Ready")) + { + for(int j =1;j<=i;j++) + + { + if (selenium.isTextPresent("Ready")) + { + status=0; + break; + } + selenium.click("//div["+j+"]/div/div[2]/span/span"); + } + if(status==0){ + break; + } + else + { + selenium.click("//div[@id='leftmenu_submenu_featured_template']/div/div[2]"); + Thread.sleep(3000); + selenium.click("//div[@id='leftmenu_submenu_my_template']/div/div[2]"); + Thread.sleep(3000); + } + + } + selenium.click("link=Delete Template"); + selenium.click("//div[28]/div[11]/button[1]"); + for (int second = 0;; second++) { + if (second >= 60) fail("timeout"); + try { if (selenium.isVisible("after_action_info_container_on_top")) break; } catch (Exception e) {} + Thread.sleep(1000); + } + + assertTrue(selenium.isTextPresent("Delete Template action succeeded")); + selenium.click("main_logout"); + selenium.waitForPageToLoad("30000"); + assertTrue(selenium.isTextPresent("Welcome to Management Console")); + } catch (SeleniumException ex) { + + System.err.println(ex.getMessage()); + fail(ex.getMessage()); + + throw ex; + } + } +} \ No newline at end of file diff --git a/test/src/com/cloud/test/ui/UIScenarioTest.java b/test/src/com/cloud/test/ui/UIScenarioTest.java new file mode 100644 index 00000000000..291332302a1 --- /dev/null +++ b/test/src/com/cloud/test/ui/UIScenarioTest.java @@ -0,0 +1,87 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.ui; + +import org.junit.Test; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import com.cloud.test.ui.AbstractSeleniumTestCase; +import com.thoughtworks.selenium.SeleniumException; + +public class UIScenarioTest extends AbstractSeleniumTestCase { + + @Test + public void testLoginStartStopVMScenario() throws Exception { + try { + selenium.open("/client/"); + selenium.type("account_username", "admin"); + selenium.type("account_password", "password"); + selenium.click("loginbutton"); + Thread.sleep(3000); + assertTrue(selenium.isTextPresent("admin")); + selenium.click("//div[@id='leftmenu_instances']/div"); + selenium + .click("//div[@id='leftmenu_instances_stopped_instances']/div/span"); + + Thread.sleep(3000); + selenium.click("//div[@id='midmenu_startvm_link']/div/div[2]"); + selenium.click("//div[39]/div[11]/button[1]"); + + for (int second = 0;; second++) { + if (second >= 60) + fail("timeout"); + try { + if (selenium.isVisible("//div/p[@id='after_action_info']")) + break; + } catch (Exception e) { + } + Thread.sleep(10000); + } + assertTrue(selenium + .isTextPresent("Start Instance action succeeded")); + selenium + .click("//div[@id='leftmenu_instances_running_instances']/div/span"); + + Thread.sleep(3000); + selenium.click("//div[@id='midmenu_stopvm_link']/div/div[2]"); + selenium.click("//div[39]/div[11]/button[1]"); + for (int second = 0;; second++) { + if (second >= 60) + fail("timeout"); + try { + if (selenium.isVisible("//div/p[@id='after_action_info']")) + break; + } catch (Exception e) { + } + Thread.sleep(10000); + } + + assertTrue(selenium.isTextPresent("Stop Instance action succeeded")); + selenium.click("main_logout"); + selenium.waitForPageToLoad("30000"); + assertTrue(selenium.isTextPresent("Welcome to Management Console")); + + } catch (SeleniumException ex) { + fail(ex.getMessage()); + System.err.println(ex.getMessage()); + throw ex; + } + } +} diff --git a/test/src/com/cloud/test/utils/ConsoleProxy.java b/test/src/com/cloud/test/utils/ConsoleProxy.java new file mode 100644 index 00000000000..46bc99692aa --- /dev/null +++ b/test/src/com/cloud/test/utils/ConsoleProxy.java @@ -0,0 +1,117 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.utils; + +import java.io.BufferedReader; +import java.io.IOException; + +import org.apache.log4j.Logger; + +import com.cloud.utils.script.OutputInterpreter; +import com.cloud.utils.script.Script; + +public class ConsoleProxy implements Runnable { + public static String proxyIp; + private String command; + private int connectionsMade; + private long responseTime; + public static final Logger s_logger = Logger.getLogger(ConsoleProxy.class + .getClass()); + + public ConsoleProxy(String port, String sid, String host) { + this.command = "https://" + proxyIp + + ".realhostip.com:8000/getscreen?w=100&h=75&host=" + host + + "&port=" + port + "&sid=" + sid; + s_logger.info("Command for a console proxy is " + this.command); + this.connectionsMade=0; + this.responseTime=0; + } + + public int getConnectionsMade() { + return this.connectionsMade; + } + + public long getResponseTime() { + return this.responseTime; + } + + public void run() { + while (true){ + + Script myScript = new Script("wget"); + myScript.add(command); + myScript.execute(); + long begin = System.currentTimeMillis(); + wgetInt process = new wgetInt(); + String response = myScript.execute(process); + long end = process.getEnd(); + if (response!=null){ + s_logger.info("Content lenght is incorrect: "+response); + } + + long duration = (end - begin); + this.connectionsMade++; + this.responseTime=this.responseTime+duration; + try{ + Thread.sleep(1000); + }catch (InterruptedException e){ + + } + + } + } + + public class wgetInt extends OutputInterpreter { + private long end; + + public long getEnd() { + return end; + } + + public void setEnd(long end) { + this.end = end; + } + + @Override + public String interpret(BufferedReader reader) throws IOException { + // TODO Auto-generated method stub + end = System.currentTimeMillis(); + String status = null; + String line = null; + while ((line = reader.readLine()) != null) { + int index = line.indexOf("Length:"); + if (index == -1) { + continue; + } + else{ + int index1 = line.indexOf("Length: 1827"); + if (index1 == -1) { + return status; + } + else + status=line; + } + + } + return status; + } + + } +} diff --git a/test/src/com/cloud/test/utils/IpSqlGenerator.java b/test/src/com/cloud/test/utils/IpSqlGenerator.java new file mode 100644 index 00000000000..cfde5f96f3d --- /dev/null +++ b/test/src/com/cloud/test/utils/IpSqlGenerator.java @@ -0,0 +1,91 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.utils; + +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.util.StringTokenizer; + +public class IpSqlGenerator { + public static void main (String[] args) { + try { + if (args.length != 5) { + System.out.println("Usage -- generate-ip.sh "); + System.out.println("Example -- generate-ip.sh public 192.168.1.1 192.168.1.255 1 1"); + System.out.println(" will generate ips ranging from public ips 192.168.1.1 to 192.168.1.255 for dc 1 and pod 1"); + return; + } + + String type = args[0]; + + StringTokenizer st = new StringTokenizer(args[1], "."); + int ipS1 = Integer.parseInt(st.nextToken()); + int ipS2 = Integer.parseInt(st.nextToken()); + int ipS3 = Integer.parseInt(st.nextToken()); + int ipS4 = Integer.parseInt(st.nextToken()); + + st = new StringTokenizer(args[2], "."); + int ipE1 = Integer.parseInt(st.nextToken()); + int ipE2 = Integer.parseInt(st.nextToken()); + int ipE3 = Integer.parseInt(st.nextToken()); + int ipE4 = Integer.parseInt(st.nextToken()); + + String dcId = args[3]; + String podId = args[4]; + + if (type.equals("private")) { + FileOutputStream fs = new FileOutputStream(new File("private-ips.sql")); + DataOutputStream out = new DataOutputStream(fs); + for (int i = ipS1; i <= ipE1; i++) { + for (int j = ipS2; j <= ipE2; j++) { + for (int k = ipS3; k <= ipE3; k++) { + for (int l = ipS4; l <= ipE4; l++) { + out.writeBytes("INSERT INTO `vmops`.`dc_ip_address_alloc` (ip_address, data_center_id, pod_id) VALUES ('" + + i + "." + j + "." + k + "." + l + "'," + dcId + "," + podId + ");\r\n"); + } + } + } + } + out.writeBytes("\r\n"); + out.flush(); + out.close(); + } else { + FileOutputStream fs = new FileOutputStream(new File("public-ips.sql")); + DataOutputStream out = new DataOutputStream(fs); + for (int i = ipS1; i <= ipE1; i++) { + for (int j = ipS2; j <= ipE2; j++) { + for (int k = ipS3; k <= ipE3; k++) { + for (int l = ipS4; l <= ipE4; l++) { + out.writeBytes("INSERT INTO `vmops`.`user_ip_address` (ip_address, data_center_id) VALUES ('" + + i + "." + j + "." + k + "." + l + "'," + dcId + ");\r\n"); + } + } + } + } + out.writeBytes("\r\n"); + out.flush(); + out.close(); + } + } catch (Exception e) { + + } + } +} diff --git a/test/src/com/cloud/test/utils/ProxyLoadTemp.java b/test/src/com/cloud/test/utils/ProxyLoadTemp.java new file mode 100644 index 00000000000..aae2bc8e54f --- /dev/null +++ b/test/src/com/cloud/test/utils/ProxyLoadTemp.java @@ -0,0 +1,125 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.utils; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.util.ArrayList; + +import org.apache.log4j.Logger; + + + + +public class ProxyLoadTemp { + //Read data from console.input, create a console connection instance and run it for a while + public static final Logger s_logger= Logger.getLogger(ProxyLoadTemp.class.getClass()); + public static int numThreads=0; + public static ArrayList proxyList = new ArrayList(); + public static long begin; + public static long end; + public static long sum=0; + + public ProxyLoadTemp(){ + } + + public static void main (String[] args){ + begin= System.currentTimeMillis(); + Runtime.getRuntime().addShutdownHook(new ShutdownThread(new ProxyLoadTemp())); + ConsoleProxy.proxyIp="172-16-1-101"; + + try + { + BufferedReader consoleInput = new BufferedReader(new FileReader("console.input")); + boolean eof = false; + s_logger.info("Started reading file"); + while (!eof){ + String line = consoleInput.readLine(); + s_logger.info("Line is "+line); + if (line == null){ + s_logger.info("Line "+numThreads+" is null"); + eof=true; + } + else{ + String[] result=null; + try + { + s_logger.info("Starting parsing line "+line); + result= parseLine(line, "[,]"); + s_logger.info("Line retrieved from the file is "+result[0]+" "+result[1]+" "+result[2]); + ConsoleProxy proxy = new ConsoleProxy(result[0], result[1], result[2]); + proxyList.add(proxy); + new Thread(proxy).start(); + numThreads++; + + } + catch (Exception ex){ + s_logger.warn(ex); + } + } + + } + }catch(Exception e){ + s_logger.warn(e); + } + + } + + public static class ShutdownThread extends Thread { + ProxyLoadTemp temp; + public ShutdownThread(ProxyLoadTemp temp) { + this.temp = temp; + } + public void run() { + s_logger.info("Program was running in "+numThreads+" threads"); + + for (int j=0; j. + * + */ + +package com.cloud.test.utils; + +import java.io.FileInputStream; +import java.io.IOException; +import java.net.URLEncoder; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.TreeMap; + +import org.apache.log4j.Logger; + +public class SignEC2 { + public static String url; + public static String secretkey; + public static String host; + public static String port; + public static String command; + public static String accessPoint; + public static final Logger s_logger = Logger + .getLogger(SignRequest.class.getName()); + + + public static void main (String[] args) { + // Parameters + List argsList = Arrays.asList(args); + Iterator iter = argsList.iterator(); + while (iter.hasNext()) { + String arg = iter.next(); + + if (arg.equals("-u")) { + url = iter.next(); + } + } + + Properties prop = new Properties(); + try { + prop.load(new FileInputStream("../conf/tool.properties")); + } catch (IOException ex) { + s_logger.error("Error reading from ../conf/tool.properties", ex); + System.exit(2); + } + + host = prop.getProperty("host"); + secretkey = prop.getProperty("secretkey"); + port = prop.getProperty("port"); + + + if (host == null) { + s_logger.info("Please set host in tool.properties file"); + System.exit(1); + } + + if (port == null) { + s_logger.info("Please set port in tool.properties file"); + System.exit(1); + } + + if (url == null) { + s_logger.info("Please specify url with -u option"); + System.exit(1); + } + + if (secretkey == null) { + s_logger.info("Please set secretkey in tool.properties file"); + System.exit(1); + } + + if (prop.get("apikey") == null) { + s_logger.info("Please set apikey in tool.properties file"); + System.exit(1); + } + + if (prop.get("accesspoint") == null) { + s_logger.info("Please set apikey in tool.properties file"); + System.exit(1); + } + + + + TreeMap param = new TreeMap(); + + String req = "GET\n" + host + ":" + prop.getProperty("port") + "\n/" + prop.getProperty("accesspoint") + "\n"; + String temp = ""; + param.put("AWSAccessKeyId", prop.getProperty("apikey")); + param.put("Expires",prop.getProperty("expires")); + param.put("SignatureMethod", "HmacSHA1"); + param.put("SignatureVersion", "2"); + param.put("Version", prop.getProperty("version")); + param.put("id", "1"); + + StringTokenizer str1 = new StringTokenizer (url, "&"); + while(str1.hasMoreTokens()) { + String newEl = str1.nextToken(); + StringTokenizer str2 = new StringTokenizer(newEl, "="); + String name = str2.nextToken(); + String value= str2.nextToken(); + param.put(name, value); + } + + //sort url hash map by key + Set c = param.entrySet(); + Iterator it = c.iterator(); + while (it.hasNext()) { + Map.Entry me = (Map.Entry)it.next(); + String key = (String) me.getKey(); + String value = (String) me.getValue(); + try { + temp = temp + key + "=" + URLEncoder.encode(value, "UTF-8") + "&"; + } catch (Exception ex) { + s_logger.error("Unable to set parameter " + value + " for the command " + param.get("command")); + } + + } + temp = temp.substring(0, temp.length()-1 ); + String requestToSign = req + temp; + String signature = UtilsForTest.signRequest(requestToSign, secretkey); + String encodedSignature = ""; + try { + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + } catch (Exception ex) { + s_logger.error(ex); + } + String url = "http://" + host + ":" + prop.getProperty("port") + "/" + prop.getProperty("accesspoint") + "?" + temp + "&Signature=" + encodedSignature; + s_logger.info("Url is " + url); + + } +} diff --git a/test/src/com/cloud/test/utils/SignRequest.java b/test/src/com/cloud/test/utils/SignRequest.java new file mode 100644 index 00000000000..659c11eb2dc --- /dev/null +++ b/test/src/com/cloud/test/utils/SignRequest.java @@ -0,0 +1,117 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.utils; + +import java.net.URLEncoder; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.TreeMap; + +public class SignRequest { + public static String url; + public static String apikey; + public static String secretkey; + public static String command; + + + public static void main (String[] args) { + // Parameters + List argsList = Arrays.asList(args); + Iterator iter = argsList.iterator(); + while (iter.hasNext()) { + String arg = iter.next(); + if (arg.equals("-a")) { + apikey = iter.next(); + + } + if (arg.equals("-u")) { + url = iter.next(); + } + + if (arg.equals("-s")) { + secretkey = iter.next(); + } + } + + + if (url == null) { + System.out.println("Please specify url with -u option. Example: -u \"command=listZones&id=1\""); + System.exit(1); + } + + if (apikey == null) { + System.out.println("Please specify apikey with -a option"); + System.exit(1); + } + + if (secretkey == null) { + System.out.println("Please specify secretkey with -s option"); + System.exit(1); + } + + TreeMap param = new TreeMap(); + + String temp = ""; + param.put("apikey", apikey); + + StringTokenizer str1 = new StringTokenizer (url, "&"); + while(str1.hasMoreTokens()) { + String newEl = str1.nextToken(); + StringTokenizer str2 = new StringTokenizer(newEl, "="); + String name = str2.nextToken(); + String value= str2.nextToken(); + param.put(name, value); + } + + //sort url hash map by key + Set c = param.entrySet(); + Iterator it = c.iterator(); + while (it.hasNext()) { + Map.Entry me = (Map.Entry)it.next(); + String key = (String) me.getKey(); + String value = (String) me.getValue(); + try { + temp = temp + key + "=" + URLEncoder.encode(value, "UTF-8") + "&"; + } catch (Exception ex) { + System.out.println("Unable to set parameter " + value + " for the command " + param.get("command")); + } + + } + temp = temp.substring(0, temp.length()-1 ); + String requestToSign = temp.toLowerCase(); + System.out.println("After sorting: " + requestToSign); + String signature = UtilsForTest.signRequest(requestToSign, secretkey); + System.out.println("After Base64 encoding: " + signature); + String encodedSignature = ""; + try { + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + } catch (Exception ex) { + System.out.println(ex); + } + System.out.println("After UTF8 encoding: " + encodedSignature); + String url = temp + "&signature=" + encodedSignature; + System.out.println("After sort and add signature: " + url); + + } +} diff --git a/test/src/com/cloud/test/utils/SqlDataGenerator.java b/test/src/com/cloud/test/utils/SqlDataGenerator.java new file mode 100644 index 00000000000..f2954f527bf --- /dev/null +++ b/test/src/com/cloud/test/utils/SqlDataGenerator.java @@ -0,0 +1,51 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.utils; + +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.util.Formatter; + +public class SqlDataGenerator { + public static void main (String[] args) { + try { + FileOutputStream fs = new FileOutputStream(new File("out.txt")); + + DataOutputStream out = new DataOutputStream(fs); + + for (int i = 20; i < 171; i++) { + out.writeBytes("INSERT INTO `vmops`.`dc_ip_address_alloc` (ip_address, data_center_id, pod_id) VALUES ('192.168.2."+i+"',1,1);\r\n"); + } + out.writeBytes("\r\n"); + for (int i = 1; i < 10000; i++) { + StringBuilder imagePath = new StringBuilder(); + Formatter formatter = new Formatter(imagePath); + formatter.format("%04x", i); + out.writeBytes("INSERT INTO `vmops`.`dc_vnet_alloc` (vnet, data_center_id) VALUES ('"+imagePath.toString()+"',1);\r\n"); + } + + out.flush(); + out.close(); + } catch (Exception e) { + + } + } +} diff --git a/test/src/com/cloud/test/utils/SubmitCert.java b/test/src/com/cloud/test/utils/SubmitCert.java new file mode 100644 index 00000000000..09b9f5bfbc7 --- /dev/null +++ b/test/src/com/cloud/test/utils/SubmitCert.java @@ -0,0 +1,206 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.utils; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.net.URLEncoder; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.TreeMap; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.log4j.Logger; + +public class SubmitCert { + public static String url = "Action=SetCertificate"; + public static String secretKey; + public static String apiKey; + public static String host; + public static String port; + public static String command; + public static String accessPoint; + public static String signatureMethod; + public static String fileName = "tool.properties"; + public static String certFileName; + public static String cert; + public static final Logger s_logger = Logger + .getLogger(SubmitCert.class.getName()); + + + public static void main (String[] args) { + // Parameters + List argsList = Arrays.asList(args); + Iterator iter = argsList.iterator(); + while (iter.hasNext()) { + String arg = iter.next(); + + if (arg.equals("-c")) { + certFileName = iter.next(); + } + + if (arg.equals("-s")) { + secretKey = iter.next(); + } + + if (arg.equals("-a")) { + apiKey = iter.next(); + } + + if (arg.equals("-action")) { + url = "Action=" + iter.next(); + } + } + + Properties prop = new Properties(); + try { + prop.load(new FileInputStream("conf/tool.properties")); + } catch (IOException ex) { + s_logger.error("Error reading from conf/tool.properties", ex); + System.exit(2); + } + + host = prop.getProperty("host"); + port = prop.getProperty("port"); + + if (url.equals("Action=SetCertificate") && certFileName == null) { + s_logger.error("Please set path to certificate (including file name) with -c option"); + System.exit(1); + } + + if (secretKey == null) { + s_logger.error("Please set secretkey with -s option"); + System.exit(1); + } + + if (apiKey == null) { + s_logger.error("Please set apikey with -a option"); + System.exit(1); + } + + if (host == null) { + s_logger.error("Please set host in tool.properties file"); + System.exit(1); + } + + if (port == null) { + s_logger.error("Please set port in tool.properties file"); + System.exit(1); + } + + + TreeMap param = new TreeMap(); + + String req = "GET\n" + host + ":" + prop.getProperty("port") + "\n/" + prop.getProperty("accesspoint") + "\n"; + String temp = ""; + + if (certFileName != null) { + cert = readCert(certFileName); + param.put("cert", cert); + } + + param.put("AWSAccessKeyId", apiKey); + param.put("Expires",prop.getProperty("expires")); + param.put("SignatureMethod", prop.getProperty("signaturemethod")); + param.put("SignatureVersion", "2"); + param.put("Version", prop.getProperty("version")); + + StringTokenizer str1 = new StringTokenizer (url, "&"); + while(str1.hasMoreTokens()) { + String newEl = str1.nextToken(); + StringTokenizer str2 = new StringTokenizer(newEl, "="); + String name = str2.nextToken(); + String value= str2.nextToken(); + param.put(name, value); + } + + //sort url hash map by key + Set c = param.entrySet(); + Iterator it = c.iterator(); + while (it.hasNext()) { + Map.Entry me = (Map.Entry)it.next(); + String key = (String) me.getKey(); + String value = (String) me.getValue(); + try { + temp = temp + key + "=" + URLEncoder.encode(value, "UTF-8") + "&"; + } catch (Exception ex) { + s_logger.error("Unable to set parameter " + value + " for the command " + param.get("command"), ex); + } + + } + temp = temp.substring(0, temp.length()-1 ); + String requestToSign = req + temp; + String signature = UtilsForTest.signRequest(requestToSign, secretKey); + String encodedSignature = ""; + try { + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + } catch (Exception ex) { + ex.printStackTrace(); + } + + String url = "http://" + host + ":" + prop.getProperty("port") + "/" + prop.getProperty("accesspoint") + "?" + temp + "&Signature=" + encodedSignature; + s_logger.info("Sending request with url: " + url + "\n"); + sendRequest(url); + } + + public static String readCert(String filePath) { + try { + StringBuffer fileData = new StringBuffer(1000); + BufferedReader reader = new BufferedReader( + new FileReader(filePath)); + char[] buf = new char[1024]; + int numRead=0; + while((numRead=reader.read(buf)) != -1){ + String readData = String.valueOf(buf, 0, numRead); + fileData.append(readData); + buf = new char[1024]; + } + reader.close(); + return fileData.toString(); + } catch (Exception ex) { + s_logger.error(ex); + return null; + } + } + + public static void sendRequest(String url) { + try { + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + int responseCode = client.executeMethod(method); + String is = method.getResponseBodyAsString(); + s_logger.info("Response code " + responseCode + ": " + is); + } catch (Exception ex) { + ex.printStackTrace(); + } + + } + +} diff --git a/test/src/com/cloud/test/utils/TestClient.java b/test/src/com/cloud/test/utils/TestClient.java new file mode 100644 index 00000000000..6fb03b7a831 --- /dev/null +++ b/test/src/com/cloud/test/utils/TestClient.java @@ -0,0 +1,384 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.utils; + +import java.io.InputStream; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Random; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.log4j.Logger; +import org.apache.log4j.NDC; + +import com.trilead.ssh2.ChannelCondition; +import com.trilead.ssh2.Connection; +import com.trilead.ssh2.SCPClient; +import com.trilead.ssh2.Session; + +public class TestClient { + private static long sleepTime = 180000L; // default 0 + private static boolean cleanUp = true; + public static final Logger s_logger = Logger.getLogger(TestClient.class.getName()); + private static boolean repeat = true; + private static int numOfUsers = 0; + private static String[] users = null; + private static boolean internet = true; + + private static final int MAX_RETRY_LINUX = 5; + private static final int MAX_RETRY_WIN = 10; + + public static void main (String[] args) { + String host = "http://localhost"; + String port = "8080"; + String testUrl = "/client/test"; + int numThreads = 1; + + try { + // Parameters + List argsList = Arrays.asList(args); + Iterator iter = argsList.iterator(); + while (iter.hasNext()) { + String arg = iter.next(); + // host + if (arg.equals("-h")) { + host = "http://" + iter.next(); + } + + if (arg.equals("-p")) { + port = iter.next(); + } + + if (arg.equals("-t")) { + numThreads = Integer.parseInt(iter.next()); + } + + if (arg.equals("-s")) { + sleepTime = Long.parseLong(iter.next()); + } + + if (arg.equals("-c")) { + cleanUp = Boolean.parseBoolean(iter.next()); + if (!cleanUp) sleepTime = 0L; // no need to wait if we don't ever cleanup + } + + if (arg.equals("-r")) { + repeat = Boolean.parseBoolean(iter.next()); + } + + if (arg.equals("-u")) { + numOfUsers = Integer.parseInt(iter.next()); + } + + if (arg.equals("-i")) { + internet = Boolean.parseBoolean(iter.next()); + } + } + + final String server = host+":"+port+testUrl; + s_logger.info("Starting test against server: " + server + " with " + numThreads + " thread(s)"); + if (cleanUp) s_logger.info("Clean up is enabled, each test will wait " + sleepTime + " ms before cleaning up"); + + if (numOfUsers > 0) { + s_logger.info("Pre-generating users for test of size : " + numOfUsers); + users = new String[numOfUsers]; + Random ran = new Random(); + for (int i = 0; i < numOfUsers; i++) { + users[i] = Math.abs(ran.nextInt()) + "-user"; + } + } + + for (int i = 0; i < numThreads; i++) { + new Thread(new Runnable() { + public void run() { + do { + String username = null; + try { + long now = System.currentTimeMillis(); + Random ran = new Random(); + if (users != null) { + username = users[Math.abs(ran.nextInt()) % numOfUsers]; + } else { + username = Math.abs(ran.nextInt())+"-user"; + } + NDC.push(username); + + String url = server+"?email="+username+"&password="+username+"&command=deploy"; + s_logger.info("Launching test for user: " + username + " with url: " + url); + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + int responseCode = client.executeMethod(method); + boolean success = false; + String reason = null; + if (responseCode == 200) { + if (internet) { + s_logger.info("Deploy successful...waiting 5 minute before SSH tests"); + Thread.sleep(300000L); // Wait 60 seconds so the linux VM can boot up. + + s_logger.info("Begin Linux SSH test"); + reason = sshTest(method.getResponseHeader("linuxIP").getValue()); + + if (reason == null) { + s_logger.info("Linux SSH test successful"); + s_logger.info("Begin Windows SSH test"); + reason = sshWinTest(method.getResponseHeader("windowsIP").getValue()); + } + } + if (reason == null) { + if (internet) { + s_logger.info("Windows SSH test successful"); + } else { + s_logger.info("deploy test successful....now cleaning up"); + if (cleanUp) { + s_logger.info("Waiting " + sleepTime + " ms before cleaning up vms"); + Thread.sleep(sleepTime); + } else { + success = true; + } + } + if (users == null) { + s_logger.info("Sending cleanup command"); + url = server+"?email="+username+"&password="+username+"&command=cleanup"; + } else { + s_logger.info("Sending stop DomR / destroy VM command"); + url = server+"?email="+username+"&password="+username+"&command=stopDomR"; + } + method = new GetMethod(url); + responseCode = client.executeMethod(method); + if (responseCode == 200) { + success = true; + } else { + reason = method.getStatusText(); + } + } else { + // Just stop but don't destroy the VMs/Routers + s_logger.info("SSH test failed with reason '" + reason + "', stopping VMs"); + url = server+"?email="+username+"&password="+username+"&command=stop"; + responseCode = client.executeMethod(new GetMethod(url)); + } + } else { + // Just stop but don't destroy the VMs/Routers + reason = method.getStatusText(); + s_logger.info("Deploy test failed with reason '" + reason + "', stopping VMs"); + url = server+"?email="+username+"&password="+username+"&command=stop"; + client.executeMethod(new GetMethod(url)); + } + + if (success) { + s_logger.info("***** Completed test for user : " + username + " in " + ((System.currentTimeMillis() - now) / 1000L) + " seconds"); + } else { + s_logger.info("##### FAILED test for user : " + username + " in " + ((System.currentTimeMillis() - now) / 1000L) + " seconds with reason : " + reason); + } + } catch (Exception e) { + s_logger.warn("Error in thread", e); + try { + HttpClient client = new HttpClient(); + String url = server+"?email="+username+"&password="+username+"&command=stop"; + client.executeMethod(new GetMethod(url)); + } catch (Exception e1) { + } + } finally { + NDC.clear(); + } + } while (repeat); + } + }).start(); + } + } catch (Exception e) { + s_logger.error(e); + } + } + + private static String sshWinTest(String host) { + if (host == null) { + s_logger.info("Did not receive a host back from test, ignoring win ssh test"); + return null; + } + + // We will retry 5 times before quitting + int retry = 0; + + while (true) { + try { + if (retry > 0) { + s_logger.info("Retry attempt : " + retry + " ...sleeping 300 seconds before next attempt"); + Thread.sleep(300000); + } + + s_logger.info("Attempting to SSH into windows host " + host + " with retry attempt: " + retry); + + Connection conn = new Connection(host); + conn.connect(null, 60000, 60000); + + s_logger.info("SSHed successfully into windows host " + host); + boolean success = false; + boolean isAuthenticated = conn.authenticateWithPassword("vmops", "vmops"); + if (isAuthenticated == false) { + return "Authentication failed"; + } + SCPClient scp = new SCPClient(conn); + + scp.put("wget.exe", ""); + + Session sess = conn.openSession(); + s_logger.info("Executing : wget http://172.16.0.220/dump.bin"); + sess.execCommand("wget http://172.16.0.220/dump.bin && dir dump.bin"); + + InputStream stdout = sess.getStdout(); + InputStream stderr = sess.getStderr(); + + byte[] buffer = new byte[8192]; + while (true) { + if ((stdout.available() == 0) && (stderr.available() == 0)) { + int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA + | ChannelCondition.EOF, 120000); + + if ((conditions & ChannelCondition.TIMEOUT) != 0) { + s_logger.info("Timeout while waiting for data from peer."); + return null; + } + + if ((conditions & ChannelCondition.EOF) != 0) { + if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) { + break; + } + } + } + + while (stdout.available() > 0) { + success = true; + int len = stdout.read(buffer); + if (len > 0) // this check is somewhat paranoid + s_logger.info(new String(buffer, 0, len)); + } + + while (stderr.available() > 0) { + int len = stderr.read(buffer); + } + } + sess.close(); + conn.close(); + + if (success) { + return null; + } else { + retry++; + if (retry == MAX_RETRY_WIN) { + return "SSH Windows Network test fail"; + } + } + } catch (Exception e) { + retry++; + if (retry == MAX_RETRY_WIN) { + return "SSH Windows Network test fail with error " + e.getMessage(); + } + } + } + } + + private static String sshTest(String host) { + if (host == null) { + s_logger.info("Did not receive a host back from test, ignoring ssh test"); + return null; + } + + // We will retry 5 times before quitting + int retry = 0; + + while (true) { + try { + if (retry > 0) { + s_logger.info("Retry attempt : " + retry + " ...sleeping 120 seconds before next attempt"); + Thread.sleep(120000); + } + + s_logger.info("Attempting to SSH into linux host " + host + " with retry attempt: " + retry); + + Connection conn = new Connection(host); + conn.connect(null, 60000, 60000); + + s_logger.info("SSHed successfully into linux host " + host); + + boolean isAuthenticated = conn.authenticateWithPassword("root", "password"); + + if (isAuthenticated == false) { + return "Authentication failed"; + } + boolean success = false; + Session sess = conn.openSession(); + s_logger.info("Executing : wget http://172.16.0.220/dump.bin"); + sess.execCommand("wget http://172.16.0.220/dump.bin && ls -al dump.bin"); + + InputStream stdout = sess.getStdout(); + InputStream stderr = sess.getStderr(); + + byte[] buffer = new byte[8192]; + while (true) { + if ((stdout.available() == 0) && (stderr.available() == 0)) { + int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA + | ChannelCondition.EOF, 120000); + + if ((conditions & ChannelCondition.TIMEOUT) != 0) { + s_logger.info("Timeout while waiting for data from peer."); + return null; + } + + if ((conditions & ChannelCondition.EOF) != 0) { + if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) { + break; + } + } + } + + while (stdout.available() > 0) { + success = true; + int len = stdout.read(buffer); + if (len > 0) // this check is somewhat paranoid + s_logger.info(new String(buffer, 0, len)); + } + + while (stderr.available() > 0) { + int len = stderr.read(buffer); + } + } + + sess.close(); + conn.close(); + + if (success) { + return null; + } else { + retry++; + if (retry == MAX_RETRY_LINUX) { + return "SSH Linux Network test fail"; + } + } + } catch (Exception e) { + retry++; + if (retry == MAX_RETRY_LINUX) { + return "SSH Linux Network test fail with error " + e.getMessage(); + } + } + } + } +} diff --git a/test/src/com/cloud/test/utils/UtilsForTest.java b/test/src/com/cloud/test/utils/UtilsForTest.java new file mode 100644 index 00000000000..b4d9da60a36 --- /dev/null +++ b/test/src/com/cloud/test/utils/UtilsForTest.java @@ -0,0 +1,240 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.test.utils; + +import java.io.InputStream; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import com.cloud.utils.encoding.Base64; +import com.cloud.utils.exception.CloudRuntimeException; + +public class UtilsForTest { + + private static DocumentBuilderFactory factory = DocumentBuilderFactory + .newInstance(); + + public static boolean verifyTags (Map params) { + boolean result = true; + for (String value : params.keySet()) { + if (params.get(value) == null) { + result=false; + } + } + return result; + } + + public static boolean verifyTagValues (Map params, Map pattern) { + boolean result = true; + + if (pattern != null) { + for (String value : pattern.keySet()) { + if (!pattern.get(value).equals(params.get(value))) { + result=false; + System.out.println("Tag " + value + " has " + params.get(value) + " while expected value is: " + pattern.get(value)); + } + } + } + return result; + } + + + public static Map parseXML(InputStream is, + String[] tagNames) { + Map returnValues = new HashMap(); + try { + DocumentBuilder docBuilder = factory.newDocumentBuilder(); + Document doc = docBuilder.parse(is); + Element rootElement = doc.getDocumentElement(); + + for (int i = 0; i < tagNames.length; i++) { + NodeList targetNodes = rootElement + .getElementsByTagName(tagNames[i]); + if (targetNodes.getLength() <= 0) { + System.out.println("no " + tagNames[i] + + " tag in the response"); + returnValues.put(tagNames[i], null); + } else { + returnValues.put(tagNames[i], targetNodes.item(0) + .getTextContent()); + } + } + } catch (Exception ex) { + System.out.println("error processing XML"); + ex.printStackTrace(); + } + return returnValues; + } + + + public static ArrayList> parseMulXML (InputStream is, String[] tagNames){ + ArrayList> returnValues = new ArrayList>(); + + try { + DocumentBuilder docBuilder = factory.newDocumentBuilder(); + Document doc = docBuilder.parse(is); + Element rootElement = doc.getDocumentElement(); + for (int i = 0; i < tagNames.length; i++) { + NodeList targetNodes = rootElement + .getElementsByTagName(tagNames[i]); + if (targetNodes.getLength() <= 0) { + System.out.println("no " + tagNames[i] + + " tag in XML response...returning null"); + } else { + for (int j = 0; j < targetNodes.getLength(); j++) { + HashMap valueList = new HashMap (); + Node node = targetNodes.item(j); + //parse child nodes + NodeList child = node.getChildNodes(); + for (int c=0; c getSingleValueFromXML(InputStream is, + String[] tagNames) { + Map returnValues = new HashMap(); + try { + DocumentBuilder docBuilder = factory.newDocumentBuilder(); + Document doc = docBuilder.parse(is); + Element rootElement = doc.getDocumentElement(); + + for (int i = 0; i < tagNames.length; i++) { + NodeList targetNodes = rootElement + .getElementsByTagName(tagNames[i]); + if (targetNodes.getLength() <= 0) { + System.out.println("no " + tagNames[i] + + " tag in XML response...returning null"); + } else { + returnValues.put(tagNames[i], targetNodes.item(0) + .getTextContent()); + } + } + } catch (Exception ex) { + System.out.println("error processing XML"); + ex.printStackTrace(); + } + return returnValues; + } + + + public static Map> getMultipleValuesFromXML( + InputStream is, String[] tagNames) { + Map> returnValues = new HashMap>(); + try { + DocumentBuilder docBuilder = factory.newDocumentBuilder(); + Document doc = docBuilder.parse(is); + Element rootElement = doc.getDocumentElement(); + for (int i = 0; i < tagNames.length; i++) { + NodeList targetNodes = rootElement + .getElementsByTagName(tagNames[i]); + if (targetNodes.getLength() <= 0) { + System.out.println("no " + tagNames[i] + + " tag in XML response...returning null"); + } else { + List valueList = new ArrayList(); + for (int j = 0; j < targetNodes.getLength(); j++) { + Node node = targetNodes.item(j); + valueList.add(node.getTextContent()); + } + returnValues.put(tagNames[i], valueList); + } + } + } catch (Exception ex) { + System.out.println(ex); + } + return returnValues; + } + + + + public static String signRequest(String request, String key) { + try { + Mac mac = Mac.getInstance("HmacSHA1"); + SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), + "HmacSHA1"); + mac.init(keySpec); + mac.update(request.getBytes()); + byte[] encryptedBytes = mac.doFinal(); + //System.out.println("HmacSHA1 hash: " + encryptedBytes); + return Base64.encodeBytes(encryptedBytes); + } catch (Exception ex) { + System.out.println("unable to sign request"); + ex.printStackTrace(); + } + return null; + } + +}