Add locks to container image commands

Ie5ef4045b7e22c06551e886f9f9b6f22c8d4bd21 added some additional
processing when uploading images. This unfortunately broke the
'openstack tripleo container image push' command because it assumes a
lock is always available. This change adds a process lock to the
ImageManagers used by the cli to ensure we are locking correctly when
doing any multiprocessing

Change-Id: I2d661682b3ee4d82d9f445a04e930c2fb328ef80
Closes-Bug: #1855184
This commit is contained in:
Alex Schultz 2019-12-04 14:27:42 -07:00
parent 70355d05d7
commit 94f8ef1df8
2 changed files with 47 additions and 9 deletions

View File

@ -51,20 +51,28 @@ class TestContainerImageUpload(TestPluginV1):
# Get the command object to test
self.cmd = container_image.UploadImage(self.app, None)
@mock.patch('tripleo_common.utils.locks.processlock.'
'ProcessLock')
@mock.patch('sys.exit')
@mock.patch('tripleo_common.image.image_uploader.ImageUploadManager')
def test_container_image_upload_noargs(self, mock_manager, exit_mock):
def test_container_image_upload_noargs(self, mock_manager, exit_mock,
mock_lock):
arglist = []
verifylist = []
mock_lockobj = mock.MagicMock()
mock_lock.return_value = mock_lockobj
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
# argparse will complain that --config-file is missing and exit with 2
exit_mock.assert_called_with(2)
@mock.patch('tripleo_common.utils.locks.processlock.'
'ProcessLock')
@mock.patch('tripleo_common.image.image_uploader.ImageUploadManager')
def test_container_image_upload_conf_files(self, mock_manager):
def test_container_image_upload_conf_files(self, mock_manager, mock_lock):
arglist = [
'--config-file',
'/tmp/foo.yaml',
@ -73,18 +81,27 @@ class TestContainerImageUpload(TestPluginV1):
]
verifylist = []
mock_lockobj = mock.MagicMock()
mock_lock.return_value = mock_lockobj
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
mock_manager.assert_called_once_with(
['/tmp/foo.yaml', '/tmp/bar.yaml'], cleanup='full')
['/tmp/foo.yaml', '/tmp/bar.yaml'], cleanup='full',
lock=mock_lockobj)
mock_manager.return_value.upload.assert_called_once_with()
class TestContainerImagePush(TestPluginV1):
def setUp(self):
super(TestContainerImagePush, self).setUp()
lock = mock.patch('tripleo_common.utils.locks.processlock.ProcessLock')
self.mock_lock = lock.start()
self.addCleanup(lock.stop)
self.cmd = container_image.TripleOContainerImagePush(self.app, None)
@mock.patch('tripleo_common.image.image_uploader.get_undercloud_registry',
@ -360,6 +377,11 @@ class TestContainerImageDelete(TestPluginV1):
def setUp(self):
super(TestContainerImageDelete, self).setUp()
lock = mock.patch('tripleo_common.utils.locks.processlock.ProcessLock')
self.mock_lock = lock.start()
self.addCleanup(lock.stop)
self.cmd = container_image.TripleOContainerImageDelete(self.app, None)
@mock.patch('tripleo_common.image.image_uploader.get_undercloud_registry',
@ -402,6 +424,11 @@ class TestContainerImageList(TestPluginV1):
def setUp(self):
super(TestContainerImageList, self).setUp()
lock = mock.patch('tripleo_common.utils.locks.processlock.ProcessLock')
self.mock_lock = lock.start()
self.addCleanup(lock.stop)
self.cmd = container_image.TripleOContainerImageList(self.app, None)
@mock.patch('tripleo_common.image.image_uploader.get_undercloud_registry',
@ -471,6 +498,11 @@ class TestContainerImageShow(TestPluginV1):
def setUp(self):
super(TestContainerImageShow, self).setUp()
lock = mock.patch('tripleo_common.utils.locks.processlock.ProcessLock')
self.mock_lock = lock.start()
self.addCleanup(lock.stop)
self.cmd = container_image.TripleOContainerImageShow(self.app, None)
@mock.patch('tripleoclient.v1.container_image.TripleOContainerImageShow.'

View File

@ -91,8 +91,9 @@ class UploadImage(command.Command):
if parsed_args.cleanup not in image_uploader.CLEANUP:
raise oscexc.CommandError('--cleanup must be one of: %s' %
', '.join(image_uploader.CLEANUP))
lock = processlock.ProcessLock()
uploader = image_uploader.ImageUploadManager(
parsed_args.config_files, cleanup=parsed_args.cleanup)
parsed_args.config_files, cleanup=parsed_args.cleanup, lock=lock)
try:
uploader.upload()
except KeyboardInterrupt: # ctrl-c
@ -511,7 +512,8 @@ class DiscoverImageTag(command.Command):
"replaced by the 'openstack tripleo container image "
"prepare' command.")
uploader = image_uploader.ImageUploadManager([])
lock = processlock.ProcessLock()
uploader = image_uploader.ImageUploadManager([], lock=lock)
print(uploader.discover_image_tag(
image=parsed_args.image,
tag_from_label=parsed_args.tag_from_label
@ -594,7 +596,8 @@ class TripleOContainerImagePush(command.Command):
def take_action(self, parsed_args):
self.log.debug("take_action(%s)" % parsed_args)
manager = image_uploader.ImageUploadManager()
lock = processlock.ProcessLock()
manager = image_uploader.ImageUploadManager(lock=lock)
uploader = manager.uploader('python')
source_image = parsed_args.image_to_push
@ -703,7 +706,8 @@ class TripleOContainerImageDelete(command.Command):
if not confirm:
raise oscexc.CommandError("Action not confirmed, exiting.")
manager = image_uploader.ImageUploadManager()
lock = processlock.ProcessLock()
manager = image_uploader.ImageUploadManager(lock=lock)
uploader = manager.uploader('python')
url = uploader._image_to_url(parsed_args.registry_url)
session = uploader.authenticate(url, parsed_args.username,
@ -750,7 +754,8 @@ class TripleOContainerImageList(command.Lister):
def take_action(self, parsed_args):
self.log.debug("take_action(%s)" % parsed_args)
manager = image_uploader.ImageUploadManager()
lock = processlock.ProcessLock()
manager = image_uploader.ImageUploadManager(lock=lock)
uploader = manager.uploader('python')
url = uploader._image_to_url(parsed_args.registry_url)
session = uploader.authenticate(url, parsed_args.username,
@ -799,7 +804,8 @@ class TripleOContainerImageShow(command.ShowOne):
def take_action(self, parsed_args):
self.log.debug("take_action(%s)" % parsed_args)
manager = image_uploader.ImageUploadManager()
lock = processlock.ProcessLock()
manager = image_uploader.ImageUploadManager(lock=lock)
uploader = manager.uploader('python')
url = uploader._image_to_url(parsed_args.image_to_inspect)
session = uploader.authenticate(url, parsed_args.username,