|
14 | 14 | # KIND, either express or implied. See the License for the |
15 | 15 | # specific language governing permissions and limitations |
16 | 16 | # under the License. |
17 | | - |
| 17 | +import json |
18 | 18 |
|
19 | 19 | from marvin.cloudstackTestCase import cloudstackTestCase |
20 | 20 | from marvin.lib.base import Account, VirtualMachine, ServiceOffering |
21 | | -from marvin.lib.utils import cleanup_resources |
| 21 | +from marvin.lib.utils import (validateList, cleanup_resources) |
22 | 22 | from marvin.lib.common import get_zone, get_domain, get_template |
| 23 | +from marvin.codes import PASS |
23 | 24 | from nose.plugins.attrib import attr |
24 | 25 |
|
25 | 26 | class TestData(object): |
@@ -59,6 +60,7 @@ class TestUpdateVirtualMachine(cloudstackTestCase): |
59 | 60 | def setUp(self): |
60 | 61 | self.testdata = TestData().testdata |
61 | 62 | self.apiclient = self.testClient.getApiClient() |
| 63 | + self.dbclient = self.testClient.getDbConnection() |
62 | 64 |
|
63 | 65 | # Get Zone, Domain and Default Built-in template |
64 | 66 | self.domain = get_domain(self.apiclient) |
@@ -106,18 +108,7 @@ def test_update_vm_name(self): |
106 | 108 | templateid=self.template.id |
107 | 109 | ) |
108 | 110 |
|
109 | | - list_vms = VirtualMachine.list(self.apiclient, id=self.virtual_machine.id) |
110 | | - self.assertEqual( |
111 | | - isinstance(list_vms, list), |
112 | | - True, |
113 | | - "List VM response was not a valid list" |
114 | | - ) |
115 | | - self.assertNotEqual( |
116 | | - len(list_vms), |
117 | | - 0, |
118 | | - "List VM response was empty" |
119 | | - ) |
120 | | - vm = list_vms[0] |
| 111 | + vm = self.listVmById(self.virtual_machine.id) |
121 | 112 |
|
122 | 113 | self.debug( |
123 | 114 | "VirtualMachine launched with id, name, displayname: %s %s %s"\ |
@@ -152,6 +143,111 @@ def test_update_vm_name(self): |
152 | 143 | self.assertEqual(vmnew.displayname, vmnewstarted.displayname, |
153 | 144 | msg="display name changed on start, displayname is %s" % vmnewstarted.displayname) |
154 | 145 |
|
| 146 | + @attr(tags=['advanced', 'simulator', 'basic', 'sg', 'details'], required_hardware="false") |
| 147 | + def test_update_vm_details_admin(self): |
| 148 | + """Test Update VirtualMachine Details |
| 149 | +
|
| 150 | + # Set up a VM |
| 151 | + # Set up hidden detail in DB for VM |
| 152 | +
|
| 153 | + # Validate the following: |
| 154 | + # 1. Can add two details (detail1, detail2) |
| 155 | + # 2. Can fetch new details on VM |
| 156 | + # 3. Can delete detail1 |
| 157 | + # 4. Hidden detail not removed |
| 158 | + # 6. The detail2 remains |
| 159 | + # 7. Ensure cleanup parameter doesn't remove hidden details |
| 160 | + """ |
| 161 | + hidden_detail_name = "configDriveLocation" |
| 162 | + detail1 = "detail1" |
| 163 | + detail2 = "detail2" |
| 164 | + |
| 165 | + # set up a VM |
| 166 | + self.virtual_machine = VirtualMachine.create( |
| 167 | + self.apiclient, |
| 168 | + self.testdata["virtual_machine"], |
| 169 | + accountid=self.account.name, |
| 170 | + zoneid=self.zone.id, |
| 171 | + domainid=self.account.domainid, |
| 172 | + serviceofferingid=self.service_offering.id, |
| 173 | + templateid=self.template.id |
| 174 | + ) |
| 175 | + |
| 176 | + vm = self.listVmById(self.virtual_machine.id) |
| 177 | + |
| 178 | + self.debug( |
| 179 | + "VirtualMachine launched with id, name, displayname: %s %s %s" \ |
| 180 | + % (self.virtual_machine.id, vm.name, vm.displayname) |
| 181 | + ) |
| 182 | + |
| 183 | + # set up a hidden detail |
| 184 | + dbresult = self.dbclient.execute("select id from vm_instance where uuid='%s'" % vm.id) |
| 185 | + self.assertEqual(validateList(dbresult)[0], PASS, "sql query returned invalid response") |
| 186 | + vm_db_id = dbresult[0][0] |
| 187 | + self.debug("VM has database id %d" % vm_db_id) |
| 188 | + |
| 189 | + self.dbclient.execute("insert into user_vm_details (vm_id, name, value, display) values (%d,'%s','HOST', 0)" % (vm_db_id, hidden_detail_name)) |
| 190 | + |
| 191 | + vm = self.listVmById(self.virtual_machine.id) |
| 192 | + self.debug("VirtualMachine fetched with details: %s of type %s" % (vm.details, type(vm.details))) |
| 193 | + |
| 194 | + self.assertIsNone(vm.details[hidden_detail_name], "hidden detail should be hidden") |
| 195 | + |
| 196 | + # add two details by appending to what was returned via API |
| 197 | + updating_vm_details = vm.details.__dict__ |
| 198 | + updating_vm_details[detail1] = "foo" |
| 199 | + updating_vm_details[detail2] = "bar" |
| 200 | + |
| 201 | + self.debug("Updating VM to new details: %s" % updating_vm_details) |
| 202 | + vm = self.virtual_machine.update(self.apiclient, details=[updating_vm_details]) |
| 203 | + |
| 204 | + self.assertIsNotNone(vm.details[detail1], "Expect " + detail1) |
| 205 | + self.assertIsNotNone(vm.details[detail2], "Expect " + detail2) |
| 206 | + self.assertIsNone(vm.details[hidden_detail_name], "hidden detail should be hidden") |
| 207 | + self.assertTrue(self.detailInDatabase(vm_db_id, hidden_detail_name), "hidden detail should still exist in db") |
| 208 | + |
| 209 | + # delete one detail |
| 210 | + updating_vm_details = vm.details.__dict__ |
| 211 | + del updating_vm_details["detail1"] |
| 212 | + |
| 213 | + self.debug("Deleting one detail by updating details: %s" % updating_vm_details) |
| 214 | + vm = self.virtual_machine.update(self.apiclient, details=[updating_vm_details]) |
| 215 | + |
| 216 | + self.assertIsNone(vm.details[detail1], "Do not expect " + detail1) |
| 217 | + self.assertIsNotNone(vm.details[detail2], "Expect " + detail2) |
| 218 | + self.assertIsNone(vm.details[hidden_detail_name], "hidden detail should be hidden") |
| 219 | + self.assertTrue(self.detailInDatabase(vm_db_id, hidden_detail_name), "hidden detail should still exist in db") |
| 220 | + |
| 221 | + # cleanup, ensure hidden detail is not deleted |
| 222 | + vm = self.virtual_machine.update(self.apiclient, cleanupdetails="true") |
| 223 | + self.assertIsNone(vm.details[detail1], "Do not expect " + detail1) |
| 224 | + self.assertIsNone(vm.details[detail2], "Do not expect " + detail2) |
| 225 | + self.assertIsNone(vm.details[hidden_detail_name], "hidden detail should be hidden") |
| 226 | + self.assertTrue(self.detailInDatabase(vm_db_id, hidden_detail_name), "hidden detail should still exist in db") |
| 227 | + |
| 228 | + |
| 229 | + def detailInDatabase(self, vm_id, detail_name): |
| 230 | + dbresult = self.dbclient.execute("select id from user_vm_details where vm_id=%s and name='%s'" % (vm_id, detail_name)) |
| 231 | + self.debug("Detail %s for VM %s: %s" % (detail_name, vm_id, dbresult)) |
| 232 | + if validateList(dbresult)[0] == PASS: |
| 233 | + return True |
| 234 | + return False |
| 235 | + |
| 236 | + |
| 237 | + def listVmById(self, id): |
| 238 | + list_vms = VirtualMachine.list(self.apiclient, id=id) |
| 239 | + self.assertEqual( |
| 240 | + isinstance(list_vms, list), |
| 241 | + True, |
| 242 | + "List VM response was not a valid list" |
| 243 | + ) |
| 244 | + self.assertNotEqual( |
| 245 | + len(list_vms), |
| 246 | + 0, |
| 247 | + "List VM response was empty" |
| 248 | + ) |
| 249 | + return list_vms[0] |
| 250 | + |
155 | 251 | def tearDown(self): |
156 | 252 | try: |
157 | 253 | cleanup_resources(self.apiclient, self.cleanup) |
|
0 commit comments