diff --git a/src/context/service/database/Link.py b/src/context/service/database/Link.py index 67ac9f518f610caedc631444187cac10aded56c7..f19a9f90fe3ce57a768d69e7947dc1b04ce6cbe0 100644 --- a/src/context/service/database/Link.py +++ b/src/context/service/database/Link.py @@ -99,11 +99,23 @@ def link_set(db_engine : Engine, messagebroker : MessageBroker, request : Link) }) topology_uuids.add(endpoint_topology_uuid) + total_capacity_gbps, current_capacity_gbps = None, None + if request.HasField('attributes'): + attributes = request.attributes + if attributes.HasField('total_capacity_gbps'): + total_capacity_gbps = attributes.total_capacity_gbps + if attributes.HasField('current_capacity_gbps'): + current_capacity_gbps = attributes.current_capacity_gbps + elif total_capacity_gbps is not None: + current_capacity_gbps = total_capacity_gbps + link_data = [{ - 'link_uuid' : link_uuid, - 'link_name' : link_name, - 'created_at': now, - 'updated_at': now, + 'link_uuid' : link_uuid, + 'link_name' : link_name, + 'total_capacity_gbps' : total_capacity_gbps, + 'current_capacity_gbps': current_capacity_gbps, + 'created_at' : now, + 'updated_at' : now, }] def callback(session : Session) -> Tuple[bool, List[Dict]]: @@ -111,8 +123,10 @@ def link_set(db_engine : Engine, messagebroker : MessageBroker, request : Link) stmt = stmt.on_conflict_do_update( index_elements=[LinkModel.link_uuid], set_=dict( - link_name = stmt.excluded.link_name, - updated_at = stmt.excluded.updated_at, + link_name = stmt.excluded.link_name, + total_capacity_gbps = stmt.excluded.total_capacity_gbps, + current_capacity_gbps = stmt.excluded.current_capacity_gbps, + updated_at = stmt.excluded.updated_at, ) ) stmt = stmt.returning(LinkModel.created_at, LinkModel.updated_at) diff --git a/src/context/service/database/models/LinkModel.py b/src/context/service/database/models/LinkModel.py index 9c16da3c9146f28352e8b4f7a6f9ab85f870c8b7..8840841421ec38d87eab69dd2b6471a5a80a83c0 100644 --- a/src/context/service/database/models/LinkModel.py +++ b/src/context/service/database/models/LinkModel.py @@ -13,7 +13,7 @@ # limitations under the License. import operator -from sqlalchemy import CheckConstraint, Column, DateTime, ForeignKey, Integer, String +from sqlalchemy import CheckConstraint, Column, DateTime, Float, ForeignKey, Integer, String from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import relationship from typing import Dict @@ -22,19 +22,26 @@ from ._Base import _Base class LinkModel(_Base): __tablename__ = 'link' - link_uuid = Column(UUID(as_uuid=False), primary_key=True) - link_name = Column(String, nullable=False) - created_at = Column(DateTime, nullable=False) - updated_at = Column(DateTime, nullable=False) + link_uuid = Column(UUID(as_uuid=False), primary_key=True) + link_name = Column(String, nullable=False) + total_capacity_gbps = Column(Float, nullable=True) + current_capacity_gbps = Column(Float, nullable=True) + created_at = Column(DateTime, nullable=False) + updated_at = Column(DateTime, nullable=False) #topology_links = relationship('TopologyLinkModel', back_populates='link') link_endpoints = relationship('LinkEndPointModel') # lazy='joined', back_populates='link' + __table_args__ = ( + CheckConstraint(total_capacity_gbps >= 0, name='check_value_total_capacity_gbps' ), + CheckConstraint(current_capacity_gbps >= 0, name='check_value_current_capacity_gbps'), + ) + def dump_id(self) -> Dict: return {'link_uuid': {'uuid': self.link_uuid}} def dump(self) -> Dict: - return { + result = { 'link_id' : self.dump_id(), 'name' : self.link_name, 'link_endpoint_ids': [ @@ -42,6 +49,13 @@ class LinkModel(_Base): for link_endpoint in sorted(self.link_endpoints, key=operator.attrgetter('position')) ], } + if self.total_capacity_gbps is not None: + attributes : Dict = result.setdefault('attributes', dict()) + attributes.setdefault('total_capacity_gbps', self.total_capacity_gbps) + if self.current_capacity_gbps is not None: + attributes : Dict = result.setdefault('attributes', dict()) + attributes.setdefault('current_capacity_gbps', self.current_capacity_gbps) + return result class LinkEndPointModel(_Base): __tablename__ = 'link_endpoint' diff --git a/src/context/tests/Objects.py b/src/context/tests/Objects.py index 6b52ef4c0f3583de628706ba79efffb9d5709820..3ca51631949e877fa0157421a8208ae9999cb40b 100644 --- a/src/context/tests/Objects.py +++ b/src/context/tests/Objects.py @@ -71,18 +71,33 @@ DEVICE_R3_NAME, DEVICE_R3_ID, DEVICE_R3 = compose_device('R3', ['1.1', '1.2', '2 # ----- Link ----------------------------------------------------------------------------------------------------------- -def compose_link(name : str, endpoint_ids : List[Tuple[str, str]]) -> Tuple[str, Dict, Dict]: +def compose_link( + name : str, endpoint_ids : List[Tuple[str, str]], + total_capacity_gbps : Optional[float] = None, current_capacity_gbps : Optional[float] = None +) -> Tuple[str, Dict, Dict]: link_id = json_link_id(name) endpoint_ids = [ json_endpoint_id(device_id, endpoint_name, topology_id=TOPOLOGY_ID) for device_id, endpoint_name in endpoint_ids ] - link = json_link(name, endpoint_ids) + link = json_link( + name, endpoint_ids, total_capacity_gbps=total_capacity_gbps, + current_capacity_gbps=current_capacity_gbps + ) return name, link_id, link -LINK_R1_R2_NAME, LINK_R1_R2_ID, LINK_R1_R2 = compose_link('R1==R2', [(DEVICE_R1_ID, '1.2'), (DEVICE_R2_ID, '1.1')]) -LINK_R2_R3_NAME, LINK_R2_R3_ID, LINK_R2_R3 = compose_link('R2==R3', [(DEVICE_R2_ID, '1.3'), (DEVICE_R3_ID, '1.2')]) -LINK_R1_R3_NAME, LINK_R1_R3_ID, LINK_R1_R3 = compose_link('R1==R3', [(DEVICE_R1_ID, '1.3'), (DEVICE_R3_ID, '1.1')]) +LINK_R1_R2_NAME, LINK_R1_R2_ID, LINK_R1_R2 = compose_link( + 'R1==R2', [(DEVICE_R1_ID, '1.2'), (DEVICE_R2_ID, '1.1')], + total_capacity_gbps=100, # current_capacity_gbps=None => current_capacity_gbps=total_capacity_gbps +) +LINK_R2_R3_NAME, LINK_R2_R3_ID, LINK_R2_R3 = compose_link( + 'R2==R3', [(DEVICE_R2_ID, '1.3'), (DEVICE_R3_ID, '1.2')], + total_capacity_gbps=100, # current_capacity_gbps=None => current_capacity_gbps=total_capacity_gbps +) +LINK_R1_R3_NAME, LINK_R1_R3_ID, LINK_R1_R3 = compose_link( + 'R1==R3', [(DEVICE_R1_ID, '1.3'), (DEVICE_R3_ID, '1.1')], + total_capacity_gbps=100, # current_capacity_gbps=None => current_capacity_gbps=total_capacity_gbps +) # ----- Service -------------------------------------------------------------------------------------------------------- diff --git a/src/context/tests/test_link.py b/src/context/tests/test_link.py index 894ef8ef1472e4b451314970883cb9467c63b02b..e16aa21f3ac51e5a330f96172d717388adc855ab 100644 --- a/src/context/tests/test_link.py +++ b/src/context/tests/test_link.py @@ -95,6 +95,11 @@ def test_link(context_client : ContextClient) -> None: assert response.link_id.link_uuid.uuid == link_uuid assert response.name == LINK_R1_R2_NAME assert len(response.link_endpoint_ids) == 2 + assert response.HasField('attributes') + assert response.attributes.HasField('total_capacity_gbps') + assert abs(response.attributes.total_capacity_gbps - 100) < 1.e-12 + assert response.attributes.HasField('current_capacity_gbps') + assert abs(response.attributes.current_capacity_gbps - response.attributes.total_capacity_gbps) < 1.e-12 # ----- List when the object exists -------------------------------------------------------------------------------- response = context_client.ListLinkIds(Empty()) @@ -111,6 +116,8 @@ def test_link(context_client : ContextClient) -> None: new_link_name = 'new' LINK_UPDATED = copy.deepcopy(LINK_R1_R2) LINK_UPDATED['name'] = new_link_name + LINK_UPDATED['attributes']['total_capacity_gbps'] = 200 + LINK_UPDATED['attributes']['current_capacity_gbps'] = 50 response = context_client.SetLink(Link(**LINK_UPDATED)) assert response.link_uuid.uuid == link_uuid @@ -125,6 +132,11 @@ def test_link(context_client : ContextClient) -> None: assert response.link_id.link_uuid.uuid == link_uuid assert response.name == new_link_name assert len(response.link_endpoint_ids) == 2 + assert response.HasField('attributes') + assert response.attributes.HasField('total_capacity_gbps') + assert abs(response.attributes.total_capacity_gbps - 200) < 1.e-12 + assert response.attributes.HasField('current_capacity_gbps') + assert abs(response.attributes.current_capacity_gbps - 50) < 1.e-12 # ----- List when the object is modified --------------------------------------------------------------------------- response = context_client.ListLinkIds(Empty()) @@ -136,6 +148,12 @@ def test_link(context_client : ContextClient) -> None: assert response.links[0].link_id.link_uuid.uuid == link_uuid assert response.links[0].name == new_link_name assert len(response.links[0].link_endpoint_ids) == 2 + assert len(response.links[0].link_endpoint_ids) == 2 + assert response.links[0].HasField('attributes') + assert response.links[0].attributes.HasField('total_capacity_gbps') + assert abs(response.links[0].attributes.total_capacity_gbps - 200) < 1.e-12 + assert response.links[0].attributes.HasField('current_capacity_gbps') + assert abs(response.links[0].attributes.current_capacity_gbps - 50) < 1.e-12 # ----- Check relation was created --------------------------------------------------------------------------------- response = context_client.GetTopology(TopologyId(**TOPOLOGY_ID))