heat/heat/tests/neutron/test_neutron_loadbalancer.py

1142 lines
44 KiB
Python

#
# 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 copy
import mox
from neutronclient.common import exceptions
from neutronclient.neutron import v2_0 as neutronV20
from neutronclient.v2_0 import client as neutronclient
from oslo_config import cfg
import six
from heat.common import exception
from heat.common.i18n import _
from heat.common import template_format
from heat.engine.clients.os import nova
from heat.engine.resources.openstack.neutron import loadbalancer
from heat.engine import scheduler
from heat.tests import common
from heat.tests.nova import fakes as fakes_nova
from heat.tests import utils
health_monitor_template = '''
heat_template_version: 2015-04-30
description: Template to test load balancer resources
resources:
monitor:
type: OS::Neutron::HealthMonitor
properties:
type: HTTP
delay: 3
max_retries: 5
timeout: 10
'''
pool_template_with_vip_subnet = '''
heat_template_version: 2015-04-30
description: Template to test load balancer resources
resources:
pool:
type: OS::Neutron::Pool
properties:
protocol: HTTP
subnet: sub123
lb_method: ROUND_ROBIN
vip:
protocol_port: 80
subnet: sub9999
'''
pool_template_with_provider = '''
heat_template_version: 2015-04-30
description: Template to test load balancer resources
resources:
pool:
type: OS::Neutron::Pool
properties:
protocol: HTTP
subnet: sub123
lb_method: ROUND_ROBIN
provider: test_prov
vip:
protocol_port: 80
'''
pool_template = '''
heat_template_version: 2015-04-30
description: Template to test load balancer resources
resources:
pool:
type: OS::Neutron::Pool
properties:
protocol: HTTP
subnet: sub123
lb_method: ROUND_ROBIN
vip:
protocol_port: 80
'''
pool_template_deprecated = pool_template.replace('subnet', 'subnet_id')
member_template = '''
heat_template_version: 2015-04-30
description: Template to test load balancer member
resources:
member:
type: OS::Neutron::PoolMember
properties:
protocol_port: 8080
pool_id: pool123
address: 1.2.3.4
'''
lb_template = '''
heat_template_version: 2015-04-30
description: Template to test load balancer resources
resources:
lb:
type: OS::Neutron::LoadBalancer
properties:
protocol_port: 8080
pool_id: pool123
members: [1234]
'''
pool_with_session_persistence_template = '''
heat_template_version: 2015-04-30
description: Template to test load balancer resources
resources:
pool:
type: OS::Neutron::Pool
properties:
protocol: HTTP
subnet: sub123
lb_method: ROUND_ROBIN
vip:
protocol_port: 80
session_persistence:
type: APP_COOKIE
cookie_name: cookie
'''
pool_with_health_monitors_template = '''
heat_template_version: 2015-04-30
description: Template to test load balancer resources
resources:
monitor1:
type: OS::Neutron::HealthMonitor
properties:
type: HTTP
delay: 3
max_retries: 5
timeout: 10
monitor2:
type: OS::Neutron::HealthMonitor
properties:
type: HTTP
delay: 3
max_retries: 5
timeout: 10
pool:
type: OS::Neutron::Pool
properties:
protocol: HTTP
subnet_id: sub123
lb_method: ROUND_ROBIN
vip:
protocol_port: 80
monitors:
- {get_resource: monitor1}
- {get_resource: monitor2}
'''
class HealthMonitorTest(common.HeatTestCase):
def setUp(self):
super(HealthMonitorTest, self).setUp()
self.m.StubOutWithMock(neutronclient.Client, 'create_health_monitor')
self.m.StubOutWithMock(neutronclient.Client, 'delete_health_monitor')
self.m.StubOutWithMock(neutronclient.Client, 'show_health_monitor')
self.m.StubOutWithMock(neutronclient.Client, 'update_health_monitor')
def create_health_monitor(self):
neutronclient.Client.create_health_monitor({
'health_monitor': {
'delay': 3, 'max_retries': 5, 'type': u'HTTP',
'timeout': 10, 'admin_state_up': True}}
).AndReturn({'health_monitor': {'id': '5678'}})
snippet = template_format.parse(health_monitor_template)
self.stack = utils.parse_stack(snippet)
resource_defns = self.stack.t.resource_definitions(self.stack)
return loadbalancer.HealthMonitor(
'monitor', resource_defns['monitor'], self.stack)
def test_create(self):
rsrc = self.create_health_monitor()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
def test_create_failed(self):
neutronclient.Client.create_health_monitor({
'health_monitor': {
'delay': 3, 'max_retries': 5, 'type': u'HTTP',
'timeout': 10, 'admin_state_up': True}}
).AndRaise(exceptions.NeutronClientException())
self.m.ReplayAll()
snippet = template_format.parse(health_monitor_template)
self.stack = utils.parse_stack(snippet)
resource_defns = self.stack.t.resource_definitions(self.stack)
rsrc = loadbalancer.HealthMonitor(
'monitor', resource_defns['monitor'], self.stack)
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.create))
self.assertEqual(
'NeutronClientException: resources.monitor: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
def test_delete(self):
neutronclient.Client.delete_health_monitor('5678')
neutronclient.Client.show_health_monitor('5678').AndRaise(
exceptions.NeutronClientException(status_code=404))
rsrc = self.create_health_monitor()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
scheduler.TaskRunner(rsrc.delete)()
self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
def test_delete_already_gone(self):
neutronclient.Client.delete_health_monitor('5678').AndRaise(
exceptions.NeutronClientException(status_code=404))
rsrc = self.create_health_monitor()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
scheduler.TaskRunner(rsrc.delete)()
self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
def test_delete_failed(self):
neutronclient.Client.delete_health_monitor('5678').AndRaise(
exceptions.NeutronClientException(status_code=400))
rsrc = self.create_health_monitor()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.delete))
self.assertEqual(
'NeutronClientException: resources.monitor: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
def test_attribute(self):
rsrc = self.create_health_monitor()
neutronclient.Client.show_health_monitor('5678').MultipleTimes(
).AndReturn(
{'health_monitor': {'admin_state_up': True, 'delay': 3}})
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
self.assertIs(True, rsrc.FnGetAtt('admin_state_up'))
self.assertEqual(3, rsrc.FnGetAtt('delay'))
self.m.VerifyAll()
def test_attribute_failed(self):
rsrc = self.create_health_monitor()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
error = self.assertRaises(exception.InvalidTemplateAttribute,
rsrc.FnGetAtt, 'subnet_id')
self.assertEqual(
'The Referenced Attribute (monitor subnet_id) is incorrect.',
six.text_type(error))
self.m.VerifyAll()
def test_update(self):
rsrc = self.create_health_monitor()
neutronclient.Client.update_health_monitor(
'5678', {'health_monitor': {'delay': 10}})
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
update_template = copy.deepcopy(rsrc.t)
update_template['Properties']['delay'] = 10
scheduler.TaskRunner(rsrc.update, update_template)()
self.m.VerifyAll()
class PoolTest(common.HeatTestCase):
def setUp(self):
super(PoolTest, self).setUp()
self.m.StubOutWithMock(neutronclient.Client, 'create_pool')
self.m.StubOutWithMock(neutronclient.Client, 'delete_pool')
self.m.StubOutWithMock(neutronclient.Client, 'show_pool')
self.m.StubOutWithMock(neutronclient.Client, 'update_pool')
self.m.StubOutWithMock(neutronclient.Client,
'associate_health_monitor')
self.m.StubOutWithMock(neutronclient.Client,
'disassociate_health_monitor')
self.m.StubOutWithMock(neutronclient.Client, 'create_vip')
self.m.StubOutWithMock(neutronV20, 'find_resourceid_by_name_or_id')
self.m.StubOutWithMock(neutronclient.Client, 'delete_vip')
self.m.StubOutWithMock(neutronclient.Client, 'show_vip')
def create_pool(self, resolve_neutron=True, with_vip_subnet=False):
neutronclient.Client.create_pool({
'pool': {
'subnet_id': 'sub123', 'protocol': u'HTTP',
'name': utils.PhysName('test_stack', 'pool'),
'lb_method': 'ROUND_ROBIN', 'admin_state_up': True}}
).AndReturn({'pool': {'id': '5678'}})
neutronclient.Client.show_pool('5678').AndReturn(
{'pool': {'status': 'ACTIVE'}})
neutronclient.Client.show_vip('xyz').AndReturn(
{'vip': {'status': 'ACTIVE'}})
stvipvsn = {
'vip': {
'protocol': u'HTTP', 'name': 'pool.vip',
'admin_state_up': True, 'subnet_id': u'sub9999',
'pool_id': '5678', 'protocol_port': 80}
}
stvippsn = copy.deepcopy(stvipvsn)
stvippsn['vip']['subnet_id'] = 'sub123'
self.stub_SubnetConstraint_validate()
if resolve_neutron and with_vip_subnet:
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'subnet',
'sub123'
).AndReturn('sub123')
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'subnet',
'sub9999'
).AndReturn('sub9999')
snippet = template_format.parse(pool_template_with_vip_subnet)
neutronclient.Client.create_vip(stvipvsn
).AndReturn({'vip': {'id': 'xyz'}})
elif resolve_neutron and not with_vip_subnet:
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'subnet',
'sub123'
).AndReturn('sub123')
snippet = template_format.parse(pool_template)
neutronclient.Client.create_vip(stvippsn
).AndReturn({'vip': {'id': 'xyz'}})
else:
snippet = template_format.parse(pool_template_deprecated)
neutronclient.Client.create_vip(stvippsn
).AndReturn({'vip': {'id': 'xyz'}})
self.stack = utils.parse_stack(snippet)
resource_defns = self.stack.t.resource_definitions(self.stack)
return loadbalancer.Pool(
'pool', resource_defns['pool'], self.stack)
def test_create(self):
self._test_create()
def test_create_deprecated(self):
self._test_create(resolve_neutron=False, with_vip_subnet=False)
def _test_create(self, resolve_neutron=True, with_vip_subnet=False):
rsrc = self.create_pool(resolve_neutron, with_vip_subnet)
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
def test_create_with_vip_subnet(self):
rsrc = self.create_pool(with_vip_subnet=True)
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
def test_create_pending(self):
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'subnet',
'sub123'
).MultipleTimes().AndReturn('sub123')
neutronclient.Client.create_pool({
'pool': {
'subnet_id': 'sub123', 'protocol': u'HTTP',
'name': utils.PhysName('test_stack', 'pool'),
'lb_method': 'ROUND_ROBIN', 'admin_state_up': True}}
).AndReturn({'pool': {'id': '5678'}})
neutronclient.Client.create_vip({
'vip': {
'protocol': u'HTTP', 'name': 'pool.vip',
'admin_state_up': True, 'subnet_id': u'sub123',
'pool_id': '5678', 'protocol_port': 80}}
).AndReturn({'vip': {'id': 'xyz'}})
neutronclient.Client.show_pool('5678').AndReturn(
{'pool': {'status': 'PENDING_CREATE'}})
neutronclient.Client.show_pool('5678').MultipleTimes().AndReturn(
{'pool': {'status': 'ACTIVE'}})
neutronclient.Client.show_vip('xyz').AndReturn(
{'vip': {'status': 'PENDING_CREATE'}})
neutronclient.Client.show_vip('xyz').AndReturn(
{'vip': {'status': 'ACTIVE'}})
snippet = template_format.parse(pool_template)
self.stack = utils.parse_stack(snippet)
resource_defns = self.stack.t.resource_definitions(self.stack)
rsrc = loadbalancer.Pool(
'pool', resource_defns['pool'], self.stack)
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
def test_create_failed_error_status(self):
cfg.CONF.set_override('action_retry_limit', 0)
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'subnet',
'sub123'
).MultipleTimes().AndReturn('sub123')
neutronclient.Client.create_pool({
'pool': {
'subnet_id': 'sub123', 'protocol': u'HTTP',
'name': utils.PhysName('test_stack', 'pool'),
'lb_method': 'ROUND_ROBIN', 'admin_state_up': True}}
).AndReturn({'pool': {'id': '5678'}})
neutronclient.Client.create_vip({
'vip': {
'protocol': u'HTTP', 'name': 'pool.vip',
'admin_state_up': True, 'subnet_id': u'sub123',
'pool_id': '5678', 'protocol_port': 80}}
).AndReturn({'vip': {'id': 'xyz'}})
neutronclient.Client.show_pool('5678').AndReturn(
{'pool': {'status': 'ERROR', 'name': '5678'}})
snippet = template_format.parse(pool_template)
self.stack = utils.parse_stack(snippet)
resource_defns = self.stack.t.resource_definitions(self.stack)
rsrc = loadbalancer.Pool(
'pool', resource_defns['pool'], self.stack)
self.m.ReplayAll()
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.create))
self.assertEqual(
'ResourceInError: resources.pool: '
'Went to status ERROR due to "error in pool"',
six.text_type(error))
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
def test_create_failed_unexpected_vip_status(self):
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'subnet',
'sub123'
).MultipleTimes().AndReturn('sub123')
neutronclient.Client.create_pool({
'pool': {
'subnet_id': 'sub123', 'protocol': u'HTTP',
'name': utils.PhysName('test_stack', 'pool'),
'lb_method': 'ROUND_ROBIN', 'admin_state_up': True}}
).AndReturn({'pool': {'id': '5678'}})
neutronclient.Client.create_vip({
'vip': {
'protocol': u'HTTP', 'name': 'pool.vip',
'admin_state_up': True, 'subnet_id': u'sub123',
'pool_id': '5678', 'protocol_port': 80}}
).AndReturn({'vip': {'id': 'xyz'}})
neutronclient.Client.show_pool('5678').MultipleTimes().AndReturn(
{'pool': {'status': 'ACTIVE'}})
neutronclient.Client.show_vip('xyz').AndReturn(
{'vip': {'status': 'SOMETHING', 'name': 'xyz'}})
snippet = template_format.parse(pool_template)
self.stack = utils.parse_stack(snippet)
resource_defns = self.stack.t.resource_definitions(self.stack)
rsrc = loadbalancer.Pool(
'pool', resource_defns['pool'], self.stack)
self.m.ReplayAll()
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.create))
self.assertEqual('ResourceUnknownStatus: resources.pool: '
'Pool creation failed due to '
'vip - Unknown status SOMETHING due to "Unknown"',
six.text_type(error))
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
def test_create_failed(self):
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'subnet',
'sub123'
).MultipleTimes().AndReturn('sub123')
neutronclient.Client.create_pool({
'pool': {
'subnet_id': 'sub123', 'protocol': u'HTTP',
'name': utils.PhysName('test_stack', 'pool'),
'lb_method': 'ROUND_ROBIN', 'admin_state_up': True}}
).AndRaise(exceptions.NeutronClientException())
self.m.ReplayAll()
snippet = template_format.parse(pool_template)
self.stack = utils.parse_stack(snippet)
resource_defns = self.stack.t.resource_definitions(self.stack)
rsrc = loadbalancer.Pool(
'pool', resource_defns['pool'], self.stack)
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.create))
self.assertEqual(
'NeutronClientException: resources.pool: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
def test_create_with_session_persistence(self):
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'subnet',
'sub123'
).MultipleTimes().AndReturn('sub123')
neutronclient.Client.create_pool({
'pool': {
'subnet_id': 'sub123', 'protocol': u'HTTP',
'name': utils.PhysName('test_stack', 'pool'),
'lb_method': 'ROUND_ROBIN', 'admin_state_up': True}}
).AndReturn({'pool': {'id': '5678'}})
neutronclient.Client.create_vip({
'vip': {
'protocol': u'HTTP', 'name': 'pool.vip',
'admin_state_up': True, 'subnet_id': u'sub123',
'pool_id': '5678', 'protocol_port': 80,
'session_persistence': {
'type': 'APP_COOKIE',
'cookie_name': 'cookie'}}}
).AndReturn({'vip': {'id': 'xyz'}})
neutronclient.Client.show_pool('5678').AndReturn(
{'pool': {'status': 'ACTIVE'}})
neutronclient.Client.show_vip('xyz').AndReturn(
{'vip': {'status': 'ACTIVE'}})
snippet = template_format.parse(pool_with_session_persistence_template)
self.stack = utils.parse_stack(snippet)
resource_defns = self.stack.t.resource_definitions(self.stack)
rsrc = loadbalancer.Pool(
'pool', resource_defns['pool'], self.stack)
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
def test_create_pool_with_provider(self):
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'subnet',
'sub123'
).MultipleTimes().AndReturn('sub123')
neutronclient.Client.create_pool({
'pool': {
'subnet_id': 'sub123', 'protocol': u'HTTP',
'name': utils.PhysName('test_stack', 'pool'),
'lb_method': 'ROUND_ROBIN', 'admin_state_up': True,
'provider': 'test_prov'}}
).AndReturn({'pool': {'id': '5678'}})
neutronclient.Client.create_vip({
'vip': {
'protocol': u'HTTP', 'name': 'pool.vip',
'admin_state_up': True, 'subnet_id': u'sub123',
'pool_id': '5678', 'protocol_port': 80}}
).AndReturn({'vip': {'id': 'xyz'}})
neutronclient.Client.show_pool('5678').MultipleTimes().AndReturn(
{'pool': {'status': 'ACTIVE', 'provider': 'test_prov'}})
neutronclient.Client.show_vip('xyz').AndReturn(
{'vip': {'status': 'ACTIVE'}})
snippet = template_format.parse(pool_template_with_provider)
self.stack = utils.parse_stack(snippet)
resource_defns = self.stack.t.resource_definitions(self.stack)
rsrc = loadbalancer.Pool(
'pool', resource_defns['pool'], self.stack)
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
self.assertEqual("test_prov", rsrc.FnGetAtt("provider"))
self.m.VerifyAll()
def test_failing_validation_with_session_persistence(self):
msg = _('Property cookie_name is required, when '
'session_persistence type is set to APP_COOKIE.')
snippet = template_format.parse(pool_with_session_persistence_template)
pool = snippet['resources']['pool']
persistence = pool['properties']['vip']['session_persistence']
# When persistence type is set to APP_COOKIE, cookie_name is required
persistence['type'] = 'APP_COOKIE'
persistence['cookie_name'] = None
self.stack = utils.parse_stack(snippet)
resource_defns = self.stack.t.resource_definitions(self.stack)
resource = loadbalancer.Pool('pool', resource_defns['pool'],
self.stack)
error = self.assertRaises(exception.StackValidationFailed,
resource.validate)
self.assertEqual(msg, six.text_type(error))
def test_validation_not_failing_without_session_persistence(self):
snippet = template_format.parse(pool_template)
self.stack = utils.parse_stack(snippet)
resource_defns = self.stack.t.resource_definitions(self.stack)
resource = loadbalancer.Pool('pool', resource_defns['pool'],
self.stack)
self.stub_SubnetConstraint_validate()
self.m.ReplayAll()
self.assertIsNone(resource.validate())
self.m.VerifyAll()
def test_properties_are_prepared_for_session_persistence(self):
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'subnet',
'sub123'
).MultipleTimes().AndReturn('sub123')
neutronclient.Client.create_pool({
'pool': {
'subnet_id': 'sub123', 'protocol': u'HTTP',
'name': utils.PhysName('test_stack', 'pool'),
'lb_method': 'ROUND_ROBIN', 'admin_state_up': True}}
).AndReturn({'pool': {'id': '5678'}})
neutronclient.Client.create_vip({
'vip': {
'protocol': u'HTTP', 'name': 'pool.vip',
'admin_state_up': True, 'subnet_id': u'sub123',
'pool_id': '5678', 'protocol_port': 80,
'session_persistence': {'type': 'HTTP_COOKIE'}}}
).AndReturn({'vip': {'id': 'xyz'}})
neutronclient.Client.show_pool('5678').AndReturn(
{'pool': {'status': 'ACTIVE'}})
neutronclient.Client.show_vip('xyz').AndReturn(
{'vip': {'status': 'ACTIVE'}})
snippet = template_format.parse(pool_with_session_persistence_template)
pool = snippet['resources']['pool']
persistence = pool['properties']['vip']['session_persistence']
# change persistence type to HTTP_COOKIE that not require cookie_name
persistence['type'] = 'HTTP_COOKIE'
del persistence['cookie_name']
self.stack = utils.parse_stack(snippet)
resource_defns = self.stack.t.resource_definitions(self.stack)
resource = loadbalancer.Pool('pool', resource_defns['pool'],
self.stack)
# assert that properties contain cookie_name property with None value
persistence = resource.properties['vip']['session_persistence']
self.assertIn('cookie_name', persistence)
self.assertIsNone(persistence['cookie_name'])
self.m.ReplayAll()
scheduler.TaskRunner(resource.create)()
self.assertEqual((resource.CREATE, resource.COMPLETE), resource.state)
self.m.VerifyAll()
def test_delete(self):
rsrc = self.create_pool()
neutronclient.Client.delete_vip('xyz')
neutronclient.Client.show_vip('xyz').AndRaise(
exceptions.NeutronClientException(status_code=404))
neutronclient.Client.delete_pool('5678')
neutronclient.Client.show_pool('5678').AndRaise(
exceptions.NeutronClientException(status_code=404))
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
scheduler.TaskRunner(rsrc.delete)()
self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
def test_delete_already_gone(self):
neutronclient.Client.delete_vip('xyz').AndRaise(
exceptions.NeutronClientException(status_code=404))
neutronclient.Client.delete_pool('5678').AndRaise(
exceptions.NeutronClientException(status_code=404))
rsrc = self.create_pool()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
scheduler.TaskRunner(rsrc.delete)()
self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
def test_delete_vip_failed(self):
neutronclient.Client.delete_vip('xyz').AndRaise(
exceptions.NeutronClientException(status_code=400))
rsrc = self.create_pool()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.delete))
self.assertEqual(
'NeutronClientException: resources.pool: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
def test_delete_failed(self):
neutronclient.Client.delete_vip('xyz').AndRaise(
exceptions.NeutronClientException(status_code=404))
neutronclient.Client.delete_pool('5678').AndRaise(
exceptions.NeutronClientException(status_code=400))
rsrc = self.create_pool()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.delete))
self.assertEqual(
'NeutronClientException: resources.pool: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
def test_attribute(self):
rsrc = self.create_pool()
neutronclient.Client.show_pool('5678').MultipleTimes(
).AndReturn(
{'pool': {'admin_state_up': True, 'lb_method': 'ROUND_ROBIN'}})
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
self.assertIs(True, rsrc.FnGetAtt('admin_state_up'))
self.assertEqual('ROUND_ROBIN', rsrc.FnGetAtt('lb_method'))
self.m.VerifyAll()
def test_vip_attribute(self):
rsrc = self.create_pool()
neutronclient.Client.show_vip('xyz').AndReturn(
{'vip': {'address': '10.0.0.3', 'name': 'xyz'}})
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
self.assertEqual({'address': '10.0.0.3', 'name': 'xyz'},
rsrc.FnGetAtt('vip'))
self.m.VerifyAll()
def test_attribute_failed(self):
rsrc = self.create_pool()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
error = self.assertRaises(exception.InvalidTemplateAttribute,
rsrc.FnGetAtt, 'net_id')
self.assertEqual(
'The Referenced Attribute (pool net_id) is incorrect.',
six.text_type(error))
self.m.VerifyAll()
def test_update(self):
rsrc = self.create_pool()
neutronclient.Client.update_pool(
'5678', {'pool': {'admin_state_up': False}})
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
update_template = copy.deepcopy(rsrc.t)
update_template['Properties']['admin_state_up'] = False
scheduler.TaskRunner(rsrc.update, update_template)()
self.m.VerifyAll()
def test_update_monitors(self):
neutronV20.find_resourceid_by_name_or_id(
mox.IsA(neutronclient.Client),
'subnet',
'sub123'
).MultipleTimes().AndReturn('sub123')
neutronclient.Client.create_pool({
'pool': {
'subnet_id': 'sub123', 'protocol': u'HTTP',
'name': utils.PhysName('test_stack', 'pool'),
'lb_method': 'ROUND_ROBIN', 'admin_state_up': True}}
).AndReturn({'pool': {'id': '5678'}})
neutronclient.Client.associate_health_monitor(
'5678', {'health_monitor': {'id': 'mon123'}})
neutronclient.Client.associate_health_monitor(
'5678', {'health_monitor': {'id': 'mon456'}})
neutronclient.Client.create_vip({
'vip': {
'protocol': u'HTTP', 'name': 'pool.vip',
'admin_state_up': True, 'subnet_id': u'sub123',
'pool_id': '5678', 'protocol_port': 80}}
).AndReturn({'vip': {'id': 'xyz'}})
neutronclient.Client.show_pool('5678').AndReturn(
{'pool': {'status': 'ACTIVE'}})
neutronclient.Client.show_vip('xyz').AndReturn(
{'vip': {'status': 'ACTIVE'}})
neutronclient.Client.disassociate_health_monitor(
'5678', 'mon456')
neutronclient.Client.associate_health_monitor(
'5678', {'health_monitor': {'id': 'mon789'}})
snippet = template_format.parse(pool_template)
self.stack = utils.parse_stack(snippet)
snippet['resources']['pool']['properties']['monitors'] = [
'mon123', 'mon456']
resource_defns = self.stack.t.resource_definitions(self.stack)
rsrc = loadbalancer.Pool('pool', resource_defns['pool'], self.stack)
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
update_template = copy.deepcopy(rsrc.t)
update_template['Properties']['monitors'] = ['mon123', 'mon789']
scheduler.TaskRunner(rsrc.update, update_template)()
self.m.VerifyAll()
class PoolMemberTest(common.HeatTestCase):
def setUp(self):
super(PoolMemberTest, self).setUp()
self.fc = fakes_nova.FakeClient()
self.m.StubOutWithMock(neutronclient.Client, 'create_member')
self.m.StubOutWithMock(neutronclient.Client, 'delete_member')
self.m.StubOutWithMock(neutronclient.Client, 'update_member')
self.m.StubOutWithMock(neutronclient.Client, 'show_member')
def create_member(self):
neutronclient.Client.create_member({
'member': {
'pool_id': 'pool123', 'protocol_port': 8080,
'address': '1.2.3.4', 'admin_state_up': True}}
).AndReturn({'member': {'id': 'member5678'}})
snippet = template_format.parse(member_template)
self.stack = utils.parse_stack(snippet)
resource_defns = self.stack.t.resource_definitions(self.stack)
return loadbalancer.PoolMember(
'member', resource_defns['member'], self.stack)
def test_create(self):
rsrc = self.create_member()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
self.assertEqual('member5678', rsrc.resource_id)
self.m.VerifyAll()
def test_create_optional_parameters(self):
neutronclient.Client.create_member({
'member': {
'pool_id': 'pool123', 'protocol_port': 8080,
'weight': 100, 'admin_state_up': False,
'address': '1.2.3.4'}}
).AndReturn({'member': {'id': 'member5678'}})
snippet = template_format.parse(member_template)
snippet['resources']['member']['properties']['admin_state_up'] = False
snippet['resources']['member']['properties']['weight'] = 100
self.stack = utils.parse_stack(snippet)
resource_defns = self.stack.t.resource_definitions(self.stack)
rsrc = loadbalancer.PoolMember(
'member', resource_defns['member'], self.stack)
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
self.assertEqual('member5678', rsrc.resource_id)
self.m.VerifyAll()
def test_attribute(self):
rsrc = self.create_member()
neutronclient.Client.show_member('member5678').MultipleTimes(
).AndReturn(
{'member': {'admin_state_up': True, 'weight': 5}})
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
self.assertIs(True, rsrc.FnGetAtt('admin_state_up'))
self.assertEqual(5, rsrc.FnGetAtt('weight'))
self.m.VerifyAll()
def test_update(self):
rsrc = self.create_member()
neutronclient.Client.update_member(
'member5678', {'member': {'pool_id': 'pool456'}})
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
update_template = copy.deepcopy(rsrc.t)
update_template['Properties']['pool_id'] = 'pool456'
scheduler.TaskRunner(rsrc.update, update_template)()
self.m.VerifyAll()
def test_delete(self):
rsrc = self.create_member()
neutronclient.Client.delete_member(u'member5678')
neutronclient.Client.show_member(u'member5678').AndRaise(
exceptions.NeutronClientException(status_code=404))
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
scheduler.TaskRunner(rsrc.delete)()
self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
def test_delete_missing_member(self):
rsrc = self.create_member()
neutronclient.Client.delete_member(u'member5678').AndRaise(
exceptions.NeutronClientException(status_code=404))
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
scheduler.TaskRunner(rsrc.delete)()
self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
class LoadBalancerTest(common.HeatTestCase):
def setUp(self):
super(LoadBalancerTest, self).setUp()
self.fc = fakes_nova.FakeClient()
self.m.StubOutWithMock(neutronclient.Client, 'create_member')
self.m.StubOutWithMock(neutronclient.Client, 'delete_member')
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
def create_load_balancer(self):
nova.NovaClientPlugin._create().AndReturn(self.fc)
neutronclient.Client.create_member({
'member': {
'pool_id': 'pool123', 'protocol_port': 8080,
'address': '1.2.3.4'}}
).AndReturn({'member': {'id': 'member5678'}})
snippet = template_format.parse(lb_template)
self.stack = utils.parse_stack(snippet)
resource_defns = self.stack.t.resource_definitions(self.stack)
return loadbalancer.LoadBalancer(
'lb', resource_defns['lb'], self.stack)
def test_create(self):
rsrc = self.create_load_balancer()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
def test_update(self):
rsrc = self.create_load_balancer()
neutronclient.Client.delete_member(u'member5678')
neutronclient.Client.create_member({
'member': {
'pool_id': 'pool123', 'protocol_port': 8080,
'address': '4.5.6.7'}}
).AndReturn({'member': {'id': 'memberxyz'}})
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
update_template = copy.deepcopy(rsrc.t)
update_template['Properties']['members'] = ['5678']
scheduler.TaskRunner(rsrc.update, update_template)()
self.m.VerifyAll()
def test_update_missing_member(self):
rsrc = self.create_load_balancer()
neutronclient.Client.delete_member(u'member5678').AndRaise(
exceptions.NeutronClientException(status_code=404))
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
update_template = copy.deepcopy(rsrc.t)
update_template['Properties']['members'] = []
scheduler.TaskRunner(rsrc.update, update_template)()
self.assertEqual((rsrc.UPDATE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
def test_delete(self):
rsrc = self.create_load_balancer()
neutronclient.Client.delete_member(u'member5678')
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
scheduler.TaskRunner(rsrc.delete)()
self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
def test_delete_missing_member(self):
rsrc = self.create_load_balancer()
neutronclient.Client.delete_member(u'member5678').AndRaise(
exceptions.NeutronClientException(status_code=404))
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
scheduler.TaskRunner(rsrc.delete)()
self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
class PoolUpdateHealthMonitorsTest(common.HeatTestCase):
def setUp(self):
super(PoolUpdateHealthMonitorsTest, self).setUp()
self.m.StubOutWithMock(neutronclient.Client, 'create_pool')
self.m.StubOutWithMock(neutronclient.Client, 'delete_pool')
self.m.StubOutWithMock(neutronclient.Client, 'show_pool')
self.m.StubOutWithMock(neutronclient.Client, 'update_pool')
self.m.StubOutWithMock(neutronclient.Client,
'associate_health_monitor')
self.m.StubOutWithMock(neutronclient.Client,
'disassociate_health_monitor')
self.m.StubOutWithMock(neutronclient.Client, 'create_health_monitor')
self.m.StubOutWithMock(neutronclient.Client, 'delete_health_monitor')
self.m.StubOutWithMock(neutronclient.Client, 'show_health_monitor')
self.m.StubOutWithMock(neutronclient.Client, 'update_health_monitor')
self.m.StubOutWithMock(neutronclient.Client, 'create_vip')
self.m.StubOutWithMock(neutronclient.Client, 'delete_vip')
self.m.StubOutWithMock(neutronclient.Client, 'show_vip')
def _create_pool_with_health_monitors(self):
neutronclient.Client.create_health_monitor({
'health_monitor': {
'delay': 3, 'max_retries': 5, 'type': u'HTTP',
'timeout': 10, 'admin_state_up': True}}
).AndReturn({'health_monitor': {'id': '5555'}})
neutronclient.Client.create_health_monitor({
'health_monitor': {
'delay': 3, 'max_retries': 5, 'type': u'HTTP',
'timeout': 10, 'admin_state_up': True}}
).AndReturn({'health_monitor': {'id': '6666'}})
self.stub_SubnetConstraint_validate()
neutronclient.Client.create_pool({
'pool': {
'subnet_id': 'sub123', 'protocol': u'HTTP',
'name': utils.PhysName('test_stack', 'pool'),
'lb_method': 'ROUND_ROBIN', 'admin_state_up': True}}
).AndReturn({'pool': {'id': '5678'}})
neutronclient.Client.associate_health_monitor(
'5678', {'health_monitor': {'id': '5555'}}).InAnyOrder()
neutronclient.Client.associate_health_monitor(
'5678', {'health_monitor': {'id': '6666'}}).InAnyOrder()
neutronclient.Client.create_vip({
'vip': {
'protocol': u'HTTP', 'name': 'pool.vip',
'admin_state_up': True, 'subnet_id': u'sub123',
'pool_id': '5678', 'protocol_port': 80}}
).AndReturn({'vip': {'id': 'xyz'}})
neutronclient.Client.show_pool('5678').AndReturn(
{'pool': {'status': 'ACTIVE'}})
neutronclient.Client.show_vip('xyz').AndReturn(
{'vip': {'status': 'ACTIVE'}})
def test_update_pool_with_references_to_health_monitors(self):
self._create_pool_with_health_monitors()
neutronclient.Client.disassociate_health_monitor(
'5678', mox.IsA(six.string_types))
self.m.ReplayAll()
snippet = template_format.parse(pool_with_health_monitors_template)
self.stack = utils.parse_stack(snippet)
self.stack.create()
self.assertEqual((self.stack.CREATE, self.stack.COMPLETE),
self.stack.state)
snippet['resources']['pool']['properties']['monitors'] = [
{u'get_resource': u'monitor1'}]
updated_stack = utils.parse_stack(snippet)
self.stack.update(updated_stack)
self.assertEqual((self.stack.UPDATE, self.stack.COMPLETE),
self.stack.state)
self.m.VerifyAll()
def test_update_pool_with_empty_list_of_health_monitors(self):
self._create_pool_with_health_monitors()
neutronclient.Client.disassociate_health_monitor(
'5678', '5555').InAnyOrder()
neutronclient.Client.disassociate_health_monitor(
'5678', '6666').InAnyOrder()
self.m.ReplayAll()
snippet = template_format.parse(pool_with_health_monitors_template)
self.stack = utils.parse_stack(snippet)
self.stack.create()
self.assertEqual((self.stack.CREATE, self.stack.COMPLETE),
self.stack.state)
snippet['resources']['pool']['properties']['monitors'] = []
updated_stack = utils.parse_stack(snippet)
self.stack.update(updated_stack)
self.assertEqual((self.stack.UPDATE, self.stack.COMPLETE),
self.stack.state)
self.m.VerifyAll()
def test_update_pool_without_health_monitors(self):
self._create_pool_with_health_monitors()
neutronclient.Client.disassociate_health_monitor(
'5678', '5555').InAnyOrder()
neutronclient.Client.disassociate_health_monitor(
'5678', '6666').InAnyOrder()
self.m.ReplayAll()
snippet = template_format.parse(pool_with_health_monitors_template)
self.stack = utils.parse_stack(snippet)
self.stack.create()
self.assertEqual((self.stack.CREATE, self.stack.COMPLETE),
self.stack.state)
snippet['resources']['pool']['properties'].pop('monitors')
updated_stack = utils.parse_stack(snippet)
self.stack.update(updated_stack)
self.assertEqual((self.stack.UPDATE, self.stack.COMPLETE),
self.stack.state)
self.m.VerifyAll()