Merge "Reuse checksum calculation from oslo"
This commit is contained in:
commit
b8ffcc0f02
|
@ -31,6 +31,7 @@ import jinja2
|
||||||
from oslo_concurrency import processutils
|
from oslo_concurrency import processutils
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_serialization import jsonutils
|
from oslo_serialization import jsonutils
|
||||||
|
from oslo_utils import fileutils
|
||||||
from oslo_utils import netutils
|
from oslo_utils import netutils
|
||||||
from oslo_utils import timeutils
|
from oslo_utils import timeutils
|
||||||
import pytz
|
import pytz
|
||||||
|
@ -229,28 +230,6 @@ def _get_hash_object(hash_algo_name):
|
||||||
return getattr(hashlib, hash_algo_name)()
|
return getattr(hashlib, hash_algo_name)()
|
||||||
|
|
||||||
|
|
||||||
def hash_file(file_like_object, hash_algo='md5'):
|
|
||||||
"""Generate a hash for the contents of a file.
|
|
||||||
|
|
||||||
It returns a hash of the file object as a string of double length,
|
|
||||||
containing only hexadecimal digits. It supports all the algorithms
|
|
||||||
hashlib does.
|
|
||||||
:param file_like_object: file like object whose hash to be calculated.
|
|
||||||
:param hash_algo: name of the hashing strategy, default being 'md5'.
|
|
||||||
:raises: InvalidParameterValue, on unsupported or invalid input.
|
|
||||||
:returns: a condensed digest of the bytes of contents.
|
|
||||||
"""
|
|
||||||
checksum = _get_hash_object(hash_algo)
|
|
||||||
while True:
|
|
||||||
chunk = file_like_object.read(32768)
|
|
||||||
if not chunk:
|
|
||||||
break
|
|
||||||
encoded_chunk = (chunk.encode(encoding='utf-8')
|
|
||||||
if isinstance(chunk, six.string_types) else chunk)
|
|
||||||
checksum.update(encoded_chunk)
|
|
||||||
return checksum.hexdigest()
|
|
||||||
|
|
||||||
|
|
||||||
def file_has_content(path, content, hash_algo='md5'):
|
def file_has_content(path, content, hash_algo='md5'):
|
||||||
"""Checks that content of the file is the same as provided reference.
|
"""Checks that content of the file is the same as provided reference.
|
||||||
|
|
||||||
|
@ -260,8 +239,7 @@ def file_has_content(path, content, hash_algo='md5'):
|
||||||
:returns: True if the hash of reference content is the same as
|
:returns: True if the hash of reference content is the same as
|
||||||
the hash of file's content, False otherwise
|
the hash of file's content, False otherwise
|
||||||
"""
|
"""
|
||||||
with open(path, 'rb') as existing:
|
file_hash_hex = fileutils.compute_file_checksum(path, algorithm=hash_algo)
|
||||||
file_hash_hex = hash_file(existing, hash_algo=hash_algo)
|
|
||||||
ref_hash = _get_hash_object(hash_algo)
|
ref_hash = _get_hash_object(hash_algo)
|
||||||
encoded_content = (content.encode(encoding='utf-8')
|
encoded_content = (content.encode(encoding='utf-8')
|
||||||
if isinstance(content, six.string_types) else content)
|
if isinstance(content, six.string_types) else content)
|
||||||
|
|
|
@ -22,6 +22,7 @@ import tempfile
|
||||||
|
|
||||||
from ironic_lib import utils as ironic_utils
|
from ironic_lib import utils as ironic_utils
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
from oslo_utils import fileutils
|
||||||
from oslo_utils import importutils
|
from oslo_utils import importutils
|
||||||
import six
|
import six
|
||||||
import six.moves.urllib.parse as urlparse
|
import six.moves.urllib.parse as urlparse
|
||||||
|
@ -775,8 +776,8 @@ def verify_image_checksum(image_location, expected_checksum):
|
||||||
verification fails.
|
verification fails.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
with open(image_location, 'rb') as fd:
|
actual_checksum = fileutils.compute_file_checksum(image_location,
|
||||||
actual_checksum = utils.hash_file(fd)
|
algorithm='md5')
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
LOG.error("Error opening file: %(file)s", {'file': image_location})
|
LOG.error("Error opening file: %(file)s", {'file': image_location})
|
||||||
raise exception.ImageRefValidationFailed(image_href=image_location,
|
raise exception.ImageRefValidationFailed(image_href=image_location,
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import errno
|
import errno
|
||||||
import hashlib
|
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import shutil
|
import shutil
|
||||||
|
@ -26,7 +25,6 @@ import mock
|
||||||
from oslo_concurrency import processutils
|
from oslo_concurrency import processutils
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_utils import netutils
|
from oslo_utils import netutils
|
||||||
import six
|
|
||||||
|
|
||||||
from ironic.common import exception
|
from ironic.common import exception
|
||||||
from ironic.common import utils
|
from ironic.common import utils
|
||||||
|
@ -117,66 +115,19 @@ class GenericUtilsTestCase(base.TestCase):
|
||||||
utils._get_hash_object,
|
utils._get_hash_object,
|
||||||
'hickory-dickory-dock')
|
'hickory-dickory-dock')
|
||||||
|
|
||||||
def test_hash_file_for_md5(self):
|
|
||||||
# | GIVEN |
|
|
||||||
data = b'Mary had a little lamb, its fleece as white as snow'
|
|
||||||
file_like_object = six.BytesIO(data)
|
|
||||||
expected = hashlib.md5(data).hexdigest()
|
|
||||||
# | WHEN |
|
|
||||||
actual = utils.hash_file(file_like_object) # using default, 'md5'
|
|
||||||
# | THEN |
|
|
||||||
self.assertEqual(expected, actual)
|
|
||||||
|
|
||||||
def test_hash_file_for_md5_not_binary(self):
|
|
||||||
# | GIVEN |
|
|
||||||
data = u'Mary had a little lamb, its fleece as white as sno\u0449'
|
|
||||||
file_like_object = six.StringIO(data)
|
|
||||||
expected = hashlib.md5(data.encode('utf-8')).hexdigest()
|
|
||||||
# | WHEN |
|
|
||||||
actual = utils.hash_file(file_like_object) # using default, 'md5'
|
|
||||||
# | THEN |
|
|
||||||
self.assertEqual(expected, actual)
|
|
||||||
|
|
||||||
def test_hash_file_for_sha1(self):
|
|
||||||
# | GIVEN |
|
|
||||||
data = b'Mary had a little lamb, its fleece as white as snow'
|
|
||||||
file_like_object = six.BytesIO(data)
|
|
||||||
expected = hashlib.sha1(data).hexdigest()
|
|
||||||
# | WHEN |
|
|
||||||
actual = utils.hash_file(file_like_object, 'sha1')
|
|
||||||
# | THEN |
|
|
||||||
self.assertEqual(expected, actual)
|
|
||||||
|
|
||||||
def test_hash_file_for_sha512(self):
|
|
||||||
# | GIVEN |
|
|
||||||
data = b'Mary had a little lamb, its fleece as white as snow'
|
|
||||||
file_like_object = six.BytesIO(data)
|
|
||||||
expected = hashlib.sha512(data).hexdigest()
|
|
||||||
# | WHEN |
|
|
||||||
actual = utils.hash_file(file_like_object, 'sha512')
|
|
||||||
# | THEN |
|
|
||||||
self.assertEqual(expected, actual)
|
|
||||||
|
|
||||||
def test_hash_file_throws_for_invalid_or_unsupported_hash(self):
|
|
||||||
# | GIVEN |
|
|
||||||
data = b'Mary had a little lamb, its fleece as white as snow'
|
|
||||||
file_like_object = six.BytesIO(data)
|
|
||||||
# | WHEN | & | THEN |
|
|
||||||
self.assertRaises(exception.InvalidParameterValue, utils.hash_file,
|
|
||||||
file_like_object, 'hickory-dickory-dock')
|
|
||||||
|
|
||||||
def test_file_has_content_equal(self):
|
def test_file_has_content_equal(self):
|
||||||
data = b'Mary had a little lamb, its fleece as white as snow'
|
data = b'Mary had a little lamb, its fleece as white as snow'
|
||||||
ref = data
|
ref = data
|
||||||
with mock.patch('ironic.common.utils.open',
|
with mock.patch('oslo_utils.fileutils.open',
|
||||||
mock.mock_open(read_data=data)) as mopen:
|
mock.mock_open(read_data=data)) as mopen:
|
||||||
self.assertTrue(utils.file_has_content('foo', ref))
|
self.assertTrue(utils.file_has_content('foo', ref))
|
||||||
mopen.assert_called_once_with('foo', 'rb')
|
mopen.assert_called_once_with('foo', 'rb')
|
||||||
|
|
||||||
def test_file_has_content_equal_not_binary(self):
|
def test_file_has_content_equal_not_binary(self):
|
||||||
data = u'Mary had a little lamb, its fleece as white as sno\u0449'
|
data = ('Mary had a little lamb, its fleece as white as '
|
||||||
|
'sno\u0449').encode('utf-8')
|
||||||
ref = data
|
ref = data
|
||||||
with mock.patch('ironic.common.utils.open',
|
with mock.patch('oslo_utils.fileutils.open',
|
||||||
mock.mock_open(read_data=data)) as mopen:
|
mock.mock_open(read_data=data)) as mopen:
|
||||||
self.assertTrue(utils.file_has_content('foo', ref))
|
self.assertTrue(utils.file_has_content('foo', ref))
|
||||||
mopen.assert_called_once_with('foo', 'rb')
|
mopen.assert_called_once_with('foo', 'rb')
|
||||||
|
@ -184,7 +135,7 @@ class GenericUtilsTestCase(base.TestCase):
|
||||||
def test_file_has_content_differ(self):
|
def test_file_has_content_differ(self):
|
||||||
data = b'Mary had a little lamb, its fleece as white as snow'
|
data = b'Mary had a little lamb, its fleece as white as snow'
|
||||||
ref = data + b'!'
|
ref = data + b'!'
|
||||||
with mock.patch('ironic.common.utils.open',
|
with mock.patch('oslo_utils.fileutils.open',
|
||||||
mock.mock_open(read_data=data)) as mopen:
|
mock.mock_open(read_data=data)) as mopen:
|
||||||
self.assertFalse(utils.file_has_content('foo', ref))
|
self.assertFalse(utils.file_has_content('foo', ref))
|
||||||
mopen.assert_called_once_with('foo', 'rb')
|
mopen.assert_called_once_with('foo', 'rb')
|
||||||
|
|
Loading…
Reference in New Issue