summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.openstack.org>2018-07-12 21:35:14 +0000
committerGerrit Code Review <review@openstack.org>2018-07-12 21:35:14 +0000
commitf106003f5ee1a7d7c3ac5125065b1b6aca95e34e (patch)
tree8f8db5353ccdfa80aeb047efac2369c925bbfdaa
parent40230b093d20270f28ffe33653020f9bed13a131 (diff)
parent23f26555b3d4d1a089d09cd2335c39a73997c55e (diff)
Merge "Handling type's multiattach extra specs in API task flow"
-rw-r--r--cinder/tests/unit/volume/flows/test_create_volume_flow.py38
-rw-r--r--cinder/tests/unit/volume/test_volume_retype.py1
-rw-r--r--cinder/volume/api.py7
-rw-r--r--cinder/volume/flows/api/create_volume.py24
4 files changed, 56 insertions, 14 deletions
diff --git a/cinder/tests/unit/volume/flows/test_create_volume_flow.py b/cinder/tests/unit/volume/flows/test_create_volume_flow.py
index e373ae7..6f39b71 100644
--- a/cinder/tests/unit/volume/flows/test_create_volume_flow.py
+++ b/cinder/tests/unit/volume/flows/test_create_volume_flow.py
@@ -174,6 +174,9 @@ class CreateVolumeFlowTestCase(test.TestCase):
174 'ExtractVolumeRequestTask.' 174 'ExtractVolumeRequestTask.'
175 '_get_encryption_key_id', mock.Mock()) 175 '_get_encryption_key_id', mock.Mock())
176 @mock.patch('cinder.volume.volume_types.get_volume_type_qos_specs') 176 @mock.patch('cinder.volume.volume_types.get_volume_type_qos_specs')
177 @mock.patch(
178 'cinder.objects.volume_type.VolumeType.get_by_name_or_id',
179 mock.Mock(return_value={}))
177 def test_extract_volume_request_replication_status(self, 180 def test_extract_volume_request_replication_status(self,
178 replication_status, 181 replication_status,
179 extra_specs, 182 extra_specs,
@@ -211,6 +214,9 @@ class CreateVolumeFlowTestCase(test.TestCase):
211 'ExtractVolumeRequestTask.' 214 'ExtractVolumeRequestTask.'
212 '_get_encryption_key_id') 215 '_get_encryption_key_id')
213 @mock.patch('cinder.volume.volume_types.get_volume_type_qos_specs') 216 @mock.patch('cinder.volume.volume_types.get_volume_type_qos_specs')
217 @mock.patch(
218 'cinder.objects.volume_type.VolumeType.get_by_name_or_id',
219 mock.Mock(return_value={}))
214 def test_extract_volume_request_from_image_encrypted( 220 def test_extract_volume_request_from_image_encrypted(
215 self, 221 self,
216 fake_get_qos, 222 fake_get_qos,
@@ -256,8 +262,10 @@ class CreateVolumeFlowTestCase(test.TestCase):
256 @mock.patch('cinder.volume.flows.api.create_volume.' 262 @mock.patch('cinder.volume.flows.api.create_volume.'
257 'ExtractVolumeRequestTask.' 263 'ExtractVolumeRequestTask.'
258 '_get_volume_type_id') 264 '_get_volume_type_id')
265 @mock.patch('cinder.objects.volume_type.VolumeType.get_by_name_or_id')
259 def test_extract_volume_request_from_image( 266 def test_extract_volume_request_from_image(
260 self, 267 self,
268 fake_get_type,
261 fake_get_type_id, 269 fake_get_type_id,
262 fake_get_qos, 270 fake_get_qos,
263 fake_is_encrypted): 271 fake_is_encrypted):
@@ -271,6 +279,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
271 fake_image_service.create(self.ctxt, image_meta) 279 fake_image_service.create(self.ctxt, image_meta)
272 fake_key_manager = mock_key_manager.MockKeyManager() 280 fake_key_manager = mock_key_manager.MockKeyManager()
273 volume_type = {'name': 'type1'} 281 volume_type = {'name': 'type1'}
282 fake_get_type.return_value = volume_type
274 283
275 task = create_volume.ExtractVolumeRequestTask( 284 task = create_volume.ExtractVolumeRequestTask(
276 fake_image_service, 285 fake_image_service,
@@ -306,7 +315,8 @@ class CreateVolumeFlowTestCase(test.TestCase):
306 'group_id': None, 315 'group_id': None,
307 'refresh_az': False, 316 'refresh_az': False,
308 'replication_status': 'disabled', 317 'replication_status': 'disabled',
309 'backup_id': None} 318 'backup_id': None,
319 'multiattach': False}
310 self.assertEqual(expected_result, result) 320 self.assertEqual(expected_result, result)
311 321
312 @mock.patch('cinder.volume.volume_types.is_encrypted') 322 @mock.patch('cinder.volume.volume_types.is_encrypted')
@@ -468,8 +478,10 @@ class CreateVolumeFlowTestCase(test.TestCase):
468 @mock.patch('cinder.volume.flows.api.create_volume.' 478 @mock.patch('cinder.volume.flows.api.create_volume.'
469 'ExtractVolumeRequestTask.' 479 'ExtractVolumeRequestTask.'
470 '_get_volume_type_id') 480 '_get_volume_type_id')
481 @mock.patch('cinder.objects.volume_type.VolumeType.get_by_name_or_id')
471 def test_extract_availability_zones_with_fallback( 482 def test_extract_availability_zones_with_fallback(
472 self, 483 self,
484 fake_get_type,
473 fake_get_type_id, 485 fake_get_type_id,
474 fake_get_qos, 486 fake_get_qos,
475 fake_is_encrypted): 487 fake_is_encrypted):
@@ -485,6 +497,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
485 fake_image_service.create(self.ctxt, image_meta) 497 fake_image_service.create(self.ctxt, image_meta)
486 fake_key_manager = mock_key_manager.MockKeyManager() 498 fake_key_manager = mock_key_manager.MockKeyManager()
487 volume_type = {'name': 'type1'} 499 volume_type = {'name': 'type1'}
500 fake_get_type.return_value = volume_type
488 501
489 task = create_volume.ExtractVolumeRequestTask( 502 task = create_volume.ExtractVolumeRequestTask(
490 fake_image_service, 503 fake_image_service,
@@ -519,6 +532,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
519 'cgsnapshot_id': None, 532 'cgsnapshot_id': None,
520 'group_id': None, 533 'group_id': None,
521 'refresh_az': True, 534 'refresh_az': True,
535 'multiattach': False,
522 'replication_status': 'disabled', 536 'replication_status': 'disabled',
523 'backup_id': None} 537 'backup_id': None}
524 self.assertEqual(expected_result, result) 538 self.assertEqual(expected_result, result)
@@ -582,8 +596,10 @@ class CreateVolumeFlowTestCase(test.TestCase):
582 @mock.patch('cinder.volume.flows.api.create_volume.' 596 @mock.patch('cinder.volume.flows.api.create_volume.'
583 'ExtractVolumeRequestTask.' 597 'ExtractVolumeRequestTask.'
584 '_get_volume_type_id') 598 '_get_volume_type_id')
599 @mock.patch('cinder.objects.volume_type.VolumeType.get_by_name_or_id')
585 def test_extract_volume_request_task_with_large_volume_size( 600 def test_extract_volume_request_task_with_large_volume_size(
586 self, 601 self,
602 fake_get_type,
587 fake_get_type_id, 603 fake_get_type_id,
588 fake_get_qos, 604 fake_get_qos,
589 fake_is_encrypted): 605 fake_is_encrypted):
@@ -596,6 +612,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
596 fake_image_service.create(self.ctxt, image_meta) 612 fake_image_service.create(self.ctxt, image_meta)
597 fake_key_manager = mock_key_manager.MockKeyManager() 613 fake_key_manager = mock_key_manager.MockKeyManager()
598 volume_type = {'name': 'type1'} 614 volume_type = {'name': 'type1'}
615 fake_get_type.return_value = volume_type
599 616
600 task = create_volume.ExtractVolumeRequestTask( 617 task = create_volume.ExtractVolumeRequestTask(
601 fake_image_service, 618 fake_image_service,
@@ -631,6 +648,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
631 'cgsnapshot_id': None, 648 'cgsnapshot_id': None,
632 'refresh_az': False, 649 'refresh_az': False,
633 'group_id': None, 650 'group_id': None,
651 'multiattach': False,
634 'backup_id': None} 652 'backup_id': None}
635 self.assertEqual(expected_result, result) 653 self.assertEqual(expected_result, result)
636 654
@@ -639,8 +657,10 @@ class CreateVolumeFlowTestCase(test.TestCase):
639 @mock.patch('cinder.volume.flows.api.create_volume.' 657 @mock.patch('cinder.volume.flows.api.create_volume.'
640 'ExtractVolumeRequestTask.' 658 'ExtractVolumeRequestTask.'
641 '_get_volume_type_id') 659 '_get_volume_type_id')
660 @mock.patch('cinder.objects.volume_type.VolumeType.get_by_name_or_id')
642 def test_extract_volume_request_from_image_with_qos_specs( 661 def test_extract_volume_request_from_image_with_qos_specs(
643 self, 662 self,
663 fake_get_type,
644 fake_get_type_id, 664 fake_get_type_id,
645 fake_get_qos, 665 fake_get_qos,
646 fake_is_encrypted): 666 fake_is_encrypted):
@@ -653,7 +673,8 @@ class CreateVolumeFlowTestCase(test.TestCase):
653 image_meta['size'] = 1 673 image_meta['size'] = 1
654 fake_image_service.create(self.ctxt, image_meta) 674 fake_image_service.create(self.ctxt, image_meta)
655 fake_key_manager = mock_key_manager.MockKeyManager() 675 fake_key_manager = mock_key_manager.MockKeyManager()
656 volume_type = {'name': 'type1'} 676 volume_type = {'name': 'type1', 'id': 1}
677 fake_get_type.return_value = volume_type
657 678
658 task = create_volume.ExtractVolumeRequestTask( 679 task = create_volume.ExtractVolumeRequestTask(
659 fake_image_service, 680 fake_image_service,
@@ -689,6 +710,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
689 'cgsnapshot_id': None, 710 'cgsnapshot_id': None,
690 'group_id': None, 711 'group_id': None,
691 'refresh_az': False, 712 'refresh_az': False,
713 'multiattach': False,
692 'replication_status': 'disabled', 714 'replication_status': 'disabled',
693 'backup_id': None} 715 'backup_id': None}
694 self.assertEqual(expected_result, result) 716 self.assertEqual(expected_result, result)
@@ -700,8 +722,10 @@ class CreateVolumeFlowTestCase(test.TestCase):
700 @mock.patch('cinder.volume.flows.api.create_volume.' 722 @mock.patch('cinder.volume.flows.api.create_volume.'
701 'ExtractVolumeRequestTask.' 723 'ExtractVolumeRequestTask.'
702 '_get_volume_type_id') 724 '_get_volume_type_id')
725 @mock.patch('cinder.objects.volume_type.VolumeType.get_by_name_or_id')
703 def test_extract_image_volume_type_from_image( 726 def test_extract_image_volume_type_from_image(
704 self, 727 self,
728 fake_get_type,
705 fake_get_type_id, 729 fake_get_type_id,
706 fake_get_vol_type, 730 fake_get_vol_type,
707 fake_get_def_vol_type, 731 fake_get_def_vol_type,
@@ -709,6 +733,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
709 fake_is_encrypted): 733 fake_is_encrypted):
710 734
711 image_volume_type = {'name': 'type_from_image'} 735 image_volume_type = {'name': 'type_from_image'}
736 fake_get_type.return_value = image_volume_type
712 fake_image_service = fake_image.FakeImageService() 737 fake_image_service = fake_image.FakeImageService()
713 image_id = 6 738 image_id = 6
714 image_meta = {} 739 image_meta = {}
@@ -755,6 +780,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
755 'cgsnapshot_id': None, 780 'cgsnapshot_id': None,
756 'group_id': None, 781 'group_id': None,
757 'refresh_az': False, 782 'refresh_az': False,
783 'multiattach': False,
758 'replication_status': 'disabled', 784 'replication_status': 'disabled',
759 'backup_id': None} 785 'backup_id': None}
760 self.assertEqual(expected_result, result) 786 self.assertEqual(expected_result, result)
@@ -766,8 +792,10 @@ class CreateVolumeFlowTestCase(test.TestCase):
766 @mock.patch('cinder.volume.flows.api.create_volume.' 792 @mock.patch('cinder.volume.flows.api.create_volume.'
767 'ExtractVolumeRequestTask.' 793 'ExtractVolumeRequestTask.'
768 '_get_volume_type_id') 794 '_get_volume_type_id')
795 @mock.patch('cinder.objects.volume_type.VolumeType.get_by_name_or_id')
769 def test_extract_image_volume_type_from_image_invalid_type( 796 def test_extract_image_volume_type_from_image_invalid_type(
770 self, 797 self,
798 fake_get_type,
771 fake_get_type_id, 799 fake_get_type_id,
772 fake_get_def_vol_type, 800 fake_get_def_vol_type,
773 fake_get_qos, 801 fake_get_qos,
@@ -793,6 +821,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
793 fake_is_encrypted.return_value = False 821 fake_is_encrypted.return_value = False
794 fake_get_type_id.return_value = 1 822 fake_get_type_id.return_value = 1
795 fake_get_def_vol_type.return_value = {'name': 'fake_vol_type'} 823 fake_get_def_vol_type.return_value = {'name': 'fake_vol_type'}
824 fake_get_type.return_value = {'name': 'fake_vol_type'}
796 fake_db_get_vol_type.side_effect = ( 825 fake_db_get_vol_type.side_effect = (
797 exception.VolumeTypeNotFoundByName(volume_type_name='invalid')) 826 exception.VolumeTypeNotFoundByName(volume_type_name='invalid'))
798 fake_get_qos.return_value = {'qos_specs': None} 827 fake_get_qos.return_value = {'qos_specs': None}
@@ -821,6 +850,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
821 'consistencygroup_id': None, 850 'consistencygroup_id': None,
822 'cgsnapshot_id': None, 851 'cgsnapshot_id': None,
823 'group_id': None, 852 'group_id': None,
853 'multiattach': False,
824 'refresh_az': False, 854 'refresh_az': False,
825 'replication_status': 'disabled', 855 'replication_status': 'disabled',
826 'backup_id': None} 856 'backup_id': None}
@@ -835,10 +865,12 @@ class CreateVolumeFlowTestCase(test.TestCase):
835 '_get_volume_type_id') 865 '_get_volume_type_id')
836 @ddt.data((8, None), (9, {'cinder_img_volume_type': None})) 866 @ddt.data((8, None), (9, {'cinder_img_volume_type': None}))
837 @ddt.unpack 867 @ddt.unpack
868 @mock.patch('cinder.objects.volume_type.VolumeType.get_by_name_or_id')
838 def test_extract_image_volume_type_from_image_properties_error( 869 def test_extract_image_volume_type_from_image_properties_error(
839 self, 870 self,
840 image_id, 871 image_id,
841 fake_img_properties, 872 fake_img_properties,
873 fake_get_type,
842 fake_get_type_id, 874 fake_get_type_id,
843 fake_get_def_vol_type, 875 fake_get_def_vol_type,
844 fake_get_qos, 876 fake_get_qos,
@@ -861,6 +893,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
861 fake_is_encrypted.return_value = False 893 fake_is_encrypted.return_value = False
862 fake_get_type_id.return_value = 1 894 fake_get_type_id.return_value = 1
863 fake_get_def_vol_type.return_value = {'name': 'fake_vol_type'} 895 fake_get_def_vol_type.return_value = {'name': 'fake_vol_type'}
896 fake_get_type.return_value = {'name': 'fake_vol_type'}
864 fake_get_qos.return_value = {'qos_specs': None} 897 fake_get_qos.return_value = {'qos_specs': None}
865 result = task.execute(self.ctxt, 898 result = task.execute(self.ctxt,
866 size=1, 899 size=1,
@@ -888,6 +921,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
888 'cgsnapshot_id': None, 921 'cgsnapshot_id': None,
889 'group_id': None, 922 'group_id': None,
890 'refresh_az': False, 923 'refresh_az': False,
924 'multiattach': False,
891 'replication_status': 'disabled', 925 'replication_status': 'disabled',
892 'backup_id': None} 926 'backup_id': None}
893 self.assertEqual(expected_result, result) 927 self.assertEqual(expected_result, result)
diff --git a/cinder/tests/unit/volume/test_volume_retype.py b/cinder/tests/unit/volume/test_volume_retype.py
index caee463..3a0e6ee 100644
--- a/cinder/tests/unit/volume/test_volume_retype.py
+++ b/cinder/tests/unit/volume/test_volume_retype.py
@@ -116,7 +116,6 @@ class VolumeRetypeTestCase(base.BaseVolumeTestCase):
116 mock.call(volume_policies.MULTIATTACH_POLICY, 116 mock.call(volume_policies.MULTIATTACH_POLICY,
117 target_obj=mock.ANY), 117 target_obj=mock.ANY),
118 mock.call(volume_policies.CREATE_POLICY), 118 mock.call(volume_policies.CREATE_POLICY),
119 mock.call(volume_policies.MULTIATTACH_POLICY),
120 mock.call(volume_policies.CREATE_POLICY), 119 mock.call(volume_policies.CREATE_POLICY),
121 mock.call(vol_action_policies.RETYPE_POLICY, target_obj=mock.ANY), 120 mock.call(vol_action_policies.RETYPE_POLICY, target_obj=mock.ANY),
122 mock.call(vol_action_policies.RETYPE_POLICY, target_obj=mock.ANY), 121 mock.call(vol_action_policies.RETYPE_POLICY, target_obj=mock.ANY),
diff --git a/cinder/volume/api.py b/cinder/volume/api.py
index 9c59bf4..faea172 100644
--- a/cinder/volume/api.py
+++ b/cinder/volume/api.py
@@ -289,9 +289,6 @@ class API(base.Base):
289 289
290 utils.check_metadata_properties(metadata) 290 utils.check_metadata_properties(metadata)
291 291
292 if (volume_type and self._is_multiattach(volume_type)) or multiattach:
293 context.authorize(vol_policy.MULTIATTACH_POLICY)
294
295 create_what = { 292 create_what = {
296 'context': context, 293 'context': context,
297 'raw_size': size, 294 'raw_size': size,
@@ -308,7 +305,7 @@ class API(base.Base):
308 'optional_args': {'is_quota_committed': False}, 305 'optional_args': {'is_quota_committed': False},
309 'consistencygroup': consistencygroup, 306 'consistencygroup': consistencygroup,
310 'cgsnapshot': cgsnapshot, 307 'cgsnapshot': cgsnapshot,
311 'multiattach': multiattach, 308 'raw_multiattach': multiattach,
312 'group': group, 309 'group': group,
313 'group_snapshot': group_snapshot, 310 'group_snapshot': group_snapshot,
314 'source_group': source_group, 311 'source_group': source_group,
@@ -349,8 +346,6 @@ class API(base.Base):
349 # Refresh the object here, otherwise things ain't right 346 # Refresh the object here, otherwise things ain't right
350 vref = objects.Volume.get_by_id( 347 vref = objects.Volume.get_by_id(
351 context, vref['id']) 348 context, vref['id'])
352 vref.multiattach = (self._is_multiattach(volume_type) or
353 multiattach)
354 vref.save() 349 vref.save()
355 LOG.info("Create volume request issued successfully.", 350 LOG.info("Create volume request issued successfully.",
356 resource=vref) 351 resource=vref)
diff --git a/cinder/volume/flows/api/create_volume.py b/cinder/volume/flows/api/create_volume.py
index 9607d71..1b2a804 100644
--- a/cinder/volume/flows/api/create_volume.py
+++ b/cinder/volume/flows/api/create_volume.py
@@ -69,7 +69,8 @@ class ExtractVolumeRequestTask(flow_utils.CinderTask):
69 'source_volid', 'volume_type', 'volume_type_id', 69 'source_volid', 'volume_type', 'volume_type_id',
70 'encryption_key_id', 'consistencygroup_id', 70 'encryption_key_id', 'consistencygroup_id',
71 'cgsnapshot_id', 'qos_specs', 'group_id', 71 'cgsnapshot_id', 'qos_specs', 'group_id',
72 'refresh_az', 'backup_id', 'availability_zones']) 72 'refresh_az', 'backup_id', 'availability_zones',
73 'multiattach'])
73 74
74 def __init__(self, image_service, availability_zones, **kwargs): 75 def __init__(self, image_service, availability_zones, **kwargs):
75 super(ExtractVolumeRequestTask, self).__init__(addons=[ACTION], 76 super(ExtractVolumeRequestTask, self).__init__(addons=[ACTION],
@@ -430,7 +431,8 @@ class ExtractVolumeRequestTask(flow_utils.CinderTask):
430 431
431 def execute(self, context, size, snapshot, image_id, source_volume, 432 def execute(self, context, size, snapshot, image_id, source_volume,
432 availability_zone, volume_type, metadata, key_manager, 433 availability_zone, volume_type, metadata, key_manager,
433 consistencygroup, cgsnapshot, group, group_snapshot, backup): 434 consistencygroup, cgsnapshot, group, group_snapshot, backup,
435 multiattach=False):
434 436
435 utils.check_exclusive_options(snapshot=snapshot, 437 utils.check_exclusive_options(snapshot=snapshot,
436 imageRef=image_id, 438 imageRef=image_id,
@@ -478,12 +480,22 @@ class ExtractVolumeRequestTask(flow_utils.CinderTask):
478 source_volume, 480 source_volume,
479 image_meta) 481 image_meta)
480 482
481 if encryption_key_id is not None and volume_type is not None: 483 if volume_type_id:
484 volume_type = objects.VolumeType.get_by_name_or_id(
485 context, volume_type_id)
482 extra_specs = volume_type.get('extra_specs', {}) 486 extra_specs = volume_type.get('extra_specs', {})
483 if extra_specs.get('multiattach', '') == '<is> True': 487 # NOTE(tommylikehu): Although the parameter `multiattach` from
488 # create volume API is deprecated now, we still need to consider
489 # it when multiattach is not enabled in volume type.
490 multiattach = (extra_specs.get(
491 'multiattach', '') == '<is> True' or multiattach)
492 if multiattach and encryption_key_id:
484 msg = _('Multiattach cannot be used with encrypted volumes.') 493 msg = _('Multiattach cannot be used with encrypted volumes.')
485 raise exception.InvalidVolume(reason=msg) 494 raise exception.InvalidVolume(reason=msg)
486 495
496 if multiattach:
497 context.authorize(policy.MULTIATTACH_POLICY)
498
487 specs = {} 499 specs = {}
488 if volume_type_id: 500 if volume_type_id:
489 qos_specs = volume_types.get_volume_type_qos_specs(volume_type_id) 501 qos_specs = volume_types.get_volume_type_qos_specs(volume_type_id)
@@ -517,6 +529,7 @@ class ExtractVolumeRequestTask(flow_utils.CinderTask):
517 'replication_status': replication_status, 529 'replication_status': replication_status,
518 'refresh_az': refresh_az, 530 'refresh_az': refresh_az,
519 'backup_id': backup_id, 531 'backup_id': backup_id,
532 'multiattach': multiattach,
520 'availability_zones': availability_zones 533 'availability_zones': availability_zones
521 } 534 }
522 535
@@ -858,7 +871,8 @@ def get_flow(db_api, image_service_api, availability_zones, create_what,
858 availability_zones, 871 availability_zones,
859 rebind={'size': 'raw_size', 872 rebind={'size': 'raw_size',
860 'availability_zone': 'raw_availability_zone', 873 'availability_zone': 'raw_availability_zone',
861 'volume_type': 'raw_volume_type'})) 874 'volume_type': 'raw_volume_type',
875 'multiattach': 'raw_multiattach'}))
862 api_flow.add(QuotaReserveTask(), 876 api_flow.add(QuotaReserveTask(),
863 EntryCreateTask(), 877 EntryCreateTask(),
864 QuotaCommitTask()) 878 QuotaCommitTask())