1 This upstream patch addresses CVE-2014-2573 and is tracked under |
|
2 Launchpad bug 1269418. It is addressed in Icehouse 2014.1 and Havana |
|
3 2013.2.4. It has been modified to apply cleanly into our current Havana |
|
4 implementation |
|
5 |
|
6 This particulr hypervisor driver is not currently shipped with |
|
7 Solaris. |
|
8 |
|
9 commit b3cc3f62a60662e5bb82136c0cfa464592a6afe9 |
|
10 Author: Gary Kotton <[email protected]> |
|
11 Date: Thu Mar 13 06:53:58 2014 -0700 |
|
12 |
|
13 VMware: ensure rescue instance is deleted when instance is deleted |
|
14 |
|
15 If the user creates a rescue instance and then proceeded to delete |
|
16 the original instance then the rescue instance would still be up |
|
17 and running on the backend. |
|
18 |
|
19 This patch ensures that the rescue instance is cleaned up if |
|
20 necessary. |
|
21 |
|
22 The vmops unrescue method has a new parameter indicating if |
|
23 the original VM should be powered on. |
|
24 |
|
25 Closes-bug: 1269418 |
|
26 (cherry picked from commit efb66531bc37ee416778a70d46c657608ca767af) |
|
27 |
|
28 Conflicts: |
|
29 |
|
30 nova/tests/virt/vmwareapi/test_vmwareapi.py |
|
31 nova/virt/vmwareapi/vmops.py |
|
32 |
|
33 Change-Id: I3c1d0b1d003392b306094b80ea1ac99377441fbf |
|
34 |
|
35 --- nova-2013.2.3/nova/tests/virt/vmwareapi/test_vmwareapi.py.~1~ 2014-04-03 11:49:46.000000000 -0700 |
|
36 +++ nova-2013.2.3/nova/tests/virt/vmwareapi/test_vmwareapi.py 2014-06-09 23:03:38.008877252 -0700 |
|
37 @@ -34,6 +34,7 @@ |
|
38 from nova.compute import api as compute_api |
|
39 from nova.compute import power_state |
|
40 from nova.compute import task_states |
|
41 +from nova.compute import vm_states |
|
42 from nova import context |
|
43 from nova import db |
|
44 from nova import exception |
|
45 @@ -793,6 +794,31 @@ |
|
46 'node': self.instance_node}) |
|
47 self._check_vm_info(info, power_state.RUNNING) |
|
48 |
|
49 + def destroy_rescued(self, fake_method): |
|
50 + self._rescue() |
|
51 + with ( |
|
52 + mock.patch.object(self.conn._volumeops, "detach_disk_from_vm", |
|
53 + fake_method) |
|
54 + ): |
|
55 + self.instance['vm_state'] = vm_states.RESCUED |
|
56 + self.conn.destroy(self.instance, self.network_info) |
|
57 + inst_path = '[%s] %s/%s.vmdk' % (self.ds, self.uuid, self.uuid) |
|
58 + self.assertFalse(vmwareapi_fake.get_file(inst_path)) |
|
59 + rescue_file_path = '[%s] %s-rescue/%s-rescue.vmdk' % (self.ds, |
|
60 + self.uuid, |
|
61 + self.uuid) |
|
62 + self.assertFalse(vmwareapi_fake.get_file(rescue_file_path)) |
|
63 + |
|
64 + def test_destroy_rescued(self): |
|
65 + def fake_detach_disk_from_vm(*args, **kwargs): |
|
66 + pass |
|
67 + self.destroy_rescued(fake_detach_disk_from_vm) |
|
68 + |
|
69 + def test_destroy_rescued_with_exception(self): |
|
70 + def fake_detach_disk_from_vm(*args, **kwargs): |
|
71 + raise exception.NovaException('Here is my fake exception') |
|
72 + self.destroy_rescued(fake_detach_disk_from_vm) |
|
73 + |
|
74 def test_destroy(self): |
|
75 self._create_vm() |
|
76 info = self.conn.get_info({'uuid': self.uuid, |
|
77 --- nova-2013.2.3/nova/virt/vmwareapi/vmops.py.~1~ 2014-04-03 11:49:46.000000000 -0700 |
|
78 +++ nova-2013.2.3/nova/virt/vmwareapi/vmops.py 2014-06-09 23:09:13.557941347 -0700 |
|
79 @@ -35,6 +35,7 @@ |
|
80 from nova import compute |
|
81 from nova.compute import power_state |
|
82 from nova.compute import task_states |
|
83 +from nova.compute import vm_states |
|
84 from nova import context as nova_context |
|
85 from nova import exception |
|
86 from nova.openstack.common import excutils |
|
87 @@ -904,13 +905,9 @@ |
|
88 except Exception as exc: |
|
89 LOG.exception(exc, instance=instance) |
|
90 |
|
91 - def destroy(self, instance, network_info, destroy_disks=True): |
|
92 - """ |
|
93 - Destroy a VM instance. Steps followed are: |
|
94 - 1. Power off the VM, if it is in poweredOn state. |
|
95 - 2. Un-register a VM. |
|
96 - 3. Delete the contents of the folder holding the VM related data. |
|
97 - """ |
|
98 + def _destroy_instance(self, instance, network_info, destroy_disks=True, |
|
99 + instance_name=None): |
|
100 + # Destroy a VM instance |
|
101 try: |
|
102 vm_ref = vm_util.get_vm_ref(self._session, instance) |
|
103 lst_properties = ["config.files.vmPathName", "runtime.powerState", |
|
104 @@ -943,8 +940,9 @@ |
|
105 "UnregisterVM", vm_ref) |
|
106 LOG.debug(_("Unregistered the VM"), instance=instance) |
|
107 except Exception as excep: |
|
108 - LOG.warn(_("In vmwareapi:vmops:destroy, got this exception" |
|
109 - " while un-registering the VM: %s") % str(excep)) |
|
110 + LOG.warn(_("In vmwareapi:vmops:_destroy_instance, got this " |
|
111 + "exception while un-registering the VM: %s"), |
|
112 + excep) |
|
113 |
|
114 if network_info: |
|
115 self.unplug_vifs(instance, network_info) |
|
116 @@ -976,13 +974,37 @@ |
|
117 {'datastore_name': datastore_name}, |
|
118 instance=instance) |
|
119 except Exception as excep: |
|
120 - LOG.warn(_("In vmwareapi:vmops:destroy, " |
|
121 - "got this exception while deleting" |
|
122 - " the VM contents from the disk: %s") |
|
123 - % str(excep)) |
|
124 + LOG.warn(_("In vmwareapi:vmops:_destroy_instance, " |
|
125 + "got this exception while deleting " |
|
126 + "the VM contents from the disk: %s"), |
|
127 + excep) |
|
128 except Exception as exc: |
|
129 LOG.exception(exc, instance=instance) |
|
130 |
|
131 + def destroy(self, instance, network_info, destroy_disks=True): |
|
132 + """Destroy a VM instance. |
|
133 + |
|
134 + Steps followed for each VM are: |
|
135 + 1. Power off, if it is in poweredOn state. |
|
136 + 2. Un-register. |
|
137 + 3. Delete the contents of the folder holding the VM related data. |
|
138 + """ |
|
139 + # If there is a rescue VM then we need to destroy that one too. |
|
140 + LOG.debug(_("Destroying instance"), instance=instance) |
|
141 + if instance['vm_state'] == vm_states.RESCUED: |
|
142 + LOG.debug(_("Rescue VM configured"), instance=instance) |
|
143 + try: |
|
144 + self.unrescue(instance, power_on=False) |
|
145 + LOG.debug(_("Rescue VM destroyed"), instance=instance) |
|
146 + except Exception: |
|
147 + rescue_name = instance['uuid'] + self._rescue_suffix |
|
148 + self._destroy_instance(instance, network_info, |
|
149 + destroy_disks=destroy_disks, |
|
150 + instance_name=rescue_name) |
|
151 + self._destroy_instance(instance, network_info, |
|
152 + destroy_disks=destroy_disks) |
|
153 + LOG.debug(_("Instance destroyed"), instance=instance) |
|
154 + |
|
155 def pause(self, instance): |
|
156 msg = _("pause not supported for vmwareapi") |
|
157 raise NotImplementedError(msg) |
|
158 @@ -1066,7 +1088,7 @@ |
|
159 controller_key=controller_key, |
|
160 unit_number=unit_number) |
|
161 |
|
162 - def unrescue(self, instance): |
|
163 + def unrescue(self, instance, power_on=True): |
|
164 """Unrescue the specified instance.""" |
|
165 # Get the original vmdk_path |
|
166 vm_ref = vm_util.get_vm_ref(self._session, instance) |
|
167 @@ -1079,8 +1101,9 @@ |
|
168 r_instance = copy.deepcopy(instance) |
|
169 r_instance['name'] = r_instance['name'] + self._rescue_suffix |
|
170 r_instance['uuid'] = r_instance['uuid'] + self._rescue_suffix |
|
171 - self.destroy(r_instance, None) |
|
172 - self._power_on(instance) |
|
173 + self._destroy_instance(r_instance, None, instance_name=instance_name) |
|
174 + if power_on: |
|
175 + self._power_on(instance) |
|
176 |
|
177 def power_off(self, instance): |
|
178 """Power off the specified instance.""" |
|