13
13
# under the License.
14
14
15
15
import mock
16
+ from oslo_serialization import jsonutils
16
17
from oslo_utils .fixture import uuidsentinel as uuids
17
18
19
+ from nova import context
18
20
from nova import exception
21
+ from nova import objects
19
22
from nova import test
20
23
from nova .tests import fixtures as nova_fixtures
21
24
from nova .tests .functional import integrated_helpers
@@ -116,12 +119,16 @@ def test_vol_attachments_during_driver_live_mig_failure(self, mock_lm):
116
119
117
120
* Mock live_migration to always rollback and raise a failure within the
118
121
fake virt driver
119
- * Launch a boot from volume instance
122
+ * Launch a boot from volume instance on src
120
123
* Assert that the volume is attached correctly to the instance
124
+ * Assert that the expected source attachment is recorded in the bdm
125
+ * Wrap pre_live_migration on the dest and assert that we switch over
126
+ to the new attachment and connection_info on the dest.
121
127
* Live migrate the instance to another host invoking the mocked
122
128
live_migration method
123
129
* Assert that the instance is still on the source host
124
130
* Assert that the original source host volume attachment remains
131
+ * Assert that the original src connection_info is in the bdm
125
132
"""
126
133
# Mock out driver.live_migration so that we always rollback
127
134
def _fake_live_migration_with_rollback (
@@ -135,21 +142,23 @@ def _fake_live_migration_with_rollback(
135
142
136
143
volume_id = nova_fixtures .CinderFixture .IMAGE_BACKED_VOL
137
144
server = self ._build_server (
138
- name = 'test_bfv_live_migration_failure' , image_uuid = '' ,
139
- networks = 'none'
145
+ name = 'test_bfv_live_migration_failure' ,
146
+ image_uuid = '' ,
147
+ networks = 'none' ,
148
+ host = 'src'
140
149
)
141
150
server ['block_device_mapping_v2' ] = [{
142
151
'source_type' : 'volume' ,
143
152
'destination_type' : 'volume' ,
144
153
'boot_index' : 0 ,
145
- 'uuid' : volume_id
154
+ 'uuid' : volume_id ,
146
155
}]
147
156
server = self .api .post_server ({'server' : server })
148
157
self ._wait_for_state_change (server , 'ACTIVE' )
149
158
150
- # Fetch the source host for use later
159
+ # Assert that the instance has landed correctly on src
151
160
server = self .api .get_server (server ['id' ])
152
- src_host = server ['OS-EXT-SRV-ATTR:host' ]
161
+ self . assertEqual ( 'src' , server ['OS-EXT-SRV-ATTR:host' ])
153
162
154
163
# Assert that the volume is connected to the instance
155
164
self .assertIn (
@@ -162,22 +171,75 @@ def _fake_live_migration_with_rollback(
162
171
# Fetch the attachment_id for use later once we have migrated
163
172
src_attachment_id = list (attachments .keys ())[0 ]
164
173
165
- # Migrate the instance and wait until the migration errors out thanks
166
- # to our mocked version of live_migration raising TestingException
167
- self ._live_migrate (server , 'error' , server_expected_state = 'ERROR' )
174
+ # Assert that this attachment_id is stashed in the connection_info
175
+ # of the bdm so we can assert things again after the failure
176
+ ctxt = context .get_admin_context ()
177
+ bdm = objects .BlockDeviceMapping .get_by_volume_and_instance (
178
+ ctxt , volume_id , server ['id' ])
179
+ self .assertEqual (src_attachment_id , bdm .attachment_id )
180
+ connection_info = jsonutils .loads (bdm .connection_info )
181
+ self .assertIn ('attachment_id' , connection_info ['data' ])
182
+ self .assertEqual (
183
+ src_attachment_id , connection_info ['data' ]['attachment_id' ])
184
+
185
+ dest_pre_live_mig = self .computes ['dest' ].manager .pre_live_migration
186
+
187
+ # Wrap pre_live_migration on the destination so we can assert that
188
+ # we do switch over to the new attachment before the failure
189
+ # and then later rollback to the source attachment
190
+ def wrap_pre_live_migration (* args , ** kwargs ):
191
+
192
+ # Continue with pre_live_migration before we assert anything
193
+ migrate_data = dest_pre_live_mig (* args , ** kwargs )
194
+
195
+ # Assert that we now have two attachments in the fixture, one for
196
+ # the src and another for the dest.
197
+ attachments = self .cinder .volume_to_attachment .get (volume_id )
198
+ self .assertEqual (2 , len (attachments ))
199
+
200
+ # Assert that the dest attachment id is saved in the bdm
201
+ # and the connection_info.
202
+ bdm = objects .BlockDeviceMapping .get_by_volume_and_instance (
203
+ ctxt , volume_id , server ['id' ])
204
+ self .assertNotEqual (src_attachment_id , bdm .attachment_id )
205
+ dest_attachment_id = bdm .attachment_id
206
+ connection_info = jsonutils .loads (bdm .connection_info )
207
+ self .assertIn ('attachment_id' , connection_info ['data' ])
208
+ self .assertEqual (
209
+ dest_attachment_id , connection_info ['data' ]['attachment_id' ])
210
+ return migrate_data
211
+
212
+ with mock .patch .object (
213
+ self .computes ['dest' ].manager ,
214
+ 'pre_live_migration' ,
215
+ wrap_pre_live_migration
216
+ ):
217
+ # Migrate the instance and wait until the migration errors out
218
+ # thanks to our mocked version of live_migration raising
219
+ # TestingException
220
+ self ._live_migrate (server , 'error' , server_expected_state = 'ERROR' )
168
221
169
222
# Assert that we called the fake live_migration method
170
223
mock_lm .assert_called_once ()
171
224
172
225
# Assert that the instance is on the source
173
226
server = self .api .get_server (server ['id' ])
174
- self .assertEqual (src_host , server ['OS-EXT-SRV-ATTR:host' ])
227
+ self .assertEqual ('src' , server ['OS-EXT-SRV-ATTR:host' ])
175
228
176
229
# Assert that the src attachment is still present
177
230
attachments = self .cinder .volume_to_attachment .get (volume_id )
178
231
self .assertIn (src_attachment_id , attachments .keys ())
179
232
self .assertEqual (1 , len (attachments ))
180
233
234
+ # Assert that the connection_info has reverted back to the src
235
+ bdm = objects .BlockDeviceMapping .get_by_volume_and_instance (
236
+ ctxt , volume_id , server ['id' ])
237
+ self .assertEqual (src_attachment_id , bdm .attachment_id )
238
+ connection_info = jsonutils .loads (bdm .connection_info )
239
+ self .assertIn ('attachment_id' , connection_info ['data' ])
240
+ self .assertEqual (
241
+ src_attachment_id , connection_info ['data' ]['attachment_id' ])
242
+
181
243
182
244
class LiveMigrationNeutronInteractionsTest (
183
245
integrated_helpers ._IntegratedTestBase ):
0 commit comments