summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.zuul.yaml8
-rw-r--r--bindep.txt2
-rw-r--r--devstack/lib/heat6
-rw-r--r--doc/source/getting_started/on_devstack.rst4
-rw-r--r--heat/api/openstack/v1/software_configs.py12
-rw-r--r--heat/common/environment_util.py17
-rw-r--r--heat/common/pluginutils.py20
-rw-r--r--heat/engine/resources/openstack/neutron/net.py10
-rw-r--r--heat/engine/resources/openstack/neutron/provider_net.py13
-rw-r--r--heat/engine/resources/openstack/neutron/router.py13
-rw-r--r--heat/tests/api/openstack_v1/test_software_configs.py35
-rw-r--r--heat/tests/api/openstack_v1/test_stacks.py64
-rw-r--r--heat/tests/openstack/neutron/test_neutron_net.py3
-rw-r--r--heat/tests/openstack/neutron/test_neutron_provider_net.py9
-rw-r--r--heat/tests/openstack/neutron/test_neutron_router.py3
-rw-r--r--heat/tests/test_common_env_util.py11
-rw-r--r--heat/tests/test_common_pluginutils.py31
-rwxr-xr-xheat_integrationtests/cleanup_test_env.sh2
-rwxr-xr-xheat_integrationtests/prepare_test_env.sh2
-rw-r--r--lower-constraints.txt161
-rw-r--r--releasenotes/notes/availability_zone_hints_Neutron_network_router-d01df1463193d9e6.yaml5
-rw-r--r--releasenotes/notes/drop-python-3-6-and-3-7-69dcd178c443e177.yaml5
-rw-r--r--releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po43
-rw-r--r--requirements.txt4
-rw-r--r--roles/run-heat-tests/defaults/main.yaml3
-rw-r--r--roles/run-heat-tests/tasks/main.yaml23
-rw-r--r--setup.cfg4
-rw-r--r--setup.py1
-rw-r--r--tox.ini9
29 files changed, 313 insertions, 210 deletions
diff --git a/.zuul.yaml b/.zuul.yaml
index ef999cb9a..8039ad9fb 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -72,7 +72,7 @@
minimal_image_ref: ${DEFAULT_IMAGE_NAME:-cirros-0.3.6-x86_64-disk}
instance_type: m1.heat_int
minimal_instance_type: m1.heat_micro
- image_ref: Fedora-Cloud-Base-33-1.2.x86_64
+ image_ref: Fedora-Cloud-Base-36-1.5.x86_64
hidden_stack_tag: hidden
heat_config_notify_script: /opt/stack/heat-agents/heat-config/bin/heat-config-notify
boot_config_env: /opt/stack/heat-templates/hot/software-config/boot-config/test_image_env.yaml
@@ -181,9 +181,9 @@
- ^releasenotes/.*$
- project:
+ queue: heat
templates:
- openstack-cover-jobs
- - openstack-lower-constraints-jobs
- openstack-python3-zed-jobs
- openstack-python3-zed-jobs-arm64
- periodic-stable-jobs
@@ -196,11 +196,7 @@
- heat-functional
- heat-functional-legacy
gate:
- queue: heat
jobs:
- grenade-heat-multinode
- heat-functional
- heat-functional-legacy
- experimental:
- jobs:
- - tripleo-ci-centos-8-scenario002-standalone
diff --git a/bindep.txt b/bindep.txt
index 7071c188b..55d97b80b 100644
--- a/bindep.txt
+++ b/bindep.txt
@@ -6,7 +6,6 @@ mariadb-server [platform:redhat]
postgresql
build-essential [platform:dpkg]
-python-dev [platform:dpkg]
python3-all-dev [platform:dpkg]
libxml2-dev [platform:dpkg]
libxslt1-dev [platform:dpkg]
@@ -19,7 +18,6 @@ mysql-client [platform:dpkg]
postgresql-client [platform:dpkg]
gcc [platform:rpm]
-python-devel [platform:rpm]
python3-devel [platform:fedora platform:suse]
python3 [platform:suse]
libxml2-devel [platform:rpm]
diff --git a/devstack/lib/heat b/devstack/lib/heat
index d95e15266..dcd59b6f4 100644
--- a/devstack/lib/heat
+++ b/devstack/lib/heat
@@ -449,7 +449,7 @@ function configure_tempest_for_heat {
# Skip LoadBalancerv2Test as deprecated neutron-lbaas service is not enabled
iniset $TEMPEST_CONFIG heat_plugin skip_functional_test_list 'LoadBalancerv2Test, NotificationTest'
- openstack flavor show m1.heat_int || openstack flavor create m1.heat_int --ram 512 --disk 4
+ openstack flavor show m1.heat_int || openstack flavor create m1.heat_int --ram 512 --disk 10
openstack flavor show m1.heat_micro || openstack flavor create m1.heat_micro --ram 128 --disk 1
export OS_CLOUD=devstack
@@ -463,14 +463,14 @@ function configure_tempest_for_heat {
source /etc/ci/mirror_info.sh
fi
HEAT_TEST_FEDORA_IMAGE_UPSTREAM=https://download.fedoraproject.org/pub/fedora/linux
- HEAT_TEST_FEDORA_IMAGE_PATH=releases/33/Cloud/x86_64/images/Fedora-Cloud-Base-33-1.2.x86_64.qcow2
+ HEAT_TEST_FEDORA_IMAGE_PATH=releases/36/Cloud/x86_64/images/Fedora-Cloud-Base-36-1.5.x86_64.qcow2
if curl --output /dev/null --silent --head --fail "${NODEPOOL_FEDORA_MIRROR}/${HEAT_TEST_FEDORA_IMAGE_PATH}"; then
export HEAT_TEST_FEDORA_IMAGE="${NODEPOOL_FEDORA_MIRROR}/${HEAT_TEST_FEDORA_IMAGE_PATH}"
else
export HEAT_TEST_FEDORA_IMAGE="${HEAT_TEST_FEDORA_IMAGE_UPSTREAM}/${HEAT_TEST_FEDORA_IMAGE_PATH}"
fi
TOKEN=$(openstack token issue -c id -f value)
- local image_exists=$( openstack image list | grep "Fedora-Cloud-Base-33-1.2.x86_64" )
+ local image_exists=$( openstack image list | grep "Fedora-Cloud-Base-36-1.5.x86_64" )
if [[ -z $image_exists ]]; then
if is_service_enabled g-api; then
upload_image $HEAT_TEST_FEDORA_IMAGE $TOKEN
diff --git a/doc/source/getting_started/on_devstack.rst b/doc/source/getting_started/on_devstack.rst
index 29581390d..64d607ab2 100644
--- a/doc/source/getting_started/on_devstack.rst
+++ b/doc/source/getting_started/on_devstack.rst
@@ -51,8 +51,8 @@ a VM image that heat can launch. To do that add the following to
`[[local|localrc]]` section of `local.conf`::
IMAGE_URL_SITE="https://download.fedoraproject.org"
- IMAGE_URL_PATH="/pub/fedora/linux/releases/33/Cloud/x86_64/images/"
- IMAGE_URL_FILE="Fedora-Cloud-Base-33-1.2.x86_64.qcow2"
+ IMAGE_URL_PATH="/pub/fedora/linux/releases/36/Cloud/x86_64/images/"
+ IMAGE_URL_FILE="Fedora-Cloud-Base-36-1.5.x86_64.qcow2"
IMAGE_URLS+=","$IMAGE_URL_SITE$IMAGE_URL_PATH$IMAGE_URL_FILE
URLs for any cloud image may be specified, but fedora images from F20 contain
diff --git a/heat/api/openstack/v1/software_configs.py b/heat/api/openstack/v1/software_configs.py
index 41f9486e4..c27da4fe7 100644
--- a/heat/api/openstack/v1/software_configs.py
+++ b/heat/api/openstack/v1/software_configs.py
@@ -43,6 +43,14 @@ class SoftwareConfigController(object):
except ValueError as e:
raise exc.HTTPBadRequest(str(e))
+ def _extract_int_param(self, name, value,
+ allow_zero=True, allow_negative=False):
+ try:
+ return param_utils.extract_int(name, value,
+ allow_zero, allow_negative)
+ except ValueError as e:
+ raise exc.HTTPBadRequest(str(e))
+
def _index(self, req, use_admin_cnxt=False):
param_types = {
'limit': util.PARAM_TYPE_SINGLE,
@@ -50,6 +58,10 @@ class SoftwareConfigController(object):
}
params = util.get_allowed_params(req.params, param_types)
+ key = rpc_api.PARAM_LIMIT
+ if key in params:
+ params[key] = self._extract_int_param(key, params[key])
+
if use_admin_cnxt:
cnxt = context.get_admin_context()
else:
diff --git a/heat/common/environment_util.py b/heat/common/environment_util.py
index 8a6ed4393..eb3b8cde1 100644
--- a/heat/common/environment_util.py
+++ b/heat/common/environment_util.py
@@ -12,6 +12,7 @@
# under the License.
import collections
+from oslo_log import log as logging
from oslo_serialization import jsonutils
from heat.common import environment_format as env_fmt
@@ -21,15 +22,22 @@ from heat.common.i18n import _
ALLOWED_PARAM_MERGE_STRATEGIES = (OVERWRITE, MERGE, DEEP_MERGE) = (
'overwrite', 'merge', 'deep_merge')
+LOG = logging.getLogger(__name__)
-def get_param_merge_strategy(merge_strategies, param_key):
+
+def get_param_merge_strategy(merge_strategies, param_key,
+ available_strategies=None):
+ if not available_strategies:
+ available_strategies = {}
if merge_strategies is None:
return OVERWRITE
env_default = merge_strategies.get('default', OVERWRITE)
+ merge_strategy = merge_strategies.get(
+ param_key, available_strategies.get(
+ param_key, env_default))
- merge_strategy = merge_strategies.get(param_key, env_default)
if merge_strategy in ALLOWED_PARAM_MERGE_STRATEGIES:
return merge_strategy
@@ -114,7 +122,7 @@ def merge_parameters(old, new, param_schemata, strategies_in_file,
# if key not in param_schemata ignore it
if key in param_schemata and value is not None:
param_merge_strategy = get_param_merge_strategy(
- strategies_in_file, key)
+ strategies_in_file, key, available_strategies)
if key not in available_strategies:
new_strategies[key] = param_merge_strategy
@@ -124,12 +132,15 @@ def merge_parameters(old, new, param_schemata, strategies_in_file,
param=key, env_file=env_file)
if param_merge_strategy == DEEP_MERGE:
+ LOG.debug("Deep Merging Parameter: %s", key)
param_merge(key, value,
param_schemata[key],
deep_merge=True)
elif param_merge_strategy == MERGE:
+ LOG.debug("Merging Parameter: %s", key)
param_merge(key, value, param_schemata[key])
else:
+ LOG.debug("Overriding Parameter: %s", key)
old[key] = value
return old, new_strategies
diff --git a/heat/common/pluginutils.py b/heat/common/pluginutils.py
index c4da0ec06..1fc9618ee 100644
--- a/heat/common/pluginutils.py
+++ b/heat/common/pluginutils.py
@@ -18,9 +18,17 @@ LOG = logging.getLogger(__name__)
def log_fail_msg(manager, entrypoint, exception):
- LOG.warning('Encountered exception while loading %(module_name)s: '
- '"%(message)s". Not using %(name)s.',
- {'module_name': entrypoint.module,
- 'message': getattr(exception, 'message',
- str(exception)),
- 'name': entrypoint.name})
+ # importlib.metadata in Python 3.8 is quite old and the EntryPoint class
+ # does not have module. This logic is required to workaround AttributeError
+ # caused by that old implementation.
+ if hasattr(entrypoint, 'module'):
+ LOG.warning('Encountered exception while loading %(module_name)s: '
+ '"%(message)s". Not using %(name)s.',
+ {'module_name': entrypoint.module,
+ 'message': getattr(exception, 'message', str(exception)),
+ 'name': entrypoint.name})
+ else:
+ LOG.warning('Encountered exception: "%(message)s". '
+ 'Not using %(name)s.',
+ {'message': getattr(exception, 'message', str(exception)),
+ 'name': entrypoint.name})
diff --git a/heat/engine/resources/openstack/neutron/net.py b/heat/engine/resources/openstack/neutron/net.py
index d0d2ebd8d..156c03042 100644
--- a/heat/engine/resources/openstack/neutron/net.py
+++ b/heat/engine/resources/openstack/neutron/net.py
@@ -33,11 +33,11 @@ class Net(neutron.NeutronResource):
PROPERTIES = (
NAME, VALUE_SPECS, ADMIN_STATE_UP, TENANT_ID, SHARED,
DHCP_AGENT_IDS, PORT_SECURITY_ENABLED, QOS_POLICY,
- DNS_DOMAIN, TAGS,
+ DNS_DOMAIN, AVAILABILITY_ZONE_HINTS, TAGS,
) = (
'name', 'value_specs', 'admin_state_up', 'tenant_id', 'shared',
'dhcp_agent_ids', 'port_security_enabled', 'qos_policy',
- 'dns_domain', 'tags',
+ 'dns_domain', 'availability_zone_hints', 'tags',
)
ATTRIBUTES = (
@@ -118,6 +118,12 @@ class Net(neutron.NeutronResource):
update_allowed=True,
support_status=support.SupportStatus(version='7.0.0')
),
+ AVAILABILITY_ZONE_HINTS: properties.Schema(
+ properties.Schema.LIST,
+ _('Availability zone candidates for the network. It requires the '
+ 'availability_zone extension to be available.'),
+ support_status=support.SupportStatus(version='19.0.0')
+ ),
TAGS: properties.Schema(
properties.Schema.LIST,
_('The tags to be added to the network.'),
diff --git a/heat/engine/resources/openstack/neutron/provider_net.py b/heat/engine/resources/openstack/neutron/provider_net.py
index 9f5a038c7..899b29590 100644
--- a/heat/engine/resources/openstack/neutron/provider_net.py
+++ b/heat/engine/resources/openstack/neutron/provider_net.py
@@ -37,11 +37,13 @@ class ProviderNet(net.Net):
PROPERTIES = (
NAME, PROVIDER_NETWORK_TYPE, PROVIDER_PHYSICAL_NETWORK,
PROVIDER_SEGMENTATION_ID, ADMIN_STATE_UP, SHARED,
- PORT_SECURITY_ENABLED, ROUTER_EXTERNAL, DNS_DOMAIN, TAGS,
+ PORT_SECURITY_ENABLED, ROUTER_EXTERNAL, DNS_DOMAIN,
+ AVAILABILITY_ZONE_HINTS, TAGS,
) = (
'name', 'network_type', 'physical_network',
'segmentation_id', 'admin_state_up', 'shared',
- 'port_security_enabled', 'router_external', 'dns_domain', 'tags',
+ 'port_security_enabled', 'router_external', 'dns_domain',
+ 'availability_zone_hints', 'tags',
)
@@ -119,6 +121,13 @@ class ProviderNet(net.Net):
update_allowed=True,
support_status=support.SupportStatus(version='15.0.0')
),
+ AVAILABILITY_ZONE_HINTS: properties.Schema(
+ properties.Schema.LIST,
+ _('Availability zone candidates for the network. It requires the '
+ 'availability_zone extension to be available.'),
+ update_allowed=True,
+ support_status=support.SupportStatus(version='19.0.0')
+ ),
}
attributes_schema = {
diff --git a/heat/engine/resources/openstack/neutron/router.py b/heat/engine/resources/openstack/neutron/router.py
index 1127a2c10..72f7dbbdd 100644
--- a/heat/engine/resources/openstack/neutron/router.py
+++ b/heat/engine/resources/openstack/neutron/router.py
@@ -35,10 +35,12 @@ class Router(neutron.NeutronResource):
PROPERTIES = (
NAME, EXTERNAL_GATEWAY, VALUE_SPECS, ADMIN_STATE_UP,
- L3_AGENT_ID, L3_AGENT_IDS, DISTRIBUTED, HA, TAGS,
+ L3_AGENT_ID, L3_AGENT_IDS, DISTRIBUTED, HA, AVAILABILITY_ZONE_HINTS,
+ TAGS,
) = (
'name', 'external_gateway_info', 'value_specs', 'admin_state_up',
- 'l3_agent_id', 'l3_agent_ids', 'distributed', 'ha', 'tags',
+ 'l3_agent_id', 'l3_agent_ids', 'distributed', 'ha',
+ 'availability_zone_hints', 'tags',
)
_EXTERNAL_GATEWAY_KEYS = (
@@ -171,6 +173,13 @@ class Router(neutron.NeutronResource):
'do not support distributed and ha at the same time.'),
support_status=support.SupportStatus(version='2015.1')
),
+ AVAILABILITY_ZONE_HINTS: properties.Schema(
+ properties.Schema.LIST,
+ _('Availability zone candidates for the router. It requires the '
+ 'availability_zone extension to be available.'),
+ update_allowed=True,
+ support_status=support.SupportStatus(version='19.0.0')
+ ),
TAGS: properties.Schema(
properties.Schema.LIST,
_('The tags to be added to the router.'),
diff --git a/heat/tests/api/openstack_v1/test_software_configs.py b/heat/tests/api/openstack_v1/test_software_configs.py
index c1516eda0..110bfaef5 100644
--- a/heat/tests/api/openstack_v1/test_software_configs.py
+++ b/heat/tests/api/openstack_v1/test_software_configs.py
@@ -47,6 +47,41 @@ class SoftwareConfigControllerTest(tools.ControllerTest, common.HeatTestCase):
{'software_configs': []}, resp)
@mock.patch.object(policy.Enforcer, 'enforce')
+ def test_index_limit_negative(self, mock_enforce):
+ self._mock_enforce_setup(mock_enforce, 'index')
+ params = {'limit': -1}
+
+ with mock.patch.object(
+ self.controller.rpc_client,
+ 'list_software_configs',
+ return_value=[]) as mock_call:
+ req = self._get('/software_configs', params=params)
+ ex = self.assertRaises(webob.exc.HTTPBadRequest,
+ self.controller.index, req,
+ tenant_id=self.tenant)
+ self.assertEqual("Value '-1' is invalid for 'limit' which only "
+ "accepts non-negative integer.",
+ str(ex))
+ self.assertFalse(mock_call.called)
+
+ @mock.patch.object(policy.Enforcer, 'enforce')
+ def test_index_limit_not_int(self, mock_enforce):
+ self._mock_enforce_setup(mock_enforce, 'index')
+ params = {'limit': 'not-an-int'}
+
+ with mock.patch.object(
+ self.controller.rpc_client,
+ 'list_software_configs',
+ return_value=[]) as mock_call:
+ req = self._get('/software_configs', params=params)
+ ex = self.assertRaises(webob.exc.HTTPBadRequest,
+ self.controller.index, req,
+ tenant_id=self.tenant)
+ self.assertEqual("Only integer is acceptable by 'limit'.",
+ str(ex))
+ self.assertFalse(mock_call.called)
+
+ @mock.patch.object(policy.Enforcer, 'enforce')
def test_show(self, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'show')
config_id = 'a45559cd-8736-4375-bc39-d6a7bb62ade2'
diff --git a/heat/tests/api/openstack_v1/test_stacks.py b/heat/tests/api/openstack_v1/test_stacks.py
index 48d1ebd61..6c1a46467 100644
--- a/heat/tests/api/openstack_v1/test_stacks.py
+++ b/heat/tests/api/openstack_v1/test_stacks.py
@@ -338,6 +338,20 @@ class StackControllerTest(tools.ControllerTest, common.HeatTestCase):
self.assertNotIn('balrog', engine_args)
@mock.patch.object(rpc_client.EngineClient, 'call')
+ def test_index_limit_negative(self, mock_call, mock_enforce):
+ self._mock_enforce_setup(mock_enforce, 'index', True)
+ params = {'limit': -1}
+ req = self._get('/stacks', params=params)
+
+ ex = self.assertRaises(webob.exc.HTTPBadRequest,
+ self.controller.index, req,
+ tenant_id=self.tenant)
+ self.assertEqual("Value '-1' is invalid for 'limit' which only "
+ "accepts non-negative integer.",
+ str(ex))
+ self.assertFalse(mock_call.called)
+
+ @mock.patch.object(rpc_client.EngineClient, 'call')
def test_index_limit_not_int(self, mock_call, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'index', True)
params = {'limit': 'not-an-int'}
@@ -1936,6 +1950,31 @@ class StackControllerTest(tools.ControllerTest, common.HeatTestCase):
version='1.36'
)
+ def test_update_timeout_negative(self, mock_enforce):
+ self._mock_enforce_setup(mock_enforce, 'update', True)
+ identity = identifier.HeatIdentifier(self.tenant, 'wibble', '6')
+ template = {u'Foo': u'bar'}
+ parameters = {u'InstanceType': u'm1.xlarge'}
+ body = {'template': template,
+ 'parameters': parameters,
+ 'files': {},
+ 'timeout_mins': -1}
+
+ req = self._put('/stacks/%(stack_name)s/%(stack_id)s' % identity,
+ json.dumps(body))
+
+ mock_call = self.patchobject(rpc_client.EngineClient, 'call')
+ ex = self.assertRaises(webob.exc.HTTPBadRequest,
+ self.controller.update, req,
+ tenant_id=identity.tenant,
+ stack_name=identity.stack_name,
+ stack_id=identity.stack_id,
+ body=body)
+ self.assertEqual("Value '-1' is invalid for 'timeout_mins' which only "
+ "accepts non-negative integer.",
+ str(ex))
+ self.assertFalse(mock_call.called)
+
def test_update_timeout_not_int(self, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'update', True)
identity = identifier.HeatIdentifier(self.tenant, 'wibble', '6')
@@ -2149,6 +2188,31 @@ class StackControllerTest(tools.ControllerTest, common.HeatTestCase):
version='1.36'
)
+ def test_update_with_patch_timeout_negative(self, mock_enforce):
+ self._mock_enforce_setup(mock_enforce, 'update_patch', True)
+ identity = identifier.HeatIdentifier(self.tenant, 'wordpress', '6')
+ template = {u'Foo': u'bar'}
+ parameters = {u'InstanceType': u'm1.xlarge'}
+ body = {'template': template,
+ 'parameters': parameters,
+ 'files': {},
+ 'timeout_mins': -1}
+
+ req = self._patch('/stacks/%(stack_name)s/%(stack_id)s' % identity,
+ json.dumps(body))
+
+ mock_call = self.patchobject(rpc_client.EngineClient, 'call')
+ ex = self.assertRaises(webob.exc.HTTPBadRequest,
+ self.controller.update_patch, req,
+ tenant_id=identity.tenant,
+ stack_name=identity.stack_name,
+ stack_id=identity.stack_id,
+ body=body)
+ self.assertEqual("Value '-1' is invalid for 'timeout_mins' which only "
+ "accepts non-negative integer.",
+ str(ex))
+ self.assertFalse(mock_call.called)
+
def test_update_with_patch_timeout_not_int(self, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'update_patch', True)
identity = identifier.HeatIdentifier(self.tenant, 'wordpress', '6')
diff --git a/heat/tests/openstack/neutron/test_neutron_net.py b/heat/tests/openstack/neutron/test_neutron_net.py
index 63a68c582..f45479806 100644
--- a/heat/tests/openstack/neutron/test_neutron_net.py
+++ b/heat/tests/openstack/neutron/test_neutron_net.py
@@ -40,6 +40,8 @@ resources:
- 28c25a04-3f73-45a7-a2b4-59e183943ddc
port_security_enabled: False
dns_domain: openstack.org.
+ availability_zone_hints:
+ - az1
value_specs: {'mtu': 1500}
tags:
- tag1
@@ -186,6 +188,7 @@ class NeutronNetTest(common.HeatTestCase):
'dns_domain': u'openstack.org.',
'shared': True,
'port_security_enabled': False,
+ 'availability_zone_hints': ['az1'],
'mtu': 1500}
}
)
diff --git a/heat/tests/openstack/neutron/test_neutron_provider_net.py b/heat/tests/openstack/neutron/test_neutron_provider_net.py
index a528c4d4d..9909f160e 100644
--- a/heat/tests/openstack/neutron/test_neutron_provider_net.py
+++ b/heat/tests/openstack/neutron/test_neutron_provider_net.py
@@ -40,6 +40,8 @@ resources:
segmentation_id: 101
router_external: False
shared: true
+ availability_zone_hints:
+ - az1
tags:
- tag1
- tag2
@@ -128,7 +130,8 @@ class NeutronProviderNetTest(common.HeatTestCase):
'provider:physical_network': 'physnet_1',
'provider:segmentation_id': '101',
'router:external': False,
- 'shared': True
+ 'shared': True,
+ 'availability_zone_hints': ['az1'],
}
})
self.mockclient.replace_tag.assert_called_with(
@@ -180,7 +183,8 @@ class NeutronProviderNetTest(common.HeatTestCase):
'provider:physical_network': 'physnet_1',
'provider:segmentation_id': '101',
'router:external': False,
- 'shared': True}
+ 'shared': True,
+ 'availability_zone_hints': ['az1']}
})
self.mockclient.replace_tag.assert_called_with(
resource_type,
@@ -243,6 +247,7 @@ class NeutronProviderNetTest(common.HeatTestCase):
'port_security_enabled': True,
'segmentation_id': None,
'router_external': False,
+ 'availability_zone_hints': [],
'tags': ['tag1', 'tag2'],
}
diff --git a/heat/tests/openstack/neutron/test_neutron_router.py b/heat/tests/openstack/neutron/test_neutron_router.py
index 442668a2b..6c489301b 100644
--- a/heat/tests/openstack/neutron/test_neutron_router.py
+++ b/heat/tests/openstack/neutron/test_neutron_router.py
@@ -36,6 +36,8 @@ resources:
properties:
l3_agent_ids:
- 792ff887-6c85-4a56-b518-23f24fa65581
+ availability_zone_hints:
+ - az1
router_interface:
type: OS::Neutron::RouterInterface
@@ -262,6 +264,7 @@ class NeutronRouterTest(common.HeatTestCase):
create_body = {
'router': {
'name': utils.PhysName(stack.name, 'router'),
+ 'availability_zone_hints': ['az1'],
'admin_state_up': True}}
router_base_info = {
'router': {
diff --git a/heat/tests/test_common_env_util.py b/heat/tests/test_common_env_util.py
index dff4c9c3d..fca3a9b34 100644
--- a/heat/tests/test_common_env_util.py
+++ b/heat/tests/test_common_env_util.py
@@ -202,7 +202,13 @@ class TestMergeEnvironments(common.HeatTestCase):
'lst_value1': "merge",
'json_value1': "deep_merge"}
+ env3_merge_strategies = {
+ 'default': "overwrite",
+ 'lst_value1': "deep_merge",
+ 'json_value1': "merge"}
+
self.env_2['parameter_merge_strategies'] = merge_strategies
+ self.env_3['parameter_merge_strategies'] = env3_merge_strategies
files = {'env_1': json.dumps(self.env_1),
'env_2': json.dumps(self.env_2),
@@ -221,7 +227,12 @@ class TestMergeEnvironments(common.HeatTestCase):
'default': "overwrite",
'lst_value2': "merge"}
+ env4_merge_strategies = {
+ 'default': "overwrite",
+ 'lst_value2': "overwrite"}
+
self.env_2['parameter_merge_strategies'] = merge_strategies
+ self.env_4['parameter_merge_strategies'] = env4_merge_strategies
files = {'env_1': json.dumps(self.env_1),
'env_2': json.dumps(self.env_2),
diff --git a/heat/tests/test_common_pluginutils.py b/heat/tests/test_common_pluginutils.py
new file mode 100644
index 000000000..7a6264543
--- /dev/null
+++ b/heat/tests/test_common_pluginutils.py
@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import importlib.metadata as importlib_metadata
+from unittest import mock
+
+from heat.common import pluginutils
+from heat.tests import common
+
+
+class TestPluginUtil(common.HeatTestCase):
+
+ def test_log_fail_msg(self):
+ ep = importlib_metadata.EntryPoint(
+ name=None, group=None,
+ value='package.module:attr [extra1, extra2]')
+
+ exc = Exception('Something went wrong')
+ pluginutils.log_fail_msg(mock.Mock(), ep, exc)
+ self.assertIn("Something went wrong", self.LOG.output)
diff --git a/heat_integrationtests/cleanup_test_env.sh b/heat_integrationtests/cleanup_test_env.sh
index 12791c9fd..8cc5fb1ce 100755
--- a/heat_integrationtests/cleanup_test_env.sh
+++ b/heat_integrationtests/cleanup_test_env.sh
@@ -30,4 +30,4 @@ openstack flavor delete m1.heat_int
openstack flavor delete m1.heat_micro
# delete the image created
-openstack image delete Fedora-Cloud-Base-33-1.2.x86_64
+openstack image delete Fedora-Cloud-Base-36-1.5.x86_64
diff --git a/heat_integrationtests/prepare_test_env.sh b/heat_integrationtests/prepare_test_env.sh
index 45b86e493..d4e440f73 100755
--- a/heat_integrationtests/prepare_test_env.sh
+++ b/heat_integrationtests/prepare_test_env.sh
@@ -46,7 +46,7 @@ function _config_iniset {
iniset $conf_file heat_plugin instance_type m1.heat_int
iniset $conf_file heat_plugin minimal_instance_type m1.heat_micro
- iniset $conf_file heat_plugin image_ref Fedora-Cloud-Base-33-1.2.x86_64
+ iniset $conf_file heat_plugin image_ref Fedora-Cloud-Base-36-1.5.x86_64
iniset $conf_file heat_plugin minimal_image_ref $default_image_name
iniset $conf_file heat_plugin hidden_stack_tag hidden
diff --git a/lower-constraints.txt b/lower-constraints.txt
deleted file mode 100644
index fae3b3a64..000000000
--- a/lower-constraints.txt
+++ /dev/null
@@ -1,161 +0,0 @@
-alembic==0.9.8
-amqp==2.6.0
-aodhclient==0.9.0
-appdirs==1.4.3
-asn1crypto==0.24.0
-Babel==2.3.4
-bandit==1.1.0
-bcrypt==3.1.4
-cachetools==2.0.1
-certifi==2018.1.18
-cffi==1.14.0
-chardet==3.0.4
-cliff==2.11.0
-cmd2==0.8.1
-contextlib2==0.5.5
-coverage==4.0
-croniter==0.3.4
-cryptography==2.5
-ddt==1.4.1
-debtcollector==1.19.0
-decorator==4.3.0
-deprecation==2.0
-doc8==0.8.1
-docker-pycreds==0.2.2
-docker==3.1.1
-docutils==0.13.1
-dogpile.cache==0.6.5
-enum-compat==0.0.2
-eventlet==0.18.2
-extras==1.0.0
-fasteners==0.14.1
-fixtures==3.0.0
-flake8==3.7.0
-future==0.16.0
-futurist==1.6.0
-gitdb2==2.0.3
-GitPython==2.1.8
-greenlet==0.4.17
-idna==2.6
-iso8601==0.1.12
-Jinja2==2.10
-jmespath==0.9.3
-jsonpatch==1.21
-jsonpointer==2.0
-jsonschema==2.6.0
-keystoneauth1==3.18.0
-keystonemiddleware==5.1.0
-kombu==5.0.1
-linecache2==1.0.0
-lxml==4.5.0
-Mako==1.0.7
-MarkupSafe==1.1.1
-mccabe==0.6.0
-mock==3.0.3
-monotonic==1.4
-mox3==0.28.0
-msgpack==0.5.6
-msgpack-python==0.5.6
-munch==2.2.0
-netaddr==0.7.18
-netifaces==0.10.6
-neutron-lib==1.14.0
-openstacksdk==0.28.0
-os-client-config==1.29.0
-os-service-types==1.2.0
-osc-lib==1.10.0
-oslo.cache==1.26.0
-oslo.concurrency==3.26.0
-oslo.config==6.8.0
-oslo.context==2.22.0
-oslo.db==6.0.0
-oslo.i18n==3.20.0
-oslo.log==4.3.0
-oslo.messaging==5.29.0
-oslo.middleware==3.31.0
-oslo.policy==3.7.0
-oslo.reports==1.18.0
-oslo.serialization==2.25.0
-oslo.service==1.24.0
-oslo.upgradecheck==1.3.0
-oslo.utils==4.5.0
-oslo.versionedobjects==1.31.2
-oslotest==3.2.0
-osprofiler==1.4.0
-packaging==20.4
-paramiko==2.7.1
-Paste==2.0.3
-PasteDeploy==1.5.0
-pbr==3.1.1
-pika-pool==0.1.3
-pika==0.10.0
-ply==3.11
-prettytable==0.7.2
-psutil==5.4.3
-pyasn1==0.4.2
-pycadf==2.7.0
-pycparser==2.18
-Pygments==2.2.0
-pyinotify==0.9.6
-PyMySQL==0.8.0
-PyNaCl==1.2.1
-pyOpenSSL==17.5.0
-pyparsing==2.2.0
-pyperclip==1.6.0
-python-barbicanclient==4.5.2
-python-blazarclient===1.0.1
-python-cinderclient==3.3.0
-python-dateutil==2.7.0
-python-designateclient==2.7.0
-python-editor==1.0.3
-python-glanceclient==2.8.0
-python-heatclient==1.10.0
-python-ironicclient==2.8.0
-python-keystoneclient==3.8.0
-python-magnumclient==2.3.0
-python-manilaclient==1.16.0
-python-mimeparse==1.6.0
-python-mistralclient==3.1.0
-python-monascaclient==1.12.0
-python-neutronclient==6.14.0
-python-novaclient==9.1.0
-python-octaviaclient==1.8.0
-python-openstackclient==3.12.0
-python-saharaclient==1.4.0
-python-subunit==1.2.0
-python-swiftclient==3.2.0
-python-troveclient==2.2.0
-python-vitrageclient==2.7.0
-python-zaqarclient==1.3.0
-python-zunclient==3.4.0
-pytz==2013.6
-PyYAML==5.1
-repoze.lru==0.7
-requests==2.23.0
-requestsexceptions==1.4.0
-rfc3986==1.2.0
-Routes==2.3.1
-simplejson==3.13.2
-smmap2==2.0.3
-sqlalchemy-migrate==0.13.0
-SQLAlchemy==1.0.10
-sqlparse==0.2.4
-statsd==3.2.2
-stestr==2.0.0
-stevedore==3.1.0
-tempest==17.1.0
-Tempita==0.5.2
-tenacity==6.1.0
-testresources==2.0.0
-testscenarios==0.4
-testtools==2.2.0
-traceback2==1.4.0
-unittest2==1.1.0
-urllib3==1.22
-vine==1.1.4
-voluptuous==0.11.1
-warlock==1.2.0
-WebOb==1.7.1
-websocket-client==0.47.0
-wrapt==1.10.11
-yaql==1.1.3
diff --git a/releasenotes/notes/availability_zone_hints_Neutron_network_router-d01df1463193d9e6.yaml b/releasenotes/notes/availability_zone_hints_Neutron_network_router-d01df1463193d9e6.yaml
new file mode 100644
index 000000000..83ee5628f
--- /dev/null
+++ b/releasenotes/notes/availability_zone_hints_Neutron_network_router-d01df1463193d9e6.yaml
@@ -0,0 +1,5 @@
+---
+features:
+ - |
+ Adds the 'availability_zone_hints' property for the OS::Neutron::Router,
+ OS::Neutron::Net and OS::Neutron::ProviderNet resources.
diff --git a/releasenotes/notes/drop-python-3-6-and-3-7-69dcd178c443e177.yaml b/releasenotes/notes/drop-python-3-6-and-3-7-69dcd178c443e177.yaml
new file mode 100644
index 000000000..3d5e4e3d3
--- /dev/null
+++ b/releasenotes/notes/drop-python-3-6-and-3-7-69dcd178c443e177.yaml
@@ -0,0 +1,5 @@
+---
+upgrade:
+ - |
+ Python 3.6 & 3.7 support has been dropped. The minimum version of Python now
+ supported is Python 3.8. \ No newline at end of file
diff --git a/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po b/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po
index 68b70f458..279a46cfd 100644
--- a/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po
+++ b/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po
@@ -3,15 +3,16 @@
# Andi Chandler <andi@gowling.com>, 2019. #zanata
# Andi Chandler <andi@gowling.com>, 2020. #zanata
# Andi Chandler <andi@gowling.com>, 2021. #zanata
+# Andi Chandler <andi@gowling.com>, 2022. #zanata
msgid ""
msgstr ""
"Project-Id-Version: openstack-heat\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2021-11-01 17:53+0000\n"
+"POT-Creation-Date: 2022-05-25 07:40+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"PO-Revision-Date: 2021-09-18 07:40+0000\n"
+"PO-Revision-Date: 2022-05-25 09:20+0000\n"
"Last-Translator: Andi Chandler <andi@gowling.com>\n"
"Language-Team: English (United Kingdom)\n"
"Language: en_GB\n"
@@ -58,6 +59,9 @@ msgstr "13.0.0"
msgid "13.0.1"
msgstr "13.0.1"
+msgid "13.1.0-19"
+msgstr "13.1.0-19"
+
msgid "14.0.0"
msgstr "14.0.0"
@@ -67,12 +71,21 @@ msgstr "14.2.0"
msgid "15.0.0"
msgstr "15.0.0"
-msgid "15.0.0-21"
-msgstr "15.0.0-21"
+msgid "15.1.0"
+msgstr "15.1.0"
msgid "16.0.0"
msgstr "16.0.0"
+msgid "17.0.0"
+msgstr "17.0.0"
+
+msgid "18.0.0"
+msgstr "18.0.0"
+
+msgid "18.0.0-4"
+msgstr "18.0.0-4"
+
msgid "5.0.1"
msgstr "5.0.1"
@@ -739,6 +752,15 @@ msgstr ""
"openstack.org/heat/pike/`."
msgid ""
+"Allow Heat resources to accept more than one required_service_extension. For "
+"cases where a resource required multiple service extensions. A developer can "
+"now provide a list of those extensions."
+msgstr ""
+"Allow Heat resources to accept more than one required_service_extension. For "
+"cases where a resource required multiple service extensions. A developer can "
+"now provide a list of those extensions."
+
+msgid ""
"Allow to configure Heat service to forbid creation of stacks containing "
"Volume resources with ``deletion_policy`` set to ``Snapshot`` when there is "
"no Cinder backup service available."
@@ -1391,6 +1413,13 @@ msgstr ""
"which allows users to create a network port without any fixed IPs."
msgid ""
+"Now the ``[DEFAULT] shared_services_types`` option includes ``volumev3`` "
+"service type by default."
+msgstr ""
+"Now the ``[DEFAULT] shared_services_types`` option includes ``volumev3`` "
+"service type by default."
+
+msgid ""
"OS::Aodh::CompositeAlarm resource plugin is added to manage Aodh composite "
"alarm, aim to replace OS::Aodh::CombinationAlarm which has been deprecated "
"in Newton release."
@@ -1847,6 +1876,9 @@ msgstr ""
msgid "Support external resource reference in template."
msgstr "Support external resource reference in template."
+msgid "Support for Block Storage API v2 has been removed."
+msgstr "Support for Block Storage API v2 has been removed."
+
msgid ""
"Support shared services in multi region mode. The services are declared in a "
"list in config. shared_services_types=image, volume, volumev2."
@@ -2395,6 +2427,9 @@ msgstr ""
msgid "Xena Series Release Notes"
msgstr "Xena Series Release Notes"
+msgid "Yoga Series Release Notes"
+msgstr "Yoga Series Release Notes"
+
msgid ""
"``OS::Neutron::Port`` resources will now be replaced when the "
"``mac_address`` property is modified. Neutron is unable to update the MAC "
diff --git a/requirements.txt b/requirements.txt
index f263179a1..a6a85292a 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,7 @@
+# Requirements lower bounds listed here are our best effort to keep them up to
+# date but we do not test them so no guarantee of having them all correct. If
+# you find any incorrect lower bounds, let us know or propose a fix.
+
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
diff --git a/roles/run-heat-tests/defaults/main.yaml b/roles/run-heat-tests/defaults/main.yaml
index b601d49d9..22ce4a490 100644
--- a/roles/run-heat-tests/defaults/main.yaml
+++ b/roles/run-heat-tests/defaults/main.yaml
@@ -1,2 +1,5 @@
devstack_base_dir: /opt/stack
tempest_test_timeout: ''
+tempest_tox_environment: {}
+heat_tempest_plugin: /opt/stack/heat-tempest-plugin
+constraints_file: /opt/stack/requirements/upper-constraints.txt
diff --git a/roles/run-heat-tests/tasks/main.yaml b/roles/run-heat-tests/tasks/main.yaml
index 75122f2a1..4af1d0e03 100644
--- a/roles/run-heat-tests/tasks/main.yaml
+++ b/roles/run-heat-tests/tasks/main.yaml
@@ -1,3 +1,23 @@
+- name: Set OS_TEST_TIMEOUT if requested
+ set_fact:
+ tempest_tox_environment: "{{ tempest_tox_environment | combine({'OS_TEST_TIMEOUT': tempest_test_timeout}) }}"
+ when: tempest_test_timeout != ''
+
+- name: Set TOX_CONSTRAINTS_FILE
+ set_fact:
+ tempest_tox_environment: "{{ tempest_tox_environment | combine({'UPPER_CONSTRAINTS_FILE': constraints_file}) | combine({'TOX_CONSTRAINTS_FILE': constraints_file}) }}"
+
+- name: Allow git to read plugin directories
+ become: true
+ command: git config --system --add safe.directory {{heat_tempest_plugin}}
+
+- name: Install plugins
+ command: tox -evenv-tempest -- pip install -c{{constraints_file}} {{heat_tempest_plugin}}
+ become: true
+ args:
+ chdir: "{{devstack_base_dir}}/tempest"
+ environment: "{{ tempest_tox_environment }}"
+
- name: Run heat tests
command: tox -evenv-tempest -- stestr --test-path={{devstack_base_dir}}/heat/heat_integrationtests \
--top-dir={{devstack_base_dir}}/heat \
@@ -5,5 +25,4 @@
args:
chdir: "{{devstack_base_dir}}/tempest"
become: true
- become_user: tempest
- environment: '{{ {"OS_TEST_TIMEOUT": tempest_test_timeout} if tempest_test_timeout else {} }}'
+ environment: "{{ tempest_tox_environment }}"
diff --git a/setup.cfg b/setup.cfg
index 9a9ae5af5..6f3eba262 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -6,7 +6,7 @@ description-file =
author = OpenStack
author-email = openstack-discuss@lists.openstack.org
home-page = https://docs.openstack.org/heat/latest/
-python-requires = >=3.6
+python-requires = >=3.8
classifier =
Environment :: OpenStack
Intended Audience :: Information Technology
@@ -16,8 +16,6 @@ classifier =
Programming Language :: Python
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
diff --git a/setup.py b/setup.py
index f63cc23c5..dd26ed49b 100644
--- a/setup.py
+++ b/setup.py
@@ -18,4 +18,5 @@ import setuptools
setuptools.setup(
setup_requires=['pbr>=2.0.0'],
+ py_modules=[],
pbr=True)
diff --git a/tox.ini b/tox.ini
index 88945404a..10fc10606 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
[tox]
-envlist = py36,py37,py38,py39,pep8
+envlist = py38,py39,pep8
ignore_basepython_conflict = True
minversion = 3.18.0
skipsdist = True
@@ -153,10 +153,3 @@ commands =
deps = bindep
commands = bindep test
usedevelop = False
-
-[testenv:lower-constraints]
-install_command = pip install {opts} {packages}
-deps =
- -c{toxinidir}/lower-constraints.txt
- -r{toxinidir}/test-requirements.txt
- -r{toxinidir}/requirements.txt