Browse Source

Merge "Fix creation of share from snapshot"

Jenkins 4 years ago
parent
commit
98b9b568fe
2 changed files with 124 additions and 35 deletions
  1. 42
    14
      manila/share/api.py
  2. 82
    21
      manila/tests/share/test_api.py

+ 42
- 14
manila/share/api.py View File

@@ -31,7 +31,17 @@ from manila import quota
31 31
 from manila.scheduler import rpcapi as scheduler_rpcapi
32 32
 from manila.share import rpcapi as share_rpcapi
33 33
 
34
+share_api_opts = [
35
+    cfg.BoolOpt('use_scheduler_creating_share_from_snapshot',
36
+                default=False,
37
+                help='If set to False, then share creation from snapshot will '
38
+                     'be performed on the same host. '
39
+                     'If set to True, then scheduling step will be used.')
40
+]
41
+
34 42
 CONF = cfg.CONF
43
+CONF.register_opts(share_api_opts)
44
+
35 45
 LOG = logging.getLogger(__name__)
36 46
 GB = 1048576 * 1024
37 47
 QUOTAS = quota.QUOTAS
@@ -152,22 +162,40 @@ class API(base.Base):
152 162
                 finally:
153 163
                     QUOTAS.rollback(context, reservations)
154 164
 
155
-        request_spec = {'share_properties': options,
156
-                        'share_proto': share_proto,
157
-                        'share_id': share['id'],
158
-                        'snapshot_id': share['snapshot_id'],
159
-                        'volume_type': volume_type
160
-                        }
161
-
165
+        request_spec = {
166
+            'share_properties': options,
167
+            'share_proto': share_proto,
168
+            'share_id': share['id'],
169
+            'snapshot_id': snapshot_id,
170
+            'volume_type': volume_type,
171
+        }
162 172
         filter_properties = {}
163 173
 
164
-        self.scheduler_rpcapi.create_share(
165
-            context,
166
-            CONF.share_topic,
167
-            share['id'],
168
-            snapshot_id,
169
-            request_spec=request_spec,
170
-            filter_properties=filter_properties)
174
+        if (snapshot and not CONF.use_scheduler_creating_share_from_snapshot):
175
+            # Shares from snapshots with restriction - source host only.
176
+            # It is common situation for different types of backends.
177
+            host = snapshot['share']['host']
178
+            share = self.db.share_update(context, share['id'], {'host': host})
179
+            self.share_rpcapi.create_share(
180
+                context,
181
+                share,
182
+                host,
183
+                request_spec=request_spec,
184
+                filter_properties=filter_properties,
185
+                snapshot_id=snapshot_id,
186
+            )
187
+        else:
188
+            # Shares from scratch and from snapshots when source host is not
189
+            # the only allowed, it is possible, for example, in multibackend
190
+            # installation with Generic drivers only.
191
+            self.scheduler_rpcapi.create_share(
192
+                context,
193
+                CONF.share_topic,
194
+                share['id'],
195
+                snapshot_id,
196
+                request_spec=request_spec,
197
+                filter_properties=filter_properties,
198
+            )
171 199
 
172 200
         return share
173 201
 

+ 82
- 21
manila/tests/share/test_api.py View File

@@ -18,6 +18,7 @@ import datetime
18 18
 import uuid
19 19
 
20 20
 import mock
21
+from oslo.config import cfg
21 22
 
22 23
 from manila import context
23 24
 from manila import db as db_driver
@@ -30,6 +31,8 @@ from manila import test
30 31
 from manila.tests.db import fakes as db_fakes
31 32
 from manila import utils
32 33
 
34
+CONF = cfg.CONF
35
+
33 36
 
34 37
 def fake_share(id, **kwargs):
35 38
     share = {
@@ -73,7 +76,8 @@ def fake_snapshot(id, **kwargs):
73 76
         'progress': 'fakeprogress99%',
74 77
         'scheduled_at': datetime.datetime(1, 1, 1, 1, 1, 1),
75 78
         'launched_at': datetime.datetime(1, 1, 1, 1, 1, 1),
76
-        'terminated_at': datetime.datetime(1, 1, 1, 1, 1, 1)
79
+        'terminated_at': datetime.datetime(1, 1, 1, 1, 1, 1),
80
+        'share': {'host': 'fake_source_host'},
77 81
     }
78 82
     snapshot.update(kwargs)
79 83
     return snapshot
@@ -439,6 +443,7 @@ class ShareAPITestCase(test.TestCase):
439 443
                        mock.Mock(return_value='reservation'))
440 444
     @mock.patch.object(quota.QUOTAS, 'commit', mock.Mock())
441 445
     def test_create_from_snapshot_available(self):
446
+        CONF.set_default("use_scheduler_creating_share_from_snapshot", False)
442 447
         date = datetime.datetime(1, 1, 1, 1, 1, 1)
443 448
         self.mock_utcnow.return_value = date
444 449
         snapshot = fake_snapshot('fakesnapshotid',
@@ -460,28 +465,80 @@ class ShareAPITestCase(test.TestCase):
460 465
             'volume_type': None,
461 466
             'snapshot_id': share['snapshot_id'],
462 467
         }
463
-        with mock.patch.object(db_driver, 'share_create',
464
-                               mock.Mock(return_value=share)):
465
-            self.api.create(self.context, 'nfs', '1', 'fakename', 'fakedesc',
466
-                            snapshot=snapshot, availability_zone='fakeaz')
467
-            self.scheduler_rpcapi.create_share.assert_called_once_with(
468
-                self.context, 'manila-share', share['id'],
469
-                share['snapshot_id'], request_spec=request_spec,
470
-                filter_properties={})
471
-            db_driver.share_create.assert_called_once_with(
472
-                self.context, options)
473
-            share_api.policy.check_policy.assert_called_once_with(
474
-                self.context, 'share', 'create')
475
-            quota.QUOTAS.reserve.assert_called_once_with(
476
-                self.context, gigabytes=1, shares=1)
477
-            quota.QUOTAS.commit.assert_called_once_with(
478
-                self.context, 'reservation')
468
+        self.stubs.Set(db_driver, 'share_create',
469
+                       mock.Mock(return_value=share))
470
+        self.stubs.Set(db_driver, 'share_update',
471
+                       mock.Mock(return_value=share))
472
+
473
+        self.api.create(self.context, 'nfs', '1', 'fakename', 'fakedesc',
474
+                        snapshot=snapshot, availability_zone='fakeaz')
475
+
476
+        self.share_rpcapi.create_share.assert_called_once_with(
477
+            self.context, share, snapshot['share']['host'],
478
+            request_spec=request_spec, filter_properties={},
479
+            snapshot_id=snapshot['id'])
480
+        db_driver.share_create.assert_called_once_with(
481
+            self.context, options)
482
+        share_api.policy.check_policy.assert_called_once_with(
483
+            self.context, 'share', 'create')
484
+        quota.QUOTAS.reserve.assert_called_once_with(
485
+            self.context, gigabytes=1, shares=1)
486
+        quota.QUOTAS.commit.assert_called_once_with(
487
+            self.context, 'reservation')
488
+
489
+    @mock.patch.object(quota.QUOTAS, 'reserve',
490
+                       mock.Mock(return_value='reservation'))
491
+    @mock.patch.object(quota.QUOTAS, 'commit', mock.Mock())
492
+    def test_create_from_snapshot_without_host_restriction(self):
493
+        CONF.set_default("use_scheduler_creating_share_from_snapshot", True)
494
+        date = datetime.datetime(1, 1, 1, 1, 1, 1)
495
+        self.mock_utcnow.return_value = date
496
+        snapshot = fake_snapshot('fakesnapshotid',
497
+                                 share_id='fakeshare_id',
498
+                                 status='available')
499
+        share = fake_share('fakeid',
500
+                           user_id=self.context.user_id,
501
+                           project_id=self.context.project_id,
502
+                           snapshot_id=snapshot['id'],
503
+                           status='creating')
504
+        options = share.copy()
505
+        for name in ('id', 'export_location', 'host', 'launched_at',
506
+                     'terminated_at'):
507
+            options.pop(name, None)
508
+        request_spec = {
509
+            'share_properties': options,
510
+            'share_proto': share['share_proto'],
511
+            'share_id': share['id'],
512
+            'volume_type': None,
513
+            'snapshot_id': share['snapshot_id'],
514
+        }
515
+        self.stubs.Set(db_driver, 'share_create',
516
+                       mock.Mock(return_value=share))
517
+        self.stubs.Set(db_driver, 'share_update',
518
+                       mock.Mock(return_value=share))
519
+
520
+        self.api.create(self.context, 'nfs', '1', 'fakename', 'fakedesc',
521
+                        snapshot=snapshot, availability_zone='fakeaz')
522
+
523
+        self.scheduler_rpcapi.create_share.assert_called_once_with(
524
+            self.context, 'manila-share', share['id'],
525
+            share['snapshot_id'], request_spec=request_spec,
526
+            filter_properties={})
527
+        db_driver.share_create.assert_called_once_with(
528
+            self.context, options)
529
+        share_api.policy.check_policy.assert_called_once_with(
530
+            self.context, 'share', 'create')
531
+        quota.QUOTAS.reserve.assert_called_once_with(
532
+            self.context, gigabytes=1, shares=1)
533
+        quota.QUOTAS.commit.assert_called_once_with(
534
+            self.context, 'reservation')
479 535
 
480 536
     @mock.patch.object(quota.QUOTAS, 'reserve',
481 537
                        mock.Mock(return_value='reservation'))
482 538
     @mock.patch.object(quota.QUOTAS, 'commit', mock.Mock())
483 539
     def test_create_from_snapshot_with_volume_type_same(self):
484 540
         # Prepare data for test
541
+        CONF.set_default("use_scheduler_creating_share_from_snapshot", False)
485 542
         date = datetime.datetime(1, 1, 1, 1, 1, 1)
486 543
         self.mock_utcnow.return_value = date
487 544
         share_id = 'fake_share_id'
@@ -506,6 +563,8 @@ class ShareAPITestCase(test.TestCase):
506 563
         }
507 564
         self.stubs.Set(db_driver, 'share_create',
508 565
                        mock.Mock(return_value=share))
566
+        self.stubs.Set(db_driver, 'share_update',
567
+                       mock.Mock(return_value=share))
509 568
         self.stubs.Set(db_driver, 'share_get', mock.Mock(return_value=share))
510 569
 
511 570
         # Call tested method
@@ -514,10 +573,10 @@ class ShareAPITestCase(test.TestCase):
514 573
                         volume_type=volume_type)
515 574
 
516 575
         # Verify results
517
-        self.scheduler_rpcapi.create_share.assert_called_once_with(
518
-            self.context, 'manila-share', share_id,
519
-            share['snapshot_id'], request_spec=request_spec,
520
-            filter_properties={})
576
+        self.share_rpcapi.create_share.assert_called_once_with(
577
+            self.context, share, snapshot['share']['host'],
578
+            request_spec=request_spec, filter_properties={},
579
+            snapshot_id=snapshot['id'])
521 580
         db_driver.share_create.assert_called_once_with(
522 581
             self.context, options)
523 582
         share_api.policy.check_policy.assert_called_once_with(
@@ -528,6 +587,8 @@ class ShareAPITestCase(test.TestCase):
528 587
             self.context, 'reservation')
529 588
         db_driver.share_get.assert_called_once_with(
530 589
             self.context, share_id)
590
+        db_driver.share_update.assert_called_once_with(
591
+            self.context, share_id, {'host': snapshot['share']['host']})
531 592
 
532 593
     @mock.patch.object(quota.QUOTAS, 'reserve',
533 594
                        mock.Mock(return_value='reservation'))

Loading…
Cancel
Save