Support for Name field in Members and HMs

This patch adds support to enable naming LBaasV2 Members and Health
Monitors(HMs).

DocImpact

Closes-Bug: #1515506
Change-Id: Ieb66386fac3a5a4dace0112838fe9afde212f055
This commit is contained in:
Reedip Banerjee 2015-11-13 12:32:27 +05:30
parent 7275578a2c
commit cb3ae497c0
6 changed files with 129 additions and 34 deletions

View File

@ -14,6 +14,7 @@
# under the License.
from neutron.api.v2 import attributes as attr
from neutron.db import model_base
from neutron.db import models_v2
from neutron.db import servicetype_db as st_db
@ -85,6 +86,7 @@ class MemberV2(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):
subnet_id = sa.Column(sa.String(36), nullable=True)
provisioning_status = sa.Column(sa.String(16), nullable=False)
operating_status = sa.Column(sa.String(16), nullable=False)
name = sa.Column(sa.String(attr.NAME_MAX_LEN), nullable=True)
@property
def root_loadbalancer(self):
@ -109,6 +111,7 @@ class HealthMonitorV2(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):
expected_codes = sa.Column(sa.String(64), nullable=True)
provisioning_status = sa.Column(sa.String(16), nullable=False)
admin_state_up = sa.Column(sa.Boolean(), nullable=False)
name = sa.Column(sa.String(attr.NAME_MAX_LEN), nullable=True)
@property
def root_loadbalancer(self):

View File

@ -0,0 +1,35 @@
# Copyright 2015 NEC Corporation
#
# 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.
"""Addition of Name column to lbaas_members and lbaas_healthmonitors table
Revision ID: 4a408dd491c2
Revises: 3345facd0452
Create Date: 2015-11-16 11:47:43.061649
"""
# revision identifiers, used by Alembic.
revision = '4a408dd491c2'
down_revision = '3345facd0452'
from alembic import op
import sqlalchemy as sa
LB_TAB_NAME = ['lbaas_members', 'lbaas_healthmonitors']
def upgrade():
for table in LB_TAB_NAME:
op.add_column(table, sa.Column('name', sa.String(255), nullable=True))

View File

@ -316,7 +316,11 @@ RESOURCE_ATTRIBUTE_MAP = {
'admin_state_up': {'allow_post': True, 'allow_put': True,
'default': True,
'convert_to': attr.convert_to_boolean,
'is_visible': True}
'is_visible': True},
'name': {'allow_post': True, 'allow_put': True,
'validate': {'type:string': attr.NAME_MAX_LEN},
'default': '',
'is_visible': True}
}
}
@ -352,7 +356,10 @@ SUB_RESOURCE_ATTRIBUTE_MAP = {
'subnet_id': {'allow_post': True, 'allow_put': False,
'validate': {'type:uuid': None},
'is_visible': True},
'name': {'allow_post': True, 'allow_put': True,
'validate': {'type:string': attr.NAME_MAX_LEN},
'default': '',
'is_visible': True},
}
}
}

View File

@ -271,7 +271,7 @@ class HealthMonitor(BaseDataModel):
def __init__(self, id=None, tenant_id=None, type=None, delay=None,
timeout=None, max_retries=None, http_method=None,
url_path=None, expected_codes=None, provisioning_status=None,
admin_state_up=None, pool=None):
admin_state_up=None, pool=None, name=None):
self.id = id
self.tenant_id = tenant_id
self.type = type
@ -284,6 +284,7 @@ class HealthMonitor(BaseDataModel):
self.provisioning_status = provisioning_status
self.admin_state_up = admin_state_up
self.pool = pool
self.name = name
def attached_to_loadbalancer(self):
return bool(self.pool and self.pool.listener and
@ -378,7 +379,7 @@ class Member(BaseDataModel):
def __init__(self, id=None, tenant_id=None, pool_id=None, address=None,
protocol_port=None, weight=None, admin_state_up=None,
subnet_id=None, operating_status=None,
provisioning_status=None, pool=None):
provisioning_status=None, pool=None, name=None):
self.id = id
self.tenant_id = tenant_id
self.pool_id = pool_id
@ -390,6 +391,7 @@ class Member(BaseDataModel):
self.operating_status = operating_status
self.provisioning_status = provisioning_status
self.pool = pool
self.name = name
def attached_to_loadbalancer(self):
return bool(self.pool and self.pool.listener and

View File

@ -129,7 +129,7 @@ class LbaasTestMixin(object):
return pool_res
def _get_member_optional_args(self):
return 'weight', 'admin_state_up'
return 'weight', 'admin_state_up', 'name'
def _create_member(self, fmt, pool_id, address, protocol_port, subnet_id,
expected_res_status=None, **kwargs):
@ -142,7 +142,6 @@ class LbaasTestMixin(object):
for arg in args:
if arg in kwargs and kwargs[arg] is not None:
data['member'][arg] = kwargs[arg]
member_req = self.new_create_request('pools',
data,
fmt=fmt,
@ -156,7 +155,7 @@ class LbaasTestMixin(object):
def _get_healthmonitor_optional_args(self):
return ('weight', 'admin_state_up', 'expected_codes', 'url_path',
'http_method')
'http_method', 'name')
def _create_healthmonitor(self, fmt, pool_id, type, delay, timeout,
max_retries, expected_res_status=None, **kwargs):
@ -1625,13 +1624,14 @@ class LbaasMemberTests(MemberTestBase):
'weight': 1,
'admin_state_up': True,
'tenant_id': self._tenant_id,
'subnet_id': ''
'subnet_id': '',
'name': 'member1'
}
expected.update(extras)
expected['subnet_id'] = self.test_subnet_id
with self.member(pool_id=self.pool_id) as member:
with self.member(pool_id=self.pool_id, name='member1') as member:
member_id = member['member'].get('id')
self.assertTrue(member_id)
@ -1667,12 +1667,14 @@ class LbaasMemberTests(MemberTestBase):
('tenant_id', self._tenant_id),
('protocol_port', 80),
('weight', 10),
('admin_state_up', False)]
('admin_state_up', False),
('name', 'member2')]
with self.member(pool_id=self.pool_id) as member:
member_id = member['member']['id']
resp, pool1_update = self._get_pool_api(self.pool_id)
self.assertEqual(1, len(pool1_update['pool']['members']))
data = {'member': {'weight': 10, 'admin_state_up': False}}
data = {'member': {'weight': 10, 'admin_state_up': False,
'name': 'member2'}}
resp, body = self._update_member_api(self.pool_id, member_id, data)
for k, v in keys:
self.assertEqual(v, body['member'][k])
@ -1694,15 +1696,18 @@ class LbaasMemberTests(MemberTestBase):
('tenant_id', self._tenant_id),
('protocol_port', 80),
('weight', 1),
('admin_state_up', True)]
with self.member(pool_id=self.pool_id) as member:
('admin_state_up', True),
('name', 'member1')]
with self.member(pool_id=self.pool_id,
name='member1') as member:
member_id = member['member']['id']
resp, body = self._get_member_api(self.pool_id, member_id)
for k, v in keys:
self.assertEqual(v, body['member'][k])
def test_list_members(self):
with self.member(pool_id=self.pool_id, protocol_port=81):
with self.member(pool_id=self.pool_id,
name='member1', protocol_port=81):
resp, body = self._list_members_api(self.pool_id)
self.assertEqual(1, len(body['members']))
@ -1776,6 +1781,17 @@ class LbaasMemberTests(MemberTestBase):
'WRONG_POOL_ID', member_id, data)
self.assertEqual(webob.exc.HTTPNotFound.code, resp.status_int)
def test_create_member_invalid_name(self):
data = {'member': {'address': '127.0.0.1',
'protocol_port': 80,
'weight': 1,
'admin_state_up': True,
'tenant_id': self._tenant_id,
'subnet_id': self.test_subnet_id,
'name': 123}}
resp, body = self._create_member_api('POOL_ID', data)
self.assertEqual(webob.exc.HTTPBadRequest.code, resp.status_int)
def test_delete_member_invalid_pool_id(self):
with self.member(pool_id=self.pool_id) as member:
member_id = member['member']['id']
@ -1783,7 +1799,8 @@ class LbaasMemberTests(MemberTestBase):
self.assertEqual(webob.exc.HTTPNotFound.code, resp.status_int)
def test_get_pool_shows_members(self):
with self.member(pool_id=self.pool_id) as member:
with self.member(pool_id=self.pool_id,
name='member1') as member:
expected = {'id': member['member']['id']}
resp, body = self._get_pool_api(self.pool_id)
self.assertIn(expected, body['pool']['members'])
@ -1834,12 +1851,14 @@ class LbaasHealthMonitorTests(HealthMonitorTestBase):
'expected_codes': '200',
'admin_state_up': True,
'tenant_id': self._tenant_id,
'pools': [{'id': self.pool_id}]
'pools': [{'id': self.pool_id}],
'name': 'monitor1'
}
expected.update(extras)
with self.healthmonitor(pool_id=self.pool_id) as healthmonitor:
with self.healthmonitor(pool_id=self.pool_id,
name='monitor1') as healthmonitor:
hm_id = healthmonitor['healthmonitor'].get('id')
self.assertTrue(hm_id)
@ -1868,12 +1887,15 @@ class LbaasHealthMonitorTests(HealthMonitorTestBase):
'expected_codes': '200',
'admin_state_up': True,
'tenant_id': self._tenant_id,
'pools': [{'id': self.pool_id}]
'pools': [{'id': self.pool_id}],
'name': 'monitor1'
}
expected.update(extras)
with self.healthmonitor(pool_id=self.pool_id) as healthmonitor:
with self.healthmonitor(pool_id=self.pool_id,
name='monitor1') as healthmonitor:
hm_id = healthmonitor['healthmonitor']['id']
resp, body = self._get_healthmonitor_api(hm_id)
actual = {}
@ -1895,18 +1917,21 @@ class LbaasHealthMonitorTests(HealthMonitorTestBase):
'expected_codes': '200,404',
'admin_state_up': True,
'tenant_id': self._tenant_id,
'pools': [{'id': self.pool_id}]
'pools': [{'id': self.pool_id}],
'name': 'monitor2'
}
expected.update(extras)
with self.healthmonitor(pool_id=self.pool_id) as healthmonitor:
with self.healthmonitor(pool_id=self.pool_id,
name='monitor1') as healthmonitor:
hm_id = healthmonitor['healthmonitor']['id']
data = {'healthmonitor': {'delay': 30,
'timeout': 10,
'max_retries': 4,
'expected_codes': '200,404',
'url_path': '/index.html'}}
'url_path': '/index.html',
'name': 'monitor2'}}
resp, body = self._update_healthmonitor_api(hm_id, data)
actual = {}
for k, v in body['healthmonitor'].items():
@ -2089,6 +2114,17 @@ class LbaasHealthMonitorTests(HealthMonitorTestBase):
resp, body = self._create_healthmonitor_api(data)
self.assertEqual(webob.exc.HTTPNotFound.code, resp.status_int)
def test_create_healthmonitor_invalid_name(self):
data = {'healthmonitor': {'type': lb_const.HEALTH_MONITOR_TCP,
'delay': 1,
'timeout': 1,
'max_retries': 1,
'tenant_id': self._tenant_id,
'pool_id': self.pool_id,
'name': 123}}
resp, body = self._create_healthmonitor_api(data)
self.assertEqual(webob.exc.HTTPBadRequest.code, resp.status_int)
def test_only_one_healthmonitor_per_pool(self):
with self.healthmonitor(pool_id=self.pool_id):
data = {'healthmonitor': {'type': lb_const.HEALTH_MONITOR_TCP,
@ -2111,10 +2147,12 @@ class LbaasHealthMonitorTests(HealthMonitorTestBase):
'expected_codes': '200',
'admin_state_up': True,
'tenant_id': self._tenant_id,
'pools': [{'id': self.pool_id}]
'pools': [{'id': self.pool_id}],
'name': 'monitor1'
}
with self.healthmonitor(pool_id=self.pool_id) as healthmonitor:
with self.healthmonitor(pool_id=self.pool_id,
name='monitor1') as healthmonitor:
hm_id = healthmonitor['healthmonitor']['id']
expected['id'] = hm_id
resp, body = self._get_healthmonitor_api(hm_id)
@ -2131,7 +2169,8 @@ class LbaasHealthMonitorTests(HealthMonitorTestBase):
'expected_codes': '200',
'admin_state_up': True,
'tenant_id': self._tenant_id,
'pools': [{'id': self.pool_id}]
'pools': [{'id': self.pool_id}],
'name': '',
}
with self.healthmonitor(pool_id=self.pool_id) as healthmonitor:

View File

@ -807,7 +807,8 @@ class LoadBalancerExtensionV2TestCase(base.ExtensionTestCase):
'weight': 1,
'subnet_id': subnet_id,
'admin_state_up': True,
'tenant_id': _uuid()}}
'tenant_id': _uuid(),
'name': 'member1'}}
return_value = copy.copy(data['member'])
return_value.update({'id': member_id})
@ -831,7 +832,8 @@ class LoadBalancerExtensionV2TestCase(base.ExtensionTestCase):
return_value = [{'name': 'member1',
'admin_state_up': True,
'tenant_id': _uuid(),
'id': member_id}]
'id': member_id,
'name': 'member1'}]
instance = self.plugin.return_value
instance.get_pools.return_value = return_value
@ -850,7 +852,8 @@ class LoadBalancerExtensionV2TestCase(base.ExtensionTestCase):
update_data = {'member': {'admin_state_up': False}}
return_value = {'admin_state_up': False,
'tenant_id': _uuid(),
'id': member_id}
'id': member_id,
'name': 'member1'}
instance = self.plugin.return_value
instance.update_pool_member.return_value = return_value
@ -872,7 +875,8 @@ class LoadBalancerExtensionV2TestCase(base.ExtensionTestCase):
member_id = _uuid()
return_value = {'admin_state_up': False,
'tenant_id': _uuid(),
'id': member_id}
'id': member_id,
'name': 'member1'}
instance = self.plugin.return_value
instance.get_pool_member.return_value = return_value
@ -911,7 +915,8 @@ class LoadBalancerExtensionV2TestCase(base.ExtensionTestCase):
'expected_codes': '200-300',
'admin_state_up': True,
'tenant_id': _uuid(),
'pool_id': _uuid()}}
'pool_id': _uuid(),
'name': 'monitor1'}}
return_value = copy.copy(data['healthmonitor'])
return_value.update({'id': health_monitor_id})
del return_value['pool_id']
@ -939,7 +944,8 @@ class LoadBalancerExtensionV2TestCase(base.ExtensionTestCase):
'expected_codes': '200-300',
'admin_state_up': True,
'tenant_id': _uuid(),
'pool_id': _uuid()}}
'pool_id': _uuid(),
'name': 'monitor1'}}
res = self.api.post(_get_path('lbaas/healthmonitors',
fmt=self.fmt),
self.serialize(data),
@ -952,7 +958,8 @@ class LoadBalancerExtensionV2TestCase(base.ExtensionTestCase):
return_value = [{'type': 'HTTP',
'admin_state_up': True,
'tenant_id': _uuid(),
'id': health_monitor_id}]
'id': health_monitor_id,
'name': 'monitor1'}]
instance = self.plugin.return_value
instance.get_healthmonitors.return_value = return_value
@ -969,7 +976,8 @@ class LoadBalancerExtensionV2TestCase(base.ExtensionTestCase):
return_value = {'type': 'HTTP',
'admin_state_up': False,
'tenant_id': _uuid(),
'id': health_monitor_id}
'id': health_monitor_id,
'name': 'monitor1'}
instance = self.plugin.return_value
instance.update_healthmonitor.return_value = return_value
@ -991,7 +999,8 @@ class LoadBalancerExtensionV2TestCase(base.ExtensionTestCase):
return_value = {'type': 'HTTP',
'admin_state_up': False,
'tenant_id': _uuid(),
'id': health_monitor_id}
'id': health_monitor_id,
'name': 'monitor1'}
instance = self.plugin.return_value
instance.get_healthmonitor.return_value = return_value