diff options
Diffstat (limited to 'oti/event-handler/otihandler/dbclient')
8 files changed, 384 insertions, 0 deletions
diff --git a/oti/event-handler/otihandler/dbclient/__init__.py b/oti/event-handler/otihandler/dbclient/__init__.py new file mode 100644 index 0000000..ee3ec3e --- /dev/null +++ b/oti/event-handler/otihandler/dbclient/__init__.py @@ -0,0 +1,19 @@ +# ================================================================================ +# Copyright (c) 2019-2020 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= + +from .models import Event +from .models import EventAck +from .db_dao import DaoBase diff --git a/oti/event-handler/otihandler/dbclient/apis/__init__.py b/oti/event-handler/otihandler/dbclient/apis/__init__.py new file mode 100644 index 0000000..05e3800 --- /dev/null +++ b/oti/event-handler/otihandler/dbclient/apis/__init__.py @@ -0,0 +1,18 @@ +# ================================================================================ +# Copyright (c) 2019-2020 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= + +from .db_access import DbAccess +from .event_db_access import EventDbAccess diff --git a/oti/event-handler/otihandler/dbclient/apis/db_access.py b/oti/event-handler/otihandler/dbclient/apis/db_access.py new file mode 100644 index 0000000..f064b30 --- /dev/null +++ b/oti/event-handler/otihandler/dbclient/apis/db_access.py @@ -0,0 +1,50 @@ +# ================================================================================ +# Copyright (c) 2019-2020 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= + +""" +Base class for APIs to interact with application database using sqlAlchemy ORM lib and postgresSql driver +""" + +from sqlalchemy.orm import sessionmaker +from ..db_dao import DaoBase +import psycopg2 +from psycopg2.extras import execute_values +import os +import logging + + +class DbAccess(object): + logger = logging.getLogger("dti_handler.DbAccess") + engine = None + session = None + + def __init__(self): + self.engine = DaoBase.getDbEngine() + # create a configured "Session" class + Session = sessionmaker(bind=self.engine) + + # create a Session + self.session = Session() + + def saveDomainObject(self, obj): + self.session.add(obj) + self.session.commit() + self.session.close() + + def deleteDomainObject(self,obj): + self.session.delete(obj) + self.session.commit() + self.session.close() diff --git a/oti/event-handler/otihandler/dbclient/apis/event_db_access.py b/oti/event-handler/otihandler/dbclient/apis/event_db_access.py new file mode 100644 index 0000000..898ee8e --- /dev/null +++ b/oti/event-handler/otihandler/dbclient/apis/event_db_access.py @@ -0,0 +1,154 @@ +# ================================================================================ +# Copyright (c) 2019-2020 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= + +""" DB APIs to interact with application database using sqlAlchemy ORM lib and postgresSql driver""" + +from sqlalchemy import and_ +from sqlalchemy.orm.exc import NoResultFound + +from .db_access import DbAccess +from ..models import Event, EventAck + + +class EventDbAccess(DbAccess): + + def __init__(self): + DbAccess.__init__(self) + + def query_event_item(self, target_type, target_name): + try: + query = self.session.query(Event).filter(Event.target_type == target_type).\ + filter(Event.target_name == target_name) + evt = query.one() + except NoResultFound: + return None + else: + return evt + + def query_event_data(self, target_type, target_name): + try: + query = self.session.query(Event).filter(Event.target_type == target_type).\ + filter(Event.target_name == target_name) + evt = query.one() + except NoResultFound: + return [] + else: + try: + ack_result = self.session.query(EventAck).filter(EventAck.event == evt).all() + except NoResultFound: + return [] + else: + return ack_result + + def query_event_data_k8s(self, target_type, target_name): + try: + query = self.session.query(Event).filter(Event.target_type == target_type).\ + filter(Event.target_name == target_name) + evt = query.one() + except NoResultFound: + return [] + else: + try: + ack_result = self.session.query(EventAck).filter(EventAck.event == evt).\ + filter(EventAck.container_type != 'docker').all() + except NoResultFound: + return [] + else: + return ack_result + + def query_event_info_docker(self, prim_evt, service_component, deployment_id, container_id): + try: + query = self.session.query(EventAck).filter(EventAck.event == prim_evt).filter( + and_(EventAck.service_component == service_component, + EventAck.deployment_id == deployment_id, + EventAck.container_id == container_id, + EventAck.container_type == 'docker')) + evt = query.one() + except NoResultFound as nrf: + raise nrf + else: + return evt + + def update_event_item(self, dti_event, target_type, target_name): + self.session.query(Event).filter(Event.target_type == target_type). \ + filter(Event.target_name == target_name).update({Event.event:dti_event}) + self.session.commit() + + def query_raw_k8_events(self, cluster, pod, namespace): + """ + run an inner JOIN query to dtih_event and dtih_event_ack tables using supplied query predicates + + :param cluster: + :param pod: + :param namespace: + :return: + Set of event objects related to k8s pods + """ + try: + return self.session.query(Event).filter(Event.dtih_event_id.in_( + self.session.query(EventAck.dtih_event_id).filter(and_(EventAck.k8s_cluster_fqdn == cluster, + EventAck.k8s_pod_id == pod, + EventAck.k8s_namespace == namespace)))).all() + except NoResultFound: + print("invalid query or no data") + return () + + def query_raw_docker_events(self, target_types, locations): + """ + run a query to dtih_event table using supplied query predicates + + :param target_types: required + :param locations: optional + :return: + set of event objects related to docker container + """ + try: + if not locations or (len(locations) == 1 and locations[0] == ''): + return self.session.query(Event).filter(Event.target_type.in_(target_types)).all() + else: + return self.session.query(Event).filter(Event.target_type.in_(target_types)).filter( + Event.location_clli.in_(locations)).all() + except NoResultFound: + print("invalid query or no data") + return () + + def query_pod_info2(self, cluster): + try: + return self.session.query(EventAck).filter(EventAck.k8s_cluster_fqdn == cluster).all() + except NoResultFound: + print("invalid query or no data") + return () + + def query_pod_info(self, cluster): + try: + return self.session.query(EventAck.k8s_pod_id, EventAck.k8s_namespace, + EventAck.k8s_proxy_fqdn, EventAck.k8s_service_name, + EventAck.k8s_service_port)\ + .filter(EventAck.k8s_cluster_fqdn == cluster) \ + .distinct().order_by(EventAck.k8s_cluster_fqdn).all() + except NoResultFound: + print("invalid query or no data") + return () + + def query_event_data_k8s_pod(self, prim_evt, scn): + try: + query = self.session.query(EventAck).filter(EventAck.event == prim_evt).filter( + and_(EventAck.service_component == scn)) + event_info = query.one() + except NoResultFound: + return None + else: + return event_info diff --git a/oti/event-handler/otihandler/dbclient/db_dao.py b/oti/event-handler/otihandler/dbclient/db_dao.py new file mode 100644 index 0000000..78fa058 --- /dev/null +++ b/oti/event-handler/otihandler/dbclient/db_dao.py @@ -0,0 +1,33 @@ +# ================================================================================ +# Copyright (c) 2019-2020 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= + +""" SqlAlchemy ORM engine for postgresSql dti database """ + +from sqlalchemy import create_engine + +class DaoBase: + _engine = None + + @staticmethod + def init_db(dbConStr): + if DaoBase._engine: + return + DaoBase._engine = create_engine(dbConStr) + + @staticmethod + def getDbEngine(): + return DaoBase._engine + diff --git a/oti/event-handler/otihandler/dbclient/models/__init__.py b/oti/event-handler/otihandler/dbclient/models/__init__.py new file mode 100644 index 0000000..bc802f5 --- /dev/null +++ b/oti/event-handler/otihandler/dbclient/models/__init__.py @@ -0,0 +1,19 @@ +# ================================================================================ +# Copyright (c) 2019-2020 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= + + +from .event import Event +from .event_ack import EventAck diff --git a/oti/event-handler/otihandler/dbclient/models/event.py b/oti/event-handler/otihandler/dbclient/models/event.py new file mode 100644 index 0000000..553bec2 --- /dev/null +++ b/oti/event-handler/otihandler/dbclient/models/event.py @@ -0,0 +1,40 @@ +# ================================================================================ +# Copyright (c) 2019-2020 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= + +""" ORM - mapping class for dtih_event table """ + +from sqlalchemy import Column, String, Integer, ForeignKey, func +from sqlalchemy.dialects.postgresql import JSONB, TIMESTAMP +from sqlalchemy.ext.declarative import declarative_base +import datetime + + +Base = declarative_base() + +class Event(Base): + __tablename__ = 'dtih_event' + __table_args__ = {'schema': 'dti'} + dtih_event_id = Column(Integer, primary_key=True) + event = Column(JSONB) + create_ts = Column(TIMESTAMP(timezone=True), default=func.now()) + last_modified_ts = Column(TIMESTAMP(timezone=True), default=func.now()) + target_name = Column(String) + target_type = Column(String) + location_clli = Column(String) + # def __repr__(self): + # return "<Event(event_id='%s', target_type='%s', target_name='%s')" % ( + # self.event_id, self.target_type, self.target_name + # ) diff --git a/oti/event-handler/otihandler/dbclient/models/event_ack.py b/oti/event-handler/otihandler/dbclient/models/event_ack.py new file mode 100644 index 0000000..2b19316 --- /dev/null +++ b/oti/event-handler/otihandler/dbclient/models/event_ack.py @@ -0,0 +1,51 @@ +# ================================================================================ +# Copyright (c) 2019-2020 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= + +""" ORM - mapping class for dtih_event_ack table """ + +import datetime +from sqlalchemy import Column, String, Integer, ForeignKey, func +from sqlalchemy.dialects.postgresql import JSONB, TIMESTAMP +from sqlalchemy.orm import relationship +from sqlalchemy.ext.declarative import declarative_base +from ..models import Event + +Base = declarative_base() + +class EventAck(Base): + __tablename__ = 'dtih_event_ack' + __table_args__ = {'schema': 'dti'} + dtih_event_ack_id = Column(Integer, primary_key=True) + create_ts = Column(TIMESTAMP(timezone=True), default=func.now()) + last_modified_ts = Column(TIMESTAMP(timezone=True), default=func.now()) + action = Column(String) + k8s_namespace = Column(String) + k8s_service_name = Column(String) + k8s_service_port = Column(String) + k8s_cluster_fqdn = Column(String) + k8s_proxy_fqdn = Column(String) + k8s_pod_id = Column(String) + service_component = Column(String) + deployment_id = Column(String) + container_type = Column(String) + docker_host = Column(String) + container_id = Column(String) + reconfig_script = Column(String) + dtih_event_id = Column(Integer, ForeignKey(Event.dtih_event_id)) + event = relationship(Event) + + def update_action(self, action): + setattr(self, 'action', action) |