Merge "Add timestamp to octavia resources"

This commit is contained in:
Jenkins 2016-06-08 18:45:12 +00:00 committed by Gerrit Code Review
commit 1939931504
14 changed files with 193 additions and 29 deletions

View File

@ -45,6 +45,8 @@ class ListenerResponse(base.BaseType):
default_pool = wtypes.wsattr(pool.PoolResponse)
l7policies = wtypes.wsattr([l7policy.L7PolicyResponse])
insert_headers = wtypes.wsattr(wtypes.DictType(str, str))
created_at = wtypes.wsattr(wtypes.StringType())
updated_at = wtypes.wsattr(wtypes.StringType())
@classmethod
def from_data_model(cls, data_model, children=False):

View File

@ -36,6 +36,8 @@ class LoadBalancerResponse(base.BaseType):
vip = wtypes.wsattr(VIP)
project_id = wtypes.wsattr(wtypes.StringType())
listeners = wtypes.wsattr([listener.ListenerResponse])
created_at = wtypes.wsattr(wtypes.StringType())
updated_at = wtypes.wsattr(wtypes.StringType())
@classmethod
def from_data_model(cls, data_model, children=False):

View File

@ -27,6 +27,8 @@ class MemberResponse(base.BaseType):
weight = wtypes.wsattr(wtypes.IntegerType())
subnet_id = wtypes.wsattr(wtypes.UuidType())
project_id = wtypes.wsattr(wtypes.StringType())
created_at = wtypes.wsattr(wtypes.StringType())
updated_at = wtypes.wsattr(wtypes.StringType())
class MemberPOST(base.BaseType):

View File

@ -52,6 +52,8 @@ class PoolResponse(base.BaseType):
project_id = wtypes.wsattr(wtypes.StringType())
health_monitor = wtypes.wsattr(health_monitor.HealthMonitorResponse)
members = wtypes.wsattr([member.MemberResponse])
created_at = wtypes.wsattr(wtypes.StringType())
updated_at = wtypes.wsattr(wtypes.StringType())
@classmethod
def from_data_model(cls, data_model, children=False):

View File

@ -172,12 +172,12 @@ class HealthMonitor(BaseDataModel):
class Pool(BaseDataModel):
def __init__(self, id=None, project_id=None, name=None, description=None,
protocol=None, lb_algorithm=None, enabled=None,
operating_status=None, members=None, health_monitor=None,
session_persistence=None, load_balancer_id=None,
load_balancer=None, listeners=None, l7policies=None):
load_balancer=None, listeners=None, l7policies=None,
created_at=None, updated_at=None):
self.id = id
self.project_id = project_id
self.name = name
@ -193,6 +193,8 @@ class Pool(BaseDataModel):
self.session_persistence = session_persistence
self.listeners = listeners or []
self.l7policies = l7policies or []
self.created_at = created_at
self.updated_at = updated_at
def update(self, update_dict):
for key, value in update_dict.items():
@ -236,7 +238,8 @@ class Member(BaseDataModel):
def __init__(self, id=None, project_id=None, pool_id=None, ip_address=None,
protocol_port=None, weight=None, enabled=None,
subnet_id=None, operating_status=None, pool=None):
subnet_id=None, operating_status=None, pool=None,
created_at=None, updated_at=None):
self.id = id
self.project_id = project_id
self.pool_id = pool_id
@ -247,6 +250,8 @@ class Member(BaseDataModel):
self.subnet_id = subnet_id
self.operating_status = operating_status
self.pool = pool
self.created_at = created_at
self.updated_at = updated_at
def delete(self):
for mem in self.pool.members:
@ -263,7 +268,8 @@ class Listener(BaseDataModel):
enabled=None, provisioning_status=None, operating_status=None,
tls_certificate_id=None, stats=None, default_pool=None,
load_balancer=None, sni_containers=None, peer_port=None,
l7policies=None, pools=None, insert_headers=None):
l7policies=None, pools=None, insert_headers=None,
created_at=None, updated_at=None):
self.id = id
self.project_id = project_id
self.name = name
@ -285,6 +291,8 @@ class Listener(BaseDataModel):
self.l7policies = l7policies or []
self.insert_headers = insert_headers or {}
self.pools = pools or []
self.created_at = created_at
self.updated_at = updated_at
def update(self, update_dict):
for key, value in update_dict.items():
@ -322,7 +330,8 @@ class LoadBalancer(BaseDataModel):
def __init__(self, id=None, project_id=None, name=None, description=None,
provisioning_status=None, operating_status=None, enabled=None,
topology=None, vip=None, listeners=None, amphorae=None,
pools=None, vrrp_group=None, server_group_id=None):
pools=None, vrrp_group=None, server_group_id=None,
created_at=None, updated_at=None):
self.id = id
self.project_id = project_id
@ -338,6 +347,8 @@ class LoadBalancer(BaseDataModel):
self.amphorae = amphorae or []
self.pools = pools or []
self.server_group_id = server_group_id
self.created_at = created_at
self.updated_at = updated_at
class VRRPGroup(BaseDataModel):

View File

@ -14,11 +14,18 @@
from oslo_db.sqlalchemy import models
from oslo_utils import uuidutils
import six
import sqlalchemy as sa
from sqlalchemy.ext import declarative
from sqlalchemy.orm import collections
def datetime_to_str(dct, attr_name):
if (dct.get(attr_name) is not None
and not isinstance(dct.get(attr_name), six.string_types)):
dct[attr_name] = dct[attr_name].isoformat(' ')
class OctaviaBase(models.ModelBase):
__data_model__ = None
@ -64,6 +71,9 @@ class OctaviaBase(models.ModelBase):
dm_kwargs = {}
for column in self.__table__.columns:
dm_kwargs[column.name] = getattr(self, column.name)
datetime_to_str(dm_kwargs, 'created_at')
datetime_to_str(dm_kwargs, 'updated_at')
attr_names = [attr_name for attr_name in dir(self)
if not attr_name.startswith('_')]
# Appending early, as any unique ID should be defined already and

View File

@ -0,0 +1,42 @@
# Copyright 2016 Catalyst IT
#
# 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.
"""add timestamp
Revision ID: 36b94648fef8
Revises: 4d9cf7d32f2
Create Date: 2016-04-21 10:45:32.278433
"""
# revision identifiers, used by Alembic.
revision = '36b94648fef8'
down_revision = '4d9cf7d32f2'
from alembic import op
import sqlalchemy as sa
tables = ['member', 'pool', 'load_balancer', 'listener']
def upgrade():
for table in tables:
op.add_column(
table,
sa.Column(u'created_at', sa.DateTime(), nullable=True)
)
op.add_column(
table,
sa.Column(u'updated_at', sa.DateTime(), nullable=True)
)

View File

@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslo_db.sqlalchemy import models
import sqlalchemy as sa
from sqlalchemy.ext import orderinglist
from sqlalchemy import orm
@ -152,7 +152,8 @@ class ListenerStatistics(base_models.BASE):
return value
class Member(base_models.BASE, base_models.IdMixin, base_models.ProjectMixin):
class Member(base_models.BASE, base_models.IdMixin, base_models.ProjectMixin,
models.TimestampMixin):
__data_model__ = data_models.Member
@ -210,7 +211,8 @@ class HealthMonitor(base_models.BASE, base_models.ProjectMixin):
cascade="delete"))
class Pool(base_models.BASE, base_models.IdMixin, base_models.ProjectMixin):
class Pool(base_models.BASE, base_models.IdMixin, base_models.ProjectMixin,
models.TimestampMixin):
__data_model__ = data_models.Pool
@ -260,7 +262,7 @@ class Pool(base_models.BASE, base_models.IdMixin, base_models.ProjectMixin):
class LoadBalancer(base_models.BASE, base_models.IdMixin,
base_models.ProjectMixin):
base_models.ProjectMixin, models.TimestampMixin):
__data_model__ = data_models.LoadBalancer
@ -333,7 +335,7 @@ class Vip(base_models.BASE):
class Listener(base_models.BASE, base_models.IdMixin,
base_models.ProjectMixin):
base_models.ProjectMixin, models.TimestampMixin):
__data_model__ = data_models.Listener

View File

@ -51,6 +51,12 @@ class TestListener(base.BaseAPITest):
listener2['operating_status'] = constants.ONLINE
listener3['provisioning_status'] = constants.ACTIVE
listener3['operating_status'] = constants.ONLINE
for listener in api_listeners:
del listener['updated_at']
self.assertIsNone(listener1.pop('updated_at'))
self.assertIsNone(listener2.pop('updated_at'))
self.assertIsNone(listener3.pop('updated_at'))
self.assertIn(listener1, api_listeners)
self.assertIn(listener2, api_listeners)
self.assertIn(listener3, api_listeners)
@ -105,6 +111,8 @@ class TestListener(base.BaseAPITest):
self.assertEqual(2, len(sni_resp))
for sni in sni_resp:
self.assertIn(sni, sni_ex)
self.assertIsNotNone(listener_api.pop('created_at'))
self.assertIsNone(listener_api.pop('updated_at'))
self.assertEqual(lb_listener, listener_api)
self.assert_correct_lb_status(self.lb.get('id'),
constants.PENDING_UPDATE,
@ -182,6 +190,8 @@ class TestListener(base.BaseAPITest):
lb_listener.update(defaults)
self.assertTrue(uuidutils.is_uuid_like(listener_api.get('id')))
lb_listener['id'] = listener_api.get('id')
self.assertIsNotNone(listener_api.pop('created_at'))
self.assertIsNone(listener_api.pop('updated_at'))
self.assertEqual(lb_listener, listener_api)
self.assert_correct_lb_status(self.lb.get('id'),
constants.PENDING_UPDATE,
@ -209,6 +219,10 @@ class TestListener(base.BaseAPITest):
'provisioning_status': constants.PENDING_UPDATE,
'operating_status': constants.ONLINE}
listener.update(update_expect)
self.assertEqual(listener.pop('created_at'),
api_listener.pop('created_at'))
self.assertNotEqual(listener.pop('updated_at'),
api_listener.pop('updated_at'))
self.assertNotEqual(listener, api_listener)
self.assert_correct_lb_status(self.lb.get('id'),
constants.PENDING_UPDATE,
@ -277,6 +291,9 @@ class TestListener(base.BaseAPITest):
'provisioning_status': constants.PENDING_DELETE,
'connection_limit': None}
listener.update(expected)
self.assertIsNone(listener.pop('updated_at'))
self.assertIsNotNone(api_listener.pop('updated_at'))
self.assertEqual(listener, api_listener)
self.assert_correct_lb_status(self.lb.get('id'),
constants.PENDING_UPDATE,

View File

@ -41,6 +41,8 @@ class TestLoadBalancer(base.BaseAPITest):
self.assertEqual(constants.OFFLINE,
api_lb.get('operating_status'))
self.assertTrue(api_lb.get('enabled'))
self.assertIsNotNone(api_lb.get('created_at'))
self.assertIsNone(api_lb.get('updated_at'))
for key, value in optionals.items():
self.assertEqual(value, lb_json.get(key))
self.assert_final_lb_statuses(api_lb.get('id'))
@ -156,6 +158,8 @@ class TestLoadBalancer(base.BaseAPITest):
api_lb.get('provisioning_status'))
self.assertEqual(lb.get('operational_status'),
api_lb.get('operational_status'))
self.assertIsNotNone(api_lb.get('created_at'))
self.assertIsNotNone(api_lb.get('updated_at'))
self.assert_final_lb_statuses(api_lb.get('id'))
def test_update_with_vip(self):
@ -266,12 +270,18 @@ class TestLoadBalancerGraph(base.BaseAPITest):
def _assert_graphs_equal(self, expected_graph, observed_graph):
observed_graph_copy = copy.deepcopy(observed_graph)
del observed_graph_copy['created_at']
del observed_graph_copy['updated_at']
obs_lb_id = observed_graph_copy.pop('id')
self.assertTrue(uuidutils.is_uuid_like(obs_lb_id))
expected_listeners = expected_graph.pop('listeners', [])
observed_listeners = observed_graph_copy.pop('listeners', [])
self.assertEqual(expected_graph, observed_graph_copy)
for observed_listener in observed_listeners:
del observed_listener['created_at']
del observed_listener['updated_at']
self.assertTrue(uuidutils.is_uuid_like(
observed_listener.pop('id')))
default_pool = observed_listener.get('default_pool')
@ -279,6 +289,8 @@ class TestLoadBalancerGraph(base.BaseAPITest):
observed_listener.pop('default_pool_id')
self.assertTrue(default_pool.get('id'))
default_pool.pop('id')
default_pool.pop('created_at')
default_pool.pop('updated_at')
hm = default_pool.get('healthmonitor')
if hm:
self.assertTrue(hm.get('id'))
@ -286,6 +298,8 @@ class TestLoadBalancerGraph(base.BaseAPITest):
for member in default_pool.get('members', []):
self.assertTrue(member.get('id'))
member.pop('id')
member.pop('created_at')
member.pop('updated_at')
if observed_listener.get('sni_containers'):
observed_listener['sni_containers'].sort()
o_l7policies = observed_listener.get('l7policies')
@ -295,12 +309,16 @@ class TestLoadBalancerGraph(base.BaseAPITest):
r_pool = o_l7policy.get('redirect_pool')
self.assertTrue(r_pool.get('id'))
r_pool.pop('id')
r_pool.pop('created_at')
r_pool.pop('updated_at')
self.assertTrue(o_l7policy.get('redirect_pool_id'))
o_l7policy.pop('redirect_pool_id')
if r_pool.get('members'):
for r_member in r_pool.get('members'):
self.assertTrue(r_member.get('id'))
r_member.pop('id')
r_member.pop('created_at')
r_member.pop('updated_at')
self.assertTrue(o_l7policy.get('id'))
o_l7policy.pop('id')
l7rules = o_l7policy.get('l7rules')

View File

@ -94,6 +94,8 @@ class TestMember(base.BaseAPITest):
'10.0.0.1', 80)
self.assertEqual('10.0.0.1', api_member.get('ip_address'))
self.assertEqual(80, api_member.get('protocol_port'))
self.assertIsNotNone(api_member.get('created_at'))
self.assertIsNone(api_member.get('updated_at'))
self.assert_correct_lb_status(self.lb.get('id'),
constants.PENDING_UPDATE,
constants.ONLINE)
@ -225,7 +227,8 @@ class TestMember(base.BaseAPITest):
self.set_lb_status(self.lb.get('id'))
response_body = response.json
self.assertEqual(old_port, response_body.get('protocol_port'))
self.assertEqual(api_member.get('created_at'),
response_body.get('created_at'))
self.assert_correct_lb_status(self.lb.get('id'),
constants.ACTIVE,
constants.ONLINE)
@ -278,10 +281,13 @@ class TestMember(base.BaseAPITest):
self.pool_with_listener.get('id'),
'10.0.0.1', 80)
self.set_lb_status(self.lb.get('id'))
response = self.get(self.member_path.format(
member_id=api_member.get('id')))
member = self.get(self.member_path.format(
member_id=api_member.get('id'))).json
api_member['operating_status'] = constants.ONLINE
self.assertEqual(api_member, response.json)
self.assertIsNone(api_member.pop('updated_at'))
self.assertIsNotNone(member.pop('updated_at'))
self.assertEqual(api_member, member)
self.delete(self.member_path.format(member_id=api_member.get('id')))
self.assert_correct_lb_status(self.lb.get('id'),
constants.PENDING_UPDATE,
@ -308,10 +314,13 @@ class TestMember(base.BaseAPITest):
self.pool_with_listener.get('id'),
'10.0.0.1', 80)
self.set_lb_status(self.lb.get('id'))
response = self.get(self.member_path.format(
member_id=api_member.get('id')))
member = self.get(self.member_path.format(
member_id=api_member.get('id'))).json
api_member['operating_status'] = constants.ONLINE
self.assertEqual(api_member, response.json)
self.assertIsNone(api_member.pop('updated_at'))
self.assertIsNotNone(member.pop('updated_at'))
self.assertEqual(api_member, member)
self.handler_mock().member.delete.side_effect = Exception()
self.delete(self.member_path.format(
member_id=api_member.get('id')))

View File

@ -100,6 +100,8 @@ class TestPool(base.BaseAPITest):
self.assertEqual(constants.PROTOCOL_HTTP, api_pool.get('protocol'))
self.assertEqual(constants.LB_ALGORITHM_ROUND_ROBIN,
api_pool.get('lb_algorithm'))
self.assertIsNotNone(api_pool.get('created_at'))
self.assertIsNone(api_pool.get('updated_at'))
self.assert_correct_lb_status(self.lb.get('id'),
constants.ACTIVE,
constants.ONLINE)
@ -239,6 +241,8 @@ class TestPool(base.BaseAPITest):
response = self.get(self.pool_path.format(pool_id=api_pool.get('id')))
response_body = response.json
self.assertNotEqual('new_name', response_body.get('name'))
self.assertIsNotNone(response_body.get('created_at'))
self.assertIsNotNone(response_body.get('updated_at'))
self.assert_correct_lb_status(self.lb.get('id'),
constants.ACTIVE,
constants.ONLINE)
@ -289,7 +293,11 @@ class TestPool(base.BaseAPITest):
api_pool['operating_status'] = constants.ONLINE
response = self.get(self.pool_path.format(
pool_id=api_pool.get('id')))
self.assertEqual(api_pool, response.json)
pool = response.json
self.assertIsNone(api_pool.pop('updated_at'))
self.assertIsNotNone(pool.pop('updated_at'))
self.assertEqual(api_pool, pool)
self.delete(self.pool_path.format(pool_id=api_pool.get('id')))
self.assert_correct_lb_status(self.lb.get('id'),
constants.PENDING_UPDATE,
@ -331,7 +339,11 @@ class TestPool(base.BaseAPITest):
api_pool['operating_status'] = constants.ONLINE
response = self.get(self.pool_path.format(
pool_id=api_pool.get('id')))
self.assertEqual(api_pool, response.json)
pool = response.json
self.assertIsNone(api_pool.pop('updated_at'))
self.assertIsNotNone(pool.pop('updated_at'))
self.assertEqual(api_pool, pool)
self.handler_mock().pool.delete.side_effect = Exception()
self.delete(self.pool_path.format(pool_id=api_pool.get('id')))
self.assert_correct_lb_status(self.lb.get('id'),

View File

@ -165,15 +165,21 @@ class ModelTestMixin(object):
class PoolModelTest(base.OctaviaDBTestBase, ModelTestMixin):
def test_create(self):
self.create_pool(self.session)
pool = self.create_pool(self.session)
self.assertIsNotNone(pool.created_at)
self.assertIsNone(pool.updated_at)
def test_update(self):
pool = self.create_pool(self.session)
self.assertIsNone(pool.updated_at)
id = pool.id
pool.name = 'test1'
pool.enabled = False
new_pool = self.session.query(
models.Pool).filter_by(id=id).first()
self.assertEqual('test1', new_pool.name)
self.assertFalse(new_pool.enabled)
self.assertIsNotNone(new_pool.updated_at)
def test_delete(self):
pool = self.create_pool(self.session)
@ -233,15 +239,22 @@ class MemberModelTest(base.OctaviaDBTestBase, ModelTestMixin):
self.pool = self.create_pool(self.session)
def test_create(self):
self.create_member(self.session, self.pool.id)
member = self.create_member(self.session, self.pool.id)
self.assertIsNotNone(member.created_at)
self.assertIsNone(member.updated_at)
def test_update(self):
member = self.create_member(self.session, self.pool.id)
self.assertIsNone(member.updated_at)
member_id = member.id
member.name = 'test1'
member.enabled = False
new_member = self.session.query(
models.Member).filter_by(id=member_id).first()
self.assertEqual('test1', new_member.name)
self.assertFalse(new_member.enabled)
self.assertIsNotNone(new_member.updated_at)
def test_delete(self):
member = self.create_member(self.session, self.pool.id)
@ -303,15 +316,21 @@ class SessionPersistenceModelTest(base.OctaviaDBTestBase, ModelTestMixin):
class ListenerModelTest(base.OctaviaDBTestBase, ModelTestMixin):
def test_create(self):
self.create_listener(self.session)
listener = self.create_listener(self.session)
self.assertIsNotNone(listener.created_at)
self.assertIsNone(listener.updated_at)
def test_update(self):
listener = self.create_listener(self.session)
self.assertIsNone(listener.updated_at)
listener_id = listener.id
listener.name = 'test1'
new_listener = self.session.query(
models.Listener).filter_by(id=listener_id).first()
self.assertEqual('test1', new_listener.name)
self.assertIsNotNone(new_listener.updated_at)
def test_delete(self):
listener = self.create_listener(self.session)
@ -449,15 +468,21 @@ class HealthMonitorModelTest(base.OctaviaDBTestBase, ModelTestMixin):
class LoadBalancerModelTest(base.OctaviaDBTestBase, ModelTestMixin):
def test_create(self):
self.create_load_balancer(self.session)
load_balancer = self.create_load_balancer(self.session)
self.assertIsNotNone(load_balancer.created_at)
self.assertIsNone(load_balancer.updated_at)
def test_update(self):
load_balancer = self.create_load_balancer(self.session)
self.assertIsNone(load_balancer.updated_at)
lb_id = load_balancer.id
load_balancer.name = 'test1'
load_balancer.enabled = False
new_load_balancer = self.session.query(
models.LoadBalancer).filter_by(id=lb_id).first()
self.assertEqual('test1', new_load_balancer.name)
self.assertFalse(new_load_balancer.enabled)
self.assertIsNotNone(new_load_balancer.updated_at)
def test_delete(self):
load_balancer = self.create_load_balancer(self.session)

View File

@ -132,6 +132,8 @@ class AllRepositoriesTest(base.OctaviaDBTestBase):
del lb_dm_dict['listeners']
del lb_dm_dict['amphorae']
del lb_dm_dict['pools']
del lb_dm_dict['created_at']
del lb_dm_dict['updated_at']
self.assertEqual(lb, lb_dm_dict)
vip_dm_dict = lb_dm.vip.to_dict()
vip_dm_dict['load_balancer_id'] = lb_dm.id
@ -155,6 +157,8 @@ class AllRepositoriesTest(base.OctaviaDBTestBase):
del pool_dm_dict['load_balancer']
del pool_dm_dict['load_balancer_id']
del pool_dm_dict['l7policies']
del pool_dm_dict['created_at']
del pool_dm_dict['updated_at']
self.assertEqual(pool, pool_dm_dict)
new_listener = self.repos.listener.get(self.session,
id=self.listener.id)
@ -181,6 +185,8 @@ class AllRepositoriesTest(base.OctaviaDBTestBase):
del pool_dm_dict['load_balancer']
del pool_dm_dict['load_balancer_id']
del pool_dm_dict['l7policies']
del pool_dm_dict['created_at']
del pool_dm_dict['updated_at']
self.assertEqual(pool, pool_dm_dict)
sp_dm_dict = pool_dm.session_persistence.to_dict()
del sp_dm_dict['pool']
@ -213,6 +219,8 @@ class AllRepositoriesTest(base.OctaviaDBTestBase):
del pool_dm_dict['load_balancer']
del pool_dm_dict['load_balancer_id']
del pool_dm_dict['l7policies']
del pool_dm_dict['created_at']
del pool_dm_dict['updated_at']
pool.update(update_pool)
self.assertEqual(pool, pool_dm_dict)
self.assertIsNone(new_pool_dm.session_persistence)
@ -243,6 +251,8 @@ class AllRepositoriesTest(base.OctaviaDBTestBase):
del pool_dm_dict['load_balancer']
del pool_dm_dict['load_balancer_id']
del pool_dm_dict['l7policies']
del pool_dm_dict['created_at']
del pool_dm_dict['updated_at']
pool.update(update_pool)
self.assertEqual(pool, pool_dm_dict)
sp_dm_dict = new_pool_dm.session_persistence.to_dict()