diff --git a/src/service/clmcservice/__init__.py b/src/service/clmcservice/__init__.py index 3f29bc471ffead52b38f17779ecfe0df97ed72ae..69ee81be1959127a710caae3971c05673f88ccb0 100644 --- a/src/service/clmcservice/__init__.py +++ b/src/service/clmcservice/__init__.py @@ -23,6 +23,8 @@ """ from pyramid.config import Configurator +from sqlalchemy import engine_from_config +from clmcservice.models import DBSession, Base from clmcservice.aggregationapi.utilities import validate_conf_file, RUNNING_FLAG, MALFORMED_FLAG, CONF_FILE_ATTRIBUTE, CONF_OBJECT, AGGREGATOR_CONFIG_SECTION @@ -31,6 +33,10 @@ def main(global_config, **settings): This function returns a Pyramid WSGI application. """ + engine = engine_from_config(settings, 'sqlalchemy.') # initialise a database engine by using the 'sqlalchemy' setting in the configuration .ini file + DBSession.configure(bind=engine) # bind the engine to a DB session + Base.metadata.bind = engine # bind the engine to the Base class metadata + # validate and use (if valid) the configuration file conf_file_path = settings[CONF_FILE_ATTRIBUTE] conf = validate_conf_file(conf_file_path) # if None returned here, service is in unconfigured state diff --git a/src/service/clmcservice/initialize_db.py b/src/service/clmcservice/initialize_db.py new file mode 100644 index 0000000000000000000000000000000000000000..a0b1a099cd340e0d712a7c0fc5f470d93f877fd0 --- /dev/null +++ b/src/service/clmcservice/initialize_db.py @@ -0,0 +1,38 @@ +import os +import sys +from sqlalchemy import engine_from_config +from pyramid.paster import get_appsettings, setup_logging +from clmcservice.models import DBSession, Base + + +def usage(argv): + """ + A method to be called when the script has been used in an incorrect way. + + :param argv: cmd arguments + """ + + cmd = os.path.basename(argv[0]) + print('usage: %s <config_uri>\n' + '(example: "%s development.ini")' % (cmd, cmd)) + sys.exit(1) + + +def main(argv=sys.argv): + """ + Main method of the script - initialises the database by creating all tables declared in the models.py module + + :param argv: command line arguments - expects a configuration .ini file from which it retrieves the URL with which to connect to postgresql + """ + + if len(argv) != 2: + usage(argv) # in case of wrong usage + + config_uri = argv[1] + setup_logging(config_uri) + + settings = get_appsettings(config_uri) # get application specific settings + engine = engine_from_config(settings, 'sqlalchemy.') # create the db engine from the sqlalchemy setting configured in the .ini file + + DBSession.configure(bind=engine) + Base.metadata.create_all(engine) # creates all model tables diff --git a/src/service/clmcservice/models.py b/src/service/clmcservice/models.py new file mode 100644 index 0000000000000000000000000000000000000000..840fc08fa5ff0078432b75df670bbf485a043d32 --- /dev/null +++ b/src/service/clmcservice/models.py @@ -0,0 +1,28 @@ +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import scoped_session, sessionmaker +from zope.sqlalchemy import ZopeTransactionExtension +from sqlalchemy import Column, String, Integer, UniqueConstraint + + +DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension())) # initialise a ORM session, ought to be reused across the different modules +Base = declarative_base() # initialise a declarative Base instance to use for the web app models + + +class ServiceFunctionEndpoint(Base): + """ + This class defines the main model of the WHOAMI API, declaring the global tags for a specific service function on a specific endpoint. + """ + + __tablename__ = 'sfendpoints' # table name in the PostgreSQL database + + __table_args__ = (UniqueConstraint('sf_i', 'sf_endpoint', 'sr'),) # defines a unique constraint across 3 columns - sf_i, sf_endpoint, sr + + uid = Column(Integer, primary_key=True, autoincrement=True) # a primary key integer field (auto incremented) + + location = Column(String) # cluster label + sfc = Column(String) # service function chain label + sfc_i = Column(String) # service function chain instance identifier + sf = Column(String) # service function label + sf_i = Column(String) # service function identifier (potentially FQDN) + sf_endpoint = Column(String) # service function endpoint (potentially IP address) + sr = Column(String) # service router ID - service router that connects the VM to FLAME diff --git a/src/service/development.ini b/src/service/development.ini index 390e2a57ed7e266dd5105fb1ef609b50e16f9207..18e7f240980ddfa64376748b32529325d72ae2a8 100644 --- a/src/service/development.ini +++ b/src/service/development.ini @@ -14,9 +14,11 @@ pyramid.default_locale_name = en pyramid.includes = pyramid_debugtoolbar pyramid_exclog exclog.ignore = -## Configuration file path +# Configuration file path configuration_file_path = /etc/flame/clmc/service.conf +# PostgreSQL connection url +sqlalchemy.url = postgresql://clmc:clmc_service@localhost:5432/whoamidb # By default, the toolbar only appears for clients from IP addresses # '127.0.0.1' and '::1'. @@ -36,7 +38,7 @@ listen = localhost:9080 ### [loggers] -keys = root, exc_logger, clmcservice +keys = root, exc_logger, service_logger, sqlalchemy.engine.base.Engine [handlers] keys = console, filelog, exc_handler @@ -48,7 +50,12 @@ keys = generic, exc_formatter level = INFO handlers = console -[logger_clmcservice] +[logger_sqlalchemy.engine.base.Engine] +level = INFO +handlers = +qualname = sqlalchemy.engine.base.Engine + +[logger_service_logger] level = INFO handlers = filelog qualname = service_logger diff --git a/src/service/production.ini b/src/service/production.ini index 3e8876b27dab359006c463c17ac24c12020ce171..8ebe666780978f9f0e4b056f5b4851a3b60dffac 100644 --- a/src/service/production.ini +++ b/src/service/production.ini @@ -14,9 +14,11 @@ pyramid.default_locale_name = en pyramid.includes = pyramid_exclog exclog.ignore = -## Configuration file path +# Configuration file path configuration_file_path = /etc/flame/clmc/service.conf +# PostgreSQL connection url +sqlalchemy.url = postgresql://clmc:clmc_service@localhost:5432/whoamidb ### # wsgi server configuration @@ -32,7 +34,7 @@ listen = *:9080 ### [loggers] -keys = root, exc_logger, service_logger +keys = root, exc_logger, service_logger, sqlalchemy.engine.base.Engine [handlers] keys = console, filelog, exc_handler @@ -44,6 +46,11 @@ keys = generic, exc_formatter level = INFO handlers = console +[logger_sqlalchemy.engine.base.Engine] +level = INFO +handlers = +qualname = sqlalchemy.engine.base.Engine + [logger_service_logger] level = INFO handlers = filelog diff --git a/src/service/setup.py b/src/service/setup.py index 4b80091da7183c2eb3510e4f92c14c2498711b3d..7bbc33268cb6b8c57e30489569362872b5c13309 100644 --- a/src/service/setup.py +++ b/src/service/setup.py @@ -46,6 +46,9 @@ requires = [ 'pyramid_debugtoolbar', 'pyramid_exclog', 'waitress', + 'sqlalchemy', + 'zope.sqlalchemy', + 'psycopg2', 'influxdb', 'pytest', ] @@ -80,5 +83,8 @@ setup( 'paste.app_factory': [ 'main = clmcservice:main', ], + 'console_scripts': [ + 'initialize_clmcservice_db = clmcservice.initialize_db:main', + ] }, ) \ No newline at end of file