Merge "Wire in get_dlrn_hash"
This commit is contained in:
commit
4019c33401
|
@ -11,6 +11,11 @@ RELEASES = ['newton', 'ocata', 'pike', 'queens', 'master']
|
|||
# Define long term releases
|
||||
LONG_TERM_SUPPORT_RELEASES = ['queens']
|
||||
|
||||
# NAMED DLRN HASHES
|
||||
NEWTON_HASH_NAME = 'current-passed-ci'
|
||||
CURRENT_HASH_NAME = 'current-tripleo'
|
||||
PREVIOUS_HASH_NAME = 'previous-current-tripleo'
|
||||
|
||||
|
||||
def get_relative_release(release, relative_idx):
|
||||
current_idx = RELEASES.index(release)
|
||||
|
@ -40,30 +45,41 @@ def load_featureset_file(featureset_file):
|
|||
return featureset
|
||||
|
||||
|
||||
def get_dlrn_hash(release, hash_name, retries=10):
|
||||
def get_dlrn_hash(release, hash_name, retries=10, timeout=4):
|
||||
logger = logging.getLogger('emit-releases')
|
||||
full_hash_pattern = re.compile('[a-z,0-9]{40}_[a-z,0-9]{8}')
|
||||
repo_url = ('https://trunk.rdoproject.org/centos7-%s/%s/delorean.repo' %
|
||||
(release, hash_name))
|
||||
for retry_num in range(retries):
|
||||
repo_file = None
|
||||
# Timeout if initial connection is longer than default
|
||||
# TCP packet retransmission window (3 secs), or if the
|
||||
# sending of the data takes more than 27 seconds.
|
||||
try:
|
||||
repo_file = requests.get(repo_url, timeout=(3.05, 27))
|
||||
repo_file = requests.get(repo_url, timeout=timeout)
|
||||
except Exception as e:
|
||||
logger.warning("Attempt {} of {} to get DLRN hash threw an "
|
||||
"exception.".format(retry_num + 1, retries))
|
||||
logger.exception(e)
|
||||
pass
|
||||
else:
|
||||
if repo_file is not None and repo_file.ok:
|
||||
break
|
||||
|
||||
elif repo_file:
|
||||
logger.warning("Attempt {} of {} to get DLRN hash returned "
|
||||
"status code {}.".format(retry_num + 1,
|
||||
retries,
|
||||
repo_file.status_code))
|
||||
else:
|
||||
logger.warning("Attempt {} of {} to get DLRN hash failed to "
|
||||
"get a response.".format(retry_num + 1,
|
||||
retries))
|
||||
|
||||
if repo_file is None or not repo_file.ok:
|
||||
raise RuntimeError("Failed to retrieve repo file from {} after "
|
||||
"{} retries".format(repo_url, retries))
|
||||
|
||||
full_hash = full_hash_pattern.findall(repo_file.content)
|
||||
full_hash = full_hash_pattern.findall(repo_file.text)
|
||||
logger.info("Got DLRN hash: {} for the named hash: {} on the {} "
|
||||
"release".format(full_hash[0], hash_name, release))
|
||||
return full_hash[0]
|
||||
|
||||
|
||||
|
@ -100,37 +116,54 @@ def compose_releases_dictionary(stable_release, featureset):
|
|||
"used in a fast forward upgrade. Current long-term support "
|
||||
"releases: {}".format(stable_release, LONG_TERM_SUPPORT_RELEASES))
|
||||
|
||||
if stable_release == 'newton':
|
||||
current_hash = get_dlrn_hash(stable_release, NEWTON_HASH_NAME)
|
||||
else:
|
||||
current_hash = get_dlrn_hash(stable_release, CURRENT_HASH_NAME)
|
||||
|
||||
releases_dictionary = {
|
||||
'undercloud_install_release': stable_release,
|
||||
'undercloud_install_hash': 'current-tripleo',
|
||||
'undercloud_install_hash': current_hash,
|
||||
'undercloud_target_release': stable_release,
|
||||
'undercloud_target_hash': 'current-tripleo',
|
||||
'undercloud_target_hash': current_hash,
|
||||
'overcloud_deploy_release': stable_release,
|
||||
'overcloud_deploy_hash': 'current-tripleo',
|
||||
'overcloud_deploy_hash': current_hash,
|
||||
'overcloud_target_release': stable_release,
|
||||
'overcloud_target_hash': 'current-tripleo'
|
||||
'overcloud_target_hash': current_hash
|
||||
}
|
||||
|
||||
if featureset.get('mixed_upgrade'):
|
||||
if featureset.get('overcloud_upgrade'):
|
||||
logger.info('Doing an overcloud upgrade')
|
||||
deploy_release = get_relative_release(stable_release, -1)
|
||||
if deploy_release == 'newton':
|
||||
deploy_hash = get_dlrn_hash(deploy_release, NEWTON_HASH_NAME)
|
||||
else:
|
||||
deploy_hash = get_dlrn_hash(deploy_release, CURRENT_HASH_NAME)
|
||||
releases_dictionary['overcloud_deploy_release'] = deploy_release
|
||||
releases_dictionary['overcloud_deploy_hash'] = deploy_hash
|
||||
|
||||
elif featureset.get('ffu_overcloud_upgrade'):
|
||||
logger.info('Doing an overcloud fast forward upgrade')
|
||||
deploy_release = get_relative_release(stable_release, -3)
|
||||
if deploy_release == 'newton':
|
||||
deploy_hash = get_dlrn_hash(deploy_release, NEWTON_HASH_NAME)
|
||||
else:
|
||||
deploy_hash = get_dlrn_hash(deploy_release, CURRENT_HASH_NAME)
|
||||
releases_dictionary['overcloud_deploy_release'] = deploy_release
|
||||
releases_dictionary['overcloud_deploy_hash'] = deploy_hash
|
||||
|
||||
elif featureset.get('undercloud_upgrade'):
|
||||
logger.info('Doing an undercloud upgrade')
|
||||
install_release = get_relative_release(stable_release, -1)
|
||||
install_hash = get_dlrn_hash(install_release, CURRENT_HASH_NAME)
|
||||
releases_dictionary['undercloud_install_release'] = install_release
|
||||
releases_dictionary['undercloud_install_hash'] = install_hash
|
||||
|
||||
elif featureset.get('overcloud_update'):
|
||||
logger.info('Doing an overcloud update')
|
||||
releases_dictionary['overcloud_deploy_hash'] = \
|
||||
'previous-current-tripleo'
|
||||
previous_hash = get_dlrn_hash(stable_release, PREVIOUS_HASH_NAME)
|
||||
releases_dictionary['overcloud_deploy_hash'] = previous_hash
|
||||
|
||||
logger.debug("stable_release: %s, featureset: %s", stable_release,
|
||||
featureset)
|
||||
|
|
|
@ -4,28 +4,53 @@ import mock
|
|||
import pytest
|
||||
|
||||
|
||||
@mock.patch('logging.getLogger')
|
||||
@mock.patch('requests.get')
|
||||
def test_get_dlrn_hash(mock_get):
|
||||
def test_get_dlrn_hash_ok(mock_get, mock_logging):
|
||||
mock_logger = mock.MagicMock()
|
||||
mock_logging.return_value = mock_logger
|
||||
mock_log_exception = mock.MagicMock()
|
||||
mock_log_warning = mock.MagicMock()
|
||||
mock_log_info = mock.MagicMock()
|
||||
mock_logger.exception = mock_log_exception
|
||||
mock_logger.warning = mock_log_warning
|
||||
mock_logger.info = mock_log_info
|
||||
mock_response = mock.Mock()
|
||||
mock_response.content = (
|
||||
mock_response.ok = True
|
||||
mock_response.text = (
|
||||
'[delorean]\nname=delorean-openstack-nova-81c23c04'
|
||||
'7e8e0fc03b54164921f49fdb4103202c\nbaseurl=https:/'
|
||||
'/trunk.rdoproject.org/centos7/81/c2/81c23c047e8e0'
|
||||
'fc03b54164921f49fdb4103202c_b333f915\nenabled=1\n'
|
||||
'gpgcheck=0\npriority=1')
|
||||
mock_get.return_value = mock_response
|
||||
release = 'master'
|
||||
hash_name = 'current-tripleo'
|
||||
dlrn_hash = '81c23c047e8e0fc03b54164921f49fdb4103202c_b333f915'
|
||||
repo_url = ('https://trunk.rdoproject.org/centos7-%s/%s/delorean.repo' %
|
||||
(release, hash_name))
|
||||
mock_get.return_value = mock_response
|
||||
assert (get_dlrn_hash(
|
||||
release,
|
||||
hash_name) == '81c23c047e8e0fc03b54164921f49fdb4103202c_b333f915')
|
||||
mock_get.assert_called_once_with(repo_url, timeout=(3.05, 27))
|
||||
assert get_dlrn_hash(release, hash_name) == dlrn_hash
|
||||
mock_get.assert_called_once_with(repo_url, timeout=4)
|
||||
mock_log_info.assert_called_once_with("Got DLRN hash: {} for the named "
|
||||
"hash: {} on the {} "
|
||||
"release".format(dlrn_hash,
|
||||
hash_name,
|
||||
release))
|
||||
mock_log_warning.assert_not_called()
|
||||
mock_log_exception.assert_not_called()
|
||||
|
||||
|
||||
@mock.patch('logging.getLogger')
|
||||
@mock.patch('requests.get')
|
||||
def test_null_response_raises_runtimeerror(mock_get):
|
||||
def test_null_response_raises_runtimeerror(mock_get, mock_logging):
|
||||
mock_logger = mock.MagicMock()
|
||||
mock_logging.return_value = mock_logger
|
||||
mock_log_exception = mock.MagicMock()
|
||||
mock_log_warning = mock.MagicMock()
|
||||
mock_log_info = mock.MagicMock()
|
||||
mock_logger.exception = mock_log_exception
|
||||
mock_logger.warning = mock_log_warning
|
||||
mock_logger.info = mock_log_info
|
||||
release = 'master'
|
||||
hash_name = 'current-tripleo'
|
||||
repo_url = ('https://trunk.rdoproject.org/centos7-%s/%s/delorean.repo' %
|
||||
|
@ -33,5 +58,107 @@ def test_null_response_raises_runtimeerror(mock_get):
|
|||
mock_get.return_value = None
|
||||
with pytest.raises(RuntimeError):
|
||||
get_dlrn_hash(release, hash_name)
|
||||
mock_get.assert_called_with(repo_url, timeout=(3.05, 27))
|
||||
assert (10 == mock_get.call_count)
|
||||
mock_get.assert_called_with(repo_url, timeout=4)
|
||||
assert mock_get.call_count == 10
|
||||
mock_log_info.assert_not_called()
|
||||
mock_log_warning.assert_called_with("Attempt 10 of 10 to get DLRN hash "
|
||||
"failed to get a response.")
|
||||
assert mock_log_warning.call_count == 10
|
||||
mock_log_exception.assert_not_called()
|
||||
|
||||
|
||||
@mock.patch('logging.getLogger')
|
||||
@mock.patch('requests.get')
|
||||
def test_get_dlrn_hash_500_then_200(mock_get, mock_logging):
|
||||
mock_logger = mock.MagicMock()
|
||||
mock_logging.return_value = mock_logger
|
||||
mock_log_exception = mock.MagicMock()
|
||||
mock_log_warning = mock.MagicMock()
|
||||
mock_log_info = mock.MagicMock()
|
||||
mock_logger.exception = mock_log_exception
|
||||
mock_logger.warning = mock_log_warning
|
||||
mock_logger.info = mock_log_info
|
||||
mock_response_ok = mock.Mock()
|
||||
mock_response_ok.ok = True
|
||||
mock_response_ok.text = (
|
||||
'[delorean]\nname=delorean-openstack-nova-81c23c04'
|
||||
'7e8e0fc03b54164921f49fdb4103202c\nbaseurl=https:/'
|
||||
'/trunk.rdoproject.org/centos7/81/c2/81c23c047e8e0'
|
||||
'fc03b54164921f49fdb4103202c_b333f915\nenabled=1\n'
|
||||
'gpgcheck=0\npriority=1')
|
||||
mock_response_bad = mock.Mock()
|
||||
mock_response_bad.ok = False
|
||||
mock_response_bad.status_code = 500
|
||||
release = 'master'
|
||||
hash_name = 'current-tripleo'
|
||||
dlrn_hash = '81c23c047e8e0fc03b54164921f49fdb4103202c_b333f915'
|
||||
repo_url = ('https://trunk.rdoproject.org/centos7-%s/%s/delorean.repo' %
|
||||
(release, hash_name))
|
||||
mock_get.side_effect = [mock_response_bad, mock_response_ok]
|
||||
assert get_dlrn_hash(release, hash_name, retries=10) == dlrn_hash
|
||||
mock_get.assert_called_with(repo_url, timeout=4)
|
||||
mock_log_info.assert_called_once_with("Got DLRN hash: {} for the named "
|
||||
"hash: {} on the {} "
|
||||
"release".format(dlrn_hash,
|
||||
hash_name,
|
||||
release))
|
||||
mock_log_warning.assert_called_once_with("Attempt 1 of 10 to get DLRN "
|
||||
"hash returned status code 500.")
|
||||
mock_log_exception.assert_not_called()
|
||||
|
||||
|
||||
@mock.patch('logging.getLogger')
|
||||
@mock.patch('requests.get')
|
||||
def test_get_dlrn_hash_timeout(mock_get, mock_logging):
|
||||
mock_logger = mock.MagicMock()
|
||||
mock_logging.return_value = mock_logger
|
||||
mock_log_exception = mock.MagicMock()
|
||||
mock_log_warning = mock.MagicMock()
|
||||
mock_log_info = mock.MagicMock()
|
||||
mock_logger.exception = mock_log_exception
|
||||
mock_logger.warning = mock_log_warning
|
||||
mock_logger.info = mock_log_info
|
||||
release = 'master'
|
||||
hash_name = 'current-tripleo'
|
||||
repo_url = ('https://trunk.rdoproject.org/centos7-%s/%s/delorean.repo' %
|
||||
(release, hash_name))
|
||||
mock_get_exception = Exception("We need more power!")
|
||||
mock_get.side_effect = mock_get_exception
|
||||
with pytest.raises(RuntimeError):
|
||||
get_dlrn_hash(release, hash_name, retries=10)
|
||||
mock_get.assert_called_with(repo_url, timeout=4)
|
||||
mock_log_info.assert_not_called()
|
||||
mock_log_warning.assert_called_with("Attempt 10 of 10 to get DLRN hash "
|
||||
"threw an exception.")
|
||||
assert mock_log_warning.call_count == 10
|
||||
mock_log_exception.assert_called_with(mock_get_exception)
|
||||
assert mock_log_exception.call_count == 10
|
||||
|
||||
|
||||
@mock.patch('logging.getLogger')
|
||||
@mock.patch('requests.get')
|
||||
def test_get_dlrn_hash_500_10_times(mock_get, mock_logging):
|
||||
mock_logger = mock.MagicMock()
|
||||
mock_logging.return_value = mock_logger
|
||||
mock_log_exception = mock.MagicMock()
|
||||
mock_log_warning = mock.MagicMock()
|
||||
mock_log_info = mock.MagicMock()
|
||||
mock_logger.exception = mock_log_exception
|
||||
mock_logger.warning = mock_log_warning
|
||||
mock_logger.info = mock_log_info
|
||||
mock_response = mock.Mock()
|
||||
mock_response.ok = False
|
||||
mock_response.status_code = 500
|
||||
release = 'master'
|
||||
hash_name = 'current-tripleo'
|
||||
repo_url = ('https://trunk.rdoproject.org/centos7-%s/%s/delorean.repo' %
|
||||
(release, hash_name))
|
||||
mock_get.return_value = mock_response
|
||||
with pytest.raises(RuntimeError):
|
||||
get_dlrn_hash(release, hash_name, retries=10)
|
||||
mock_get.assert_called_with(repo_url, timeout=4)
|
||||
mock_log_info.assert_not_called()
|
||||
mock_log_warning.assert_called_with("Attempt 10 of 10 to get DLRN hash "
|
||||
"returned status code 500.")
|
||||
assert mock_log_warning.call_count == 10
|
||||
mock_log_exception.assert_not_called()
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
from emit_releases_file import compose_releases_dictionary
|
||||
|
||||
import mock
|
||||
import pytest
|
||||
|
||||
|
||||
@mock.patch('emit_releases_file.get_dlrn_hash')
|
||||
@pytest.mark.parametrize('stable_release,expected_releases',
|
||||
[('master', {
|
||||
'undercloud_install_release': 'master',
|
||||
|
@ -10,7 +12,7 @@ import pytest
|
|||
'undercloud_target_release': 'master',
|
||||
'undercloud_target_hash': 'current-tripleo',
|
||||
'overcloud_deploy_release': 'queens',
|
||||
'overcloud_deploy_hash': 'current-tripleo',
|
||||
'overcloud_deploy_hash': 'old-current-tripleo',
|
||||
'overcloud_target_release': 'master',
|
||||
'overcloud_target_hash': 'current-tripleo',
|
||||
}), ('queens', {
|
||||
|
@ -19,7 +21,7 @@ import pytest
|
|||
'undercloud_target_release': 'queens',
|
||||
'undercloud_target_hash': 'current-tripleo',
|
||||
'overcloud_deploy_release': 'pike',
|
||||
'overcloud_deploy_hash': 'current-tripleo',
|
||||
'overcloud_deploy_hash': 'old-current-tripleo',
|
||||
'overcloud_target_release': 'queens',
|
||||
'overcloud_target_hash': 'current-tripleo',
|
||||
}), ('pike', {
|
||||
|
@ -28,20 +30,27 @@ import pytest
|
|||
'undercloud_target_release': 'pike',
|
||||
'undercloud_target_hash': 'current-tripleo',
|
||||
'overcloud_deploy_release': 'ocata',
|
||||
'overcloud_deploy_hash': 'current-tripleo',
|
||||
'overcloud_deploy_hash': 'old-current-tripleo',
|
||||
'overcloud_target_release': 'pike',
|
||||
'overcloud_target_hash': 'current-tripleo',
|
||||
})])
|
||||
def test_overcloud_upgrade_is_n_minus_one_to_n(stable_release,
|
||||
def test_overcloud_upgrade_is_n_minus_one_to_n(mock_get_hash,
|
||||
stable_release,
|
||||
expected_releases):
|
||||
mock_get_hash.side_effect = ['current-tripleo', 'old-current-tripleo']
|
||||
featureset = {
|
||||
'mixed_upgrade': True,
|
||||
'overcloud_upgrade': True,
|
||||
}
|
||||
assert (compose_releases_dictionary(stable_release,
|
||||
featureset) == expected_releases)
|
||||
mock_get_hash.assert_has_calls(
|
||||
[mock.call(stable_release, 'current-tripleo'),
|
||||
mock.call(expected_releases['overcloud_deploy_release'],
|
||||
'current-tripleo')])
|
||||
|
||||
|
||||
@mock.patch('emit_releases_file.get_dlrn_hash')
|
||||
@pytest.mark.parametrize('stable_release,expected_releases', [
|
||||
('queens', {
|
||||
'undercloud_install_release': 'queens',
|
||||
|
@ -49,25 +58,32 @@ def test_overcloud_upgrade_is_n_minus_one_to_n(stable_release,
|
|||
'undercloud_target_release': 'queens',
|
||||
'undercloud_target_hash': 'current-tripleo',
|
||||
'overcloud_deploy_release': 'newton',
|
||||
'overcloud_deploy_hash': 'current-tripleo',
|
||||
'overcloud_deploy_hash': 'old-current-tripleo',
|
||||
'overcloud_target_release': 'queens',
|
||||
'overcloud_target_hash': 'current-tripleo',
|
||||
}),
|
||||
])
|
||||
def test_ffu_overcloud_upgrade_is_n_minus_three_to_n(stable_release,
|
||||
def test_ffu_overcloud_upgrade_is_n_minus_three_to_n(mock_get_hash,
|
||||
stable_release,
|
||||
expected_releases):
|
||||
mock_get_hash.side_effect = ['current-tripleo', 'old-current-tripleo']
|
||||
featureset = {
|
||||
'mixed_upgrade': True,
|
||||
'ffu_overcloud_upgrade': True,
|
||||
}
|
||||
assert (compose_releases_dictionary(stable_release,
|
||||
featureset) == expected_releases)
|
||||
mock_get_hash.assert_has_calls(
|
||||
[mock.call(stable_release, 'current-tripleo'),
|
||||
mock.call(expected_releases['overcloud_deploy_release'],
|
||||
'current-passed-ci')])
|
||||
|
||||
|
||||
@mock.patch('emit_releases_file.get_dlrn_hash')
|
||||
@pytest.mark.parametrize('stable_release,expected_releases', [
|
||||
('master', {
|
||||
'undercloud_install_release': 'queens',
|
||||
'undercloud_install_hash': 'current-tripleo',
|
||||
'undercloud_install_hash': 'old-current-tripleo',
|
||||
'undercloud_target_release': 'master',
|
||||
'undercloud_target_hash': 'current-tripleo',
|
||||
'overcloud_deploy_release': 'master',
|
||||
|
@ -76,15 +92,22 @@ def test_ffu_overcloud_upgrade_is_n_minus_three_to_n(stable_release,
|
|||
'overcloud_target_hash': 'current-tripleo',
|
||||
}),
|
||||
])
|
||||
def test_undercloud_upgrade_is_n_minus_one_to_n(stable_release,
|
||||
def test_undercloud_upgrade_is_n_minus_one_to_n(mock_get_hash,
|
||||
stable_release,
|
||||
expected_releases):
|
||||
mock_get_hash.side_effect = ['current-tripleo', 'old-current-tripleo']
|
||||
featureset = {
|
||||
'undercloud_upgrade': True,
|
||||
}
|
||||
assert (compose_releases_dictionary(stable_release,
|
||||
featureset) == expected_releases)
|
||||
mock_get_hash.assert_has_calls(
|
||||
[mock.call(stable_release, 'current-tripleo'),
|
||||
mock.call(expected_releases['undercloud_install_release'],
|
||||
'current-tripleo')])
|
||||
|
||||
|
||||
@mock.patch('emit_releases_file.get_dlrn_hash')
|
||||
@pytest.mark.parametrize(
|
||||
'stable_release,expected_releases',
|
||||
[('master', {
|
||||
|
@ -106,14 +129,22 @@ def test_undercloud_upgrade_is_n_minus_one_to_n(stable_release,
|
|||
'overcloud_target_release': 'queens',
|
||||
'overcloud_target_hash': 'current-tripleo',
|
||||
})])
|
||||
def test_overcloud_update_target_is_hash(stable_release, expected_releases):
|
||||
def test_overcloud_update_target_is_hash(mock_get_hash,
|
||||
stable_release,
|
||||
expected_releases):
|
||||
mock_get_hash.side_effect = ['current-tripleo', 'previous-current-tripleo']
|
||||
featureset = {
|
||||
'overcloud_update': True,
|
||||
}
|
||||
assert (compose_releases_dictionary(stable_release,
|
||||
featureset) == expected_releases)
|
||||
mock_get_hash.assert_has_calls(
|
||||
[mock.call(stable_release, 'current-tripleo'),
|
||||
mock.call(expected_releases['overcloud_deploy_release'],
|
||||
'previous-current-tripleo')])
|
||||
|
||||
|
||||
@mock.patch('emit_releases_file.get_dlrn_hash')
|
||||
@pytest.mark.parametrize('stable_release,expected_releases',
|
||||
[('master', {
|
||||
'undercloud_install_release': 'master',
|
||||
|
@ -152,7 +183,11 @@ def test_overcloud_update_target_is_hash(stable_release, expected_releases):
|
|||
'overcloud_target_release': 'ocata',
|
||||
'overcloud_target_hash': 'current-tripleo',
|
||||
})])
|
||||
def test_noop_target_is_the_same(stable_release, expected_releases):
|
||||
def test_noop_target_is_the_same(mock_get_hash,
|
||||
stable_release,
|
||||
expected_releases):
|
||||
mock_get_hash.return_value = 'current-tripleo'
|
||||
featureset = {}
|
||||
assert (compose_releases_dictionary(stable_release,
|
||||
featureset) == expected_releases)
|
||||
mock_get_hash.assert_called_once_with(stable_release, 'current-tripleo')
|
||||
|
|
Loading…
Reference in New Issue