diff options
author | 2017-02-14 15:10:09 +0000 | |
---|---|---|
committer | 2017-02-14 15:10:11 +0000 | |
commit | 7927ff179242b796330d17869c83fa07751abf95 (patch) | |
tree | ba2b93e26ec71bff863bc7be9fb5dbd0b5d9c928 /pgaas | |
parent | d1bf35c127a238238b573103edf7dbcb1ebd48ed (diff) |
Init dcae.pgaas
Change-Id: Ieef6b600f4cbb0bf4ee3910c1bfc6b36773cd2d2
Signed-off-by: lj1412 <lji@research.att.com>
Diffstat (limited to 'pgaas')
73 files changed, 3945 insertions, 0 deletions
diff --git a/pgaas/src/common/postinst b/pgaas/src/common/postinst new file mode 100755 index 0000000..f24e364 --- /dev/null +++ b/pgaas/src/common/postinst @@ -0,0 +1,55 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +exec 1> /tmp/pgaas.out 2>&1 +set -x +if [ -d /opt/app/postgresql-9.5.2 ] +then export OPENECOMP=false NOTOPENECOMP=true +else export OPENECOMP=true NOTOPENECOMP=false +fi + +if $OPENECOMP +then INSTALL_ROOT= +fi + +echo STARTING $0 $(date) +umask 0 +echo STARTING $0 $(date) >> /tmp/pgaas.inst.report +set -x + +export CDFCFG=${INSTALL_ROOT}/opt/app/cdf/lib/cdf.cfg +export PGAASCFG=${INSTALL_ROOT}/opt/app/pgaas/lib/pgaas.cfg + +if [ -d /opt/app/postgresql-9.5.2 ] +then PGDIR=/opt/app/postgresql-9.5.2 +else PGDIR=/usr/lib/postgresql/9.5 +fi +if [ -d /opt/app/postgresql-config-9.5.2/ ] +then CFGDIR=/opt/app/postgresql-config-9.5.2 +else CFGDIR=/opt/app/postgresql-config +fi + +( + grep '^postgres.x' < $CDFCFG | sed -e 's/^postgres/dcae_admin_db_password/' + echo "db_configuration=$CFGDIR/main/postgresql.conf" + echo "pg_bin_directory=$PGDIR/bin" + echo "skip_configuration_file=$CFGDIR/lib/ignore-database-reconfiguration" +) >> $PGAASCFG + +echo ENDING $0 $(date) +echo ENDING $0 $(date) >> /tmp/pgaas.inst.report +if $NOTOPENECOMP +then sed -n '/^STARTING/,/^ENDING/p' `dirname $0`/../../proc_out >> /tmp/pgaas.inst.report +fi diff --git a/pgaas/src/makefile b/pgaas/src/makefile new file mode 100644 index 0000000..73fe4eb --- /dev/null +++ b/pgaas/src/makefile @@ -0,0 +1,41 @@ + +DEVBIN=../../bin +PKG=pgaas +REPACKAGESWMOPTS= +REPACKAGEDEBIANOPTS= + +INS= ../install +INSSTG= $(INS)/stage +INSCOM= $(INS)/common +KEEP= + +all: + +clean-stage: + rm -rf $(INSSTG) + +clean-common: + rm -rf $(INSCOM) + +clean-ins: clean-stage clean-common + rm -rf $(INS) + +clean: clean-ins + rm -rf *~ + +build: + +stage: clean-stage + cd stage/opt/app/pgaas && $(MAKE) stage STAGEDIR=../../../../$(INSSTG) + find common ! -name makefile ! -name '*~' | cpio -pudmv $(INS) + cp -p repackage.* $(INS) + + +debian: stage + repackage -b debian $(REPACKAGEDEBIANOPTS) -d $(INS) -u + repackage -b debian $(REPACKAGEDEBIANOPTS) -d $(INS) -u -B LATEST + @echo debian built + +upload-javadocs: + @echo nothing to do here + diff --git a/pgaas/src/repackage.json b/pgaas/src/repackage.json new file mode 100644 index 0000000..578fe76 --- /dev/null +++ b/pgaas/src/repackage.json @@ -0,0 +1,25 @@ +{ + "executionGroup": "postgres", + "executionUser": "postgres", + "applicationName": "pgaas", + "description": " PostgreSQL as a Service main scripts ", + "maintainer": "OpenECOMP <dcae@lists.openecomp.org>", + "fileUser": "postgres", + "internalDependencies": [], + "directoryTreeTops": { + "/opt": "/opt/app/pgaas" + }, + "debian": { + "conflicts": [], + "groupId": "org.openecomp.dcae.storage.pgaas", + "replaces": [], + "externalDependencies": [] + }, + "fileGroup": "postgres", + "docker": { + "tag": "latest", + "externalDependencies": [] + }, + "version": "1.0.0", + "groupId": "org.openecomp.dcae.storage.pgaas" +}
\ No newline at end of file diff --git a/pgaas/src/stage/opt/app/pgaas/bin/check_cluster b/pgaas/src/stage/opt/app/pgaas/bin/check_cluster new file mode 100755 index 0000000..0af6d95 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/check_cluster @@ -0,0 +1,154 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +# NAME +# check_cluster - check the state of the cluster +# +# USAGE +# check_cluster [-v] [-l] [-t timeout] +# -l do not check localhost first (and restarting the service if necessary) +# -t timeout set how long to wait when accessing the servers +# -v verbose +# +# DESCRIPTION +# Loop through the nodes in the cluster, using pgwget to determine how many are masters, secondaries, or not up. +# Complain about certain situations. +# If there are multiple masters, and this not the first master in the list, then: +# run pg_ctl_restart +# prevent /ro from returning true + +CDF=/opt/app/cdf +if [ -d /opt/app/postgresql-9.5.2 ] +then PGDIR=/opt/app/postgresql-9.5.2 +else PGDIR=/usr/lib/postgresql/9.5 +fi +if [ -d /opt/app/postgresql-config-9.5.2/ ] +then CFGDIR=/opt/app/postgresql-config-9.5.2/ +else CFGDIR=/opt/app/postgresql-config/ +fi +PATH=$PGDIR/bin:$CDF/bin:/opt/app/pgaas/bin:/opt/app/postgresql-prep/bin:$PATH + +usage() +{ + exec 1>&2 + [ $# -gt 0 ] && echo "$@" + echo "Usage: $0 [-v] [-l] [-t timeout]" + echo -e " -l do not check localhost first (and restarting the service if necessary)" + echo -e " -t timeout set how long to wait when accessing the servers" + echo -e " -v verbose" + exit 1 +} + +VERBOSE=false +TIMEOUT=10 +TESTLOCAL=: +while getopts lt:v c +do + case "$c" in + l ) TESTLOCAL=false ;; + t ) TIMEOUT=$OPTARG ;; + v ) VERBOSE=: ;; + \?) usage ;; + esac +done +shift $(($OPTIND - 1)) + +# loop through the nodes in the cluster, using pgwget to determine if any are a master. Save in $@ +master_count=0 +secondary_count=0 +total_count=0 +down_count=0 + +DOWNS= +MASTERS= +SECONDARIES= + +MSEP= +SSEP= +DSEP= +HOSTNAME=$(hostname -f) +FOUNDPREVIOUSMASTER= +DOPGCTLSTOP= + +if $TESTLOCAL +then + isrw=`pgwget --tries=1 --read-timeout=$TIMEOUT --quiet -O/dev/stdout http://localhost:8000/isrw` + case "$isrw" in + Master | Secondary ) ;; + * ) + echo "$(date)|WARNING|RESTARTED|Local iDNS-responder.py not responding. Restarting." + ps -fu postgres | grep "python3 /opt/app/postgresql-prep/bin/iDNS-responder.py" | grep -v grep | awk '{print "kill " $2}' | sh + sleep 10 + ;; + esac +fi + +for i in $(getpropvalue -n pgnodes | sed 's/|/ /g') +do + $VERBOSE && echo -n "Checking $i" + isrw=`pgwget --tries=1 --read-timeout=10 --quiet -O/dev/stdout http://$i:8000/isrw` + $VERBOSE && echo ": $isrw" + case "$isrw" in + Master ) + (( master_count = master_count + 1 )) + (( total_count = total_count + 1 )) + MASTERS="$MASTERS$MSEP$i" + MSEP=" " + if [ -z "$FOUNDPREVIOUSMASTER" ] + then FOUNDPREVIOUSMASTER=yes + elif [ -n "$FOUNDPREVIOUSMASTER" -a "$i" = $HOSTNAME ] + then DOPGCTLSTOP=yes + fi + ;; + Secondary ) + (( secondary_count = secondary_count + 1 )) + (( total_count = total_count + 1 )) + SECONDARIES="$SECONDARIES$SSEP$i" + SSEP=" " + ;; + * ) + DOWNS="$DOWNS$DSEP$i" + DSEP=" " + (( down_count = down_count + 1 )) + (( total_count = total_count + 1 )) + ;; + esac +done + +(( up_count = master_count + secondary_count )) + +date=$(date) +echo "$date|INFO|masters=$master_count $MASTERS|secondaries=$secondary_count $SECONDARIES|down=$down_count $DOWNS|" + +FORCEROOFF=/var/run/postgresql/force-ro-off +if [ $master_count -lt 1 ] +then echo "$date|FATAL|NOMASTER|NO MASTER FOUND|" +elif [ $master_count -gt 1 ] +then echo "$date|FATAL|MULTIPLEMASTERS|TOO MANY MASTERS FOUND|" + if [ -n "$DOPGCTLSTOP" ] + then + touch "$FORCEROOFF" + pg_ctl_stop + fi +fi +if [ -z "$DOPGCTLSTOP" -a -f "$FORCEROOFF" ] +then rm -f "$FORCEROOFF" +fi +if [ $up_count -eq 0 ] +then echo "$date|FATAL|NOREADER|NO SECONDARY FOUND" +fi +if [ $down_count -ne 0 ] +then echo "$date|ERROR|DOWN|One or more systems are down: $DOWNS" +fi diff --git a/pgaas/src/stage/opt/app/pgaas/bin/dcae_admin_db.py b/pgaas/src/stage/opt/app/pgaas/bin/dcae_admin_db.py new file mode 100755 index 0000000..80da148 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/dcae_admin_db.py @@ -0,0 +1,819 @@ +#!/usr/bin/python3 +# -*- indent-tabs-mode: nil -*- +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +""" + +NAME + dcae_admin_db.py - given a database description json file, update the current VM accordingly + +USAGE + dcae_admin_db.py [options] configurationChanged json-file + dcae_admin_db.py [options] suspend + dcae_admin_db.py [options] resume + dcae_admin_db.py [options] test + + options: + + -H / --dbhost= - host name, defaults to CFG['dcae_admin_db_hostname'] + -d / --dbdir= - database directory path, defaults to CFG['db_directory'] + -c / --dbconf= - database configuration path, defaults to CFG['db_configuration'] + -D / --dbname= - database name, defaults to CFG['dcae_admin_db_databasename'] + -U / --user= - user to login as, defaults to CFG['dcae_admin_db_username'] + -P / --password= - password for user, defaults to CFG['dcae_admin_db_password'] + -B / --bindir= - postgresql bin directory, defaults to CFG['pg_bin_directory'] + -i / --ignorefile= - skip configuration if this file is present, defaults to CFG['skip_configuration_file'] + -n / --nocreate - do not create the databases / users + -I / --ignoredb - ignore current state of database + -R / --remove - remove old databases / users + -J / --jsontop= - top of json tree, as in \"['pgaas']\" + -e / --errors= - where to redirect error output, defaults to CFG['dcae_admin_db_errors_file'] then stderr + -t / --trace= - where to redirect trace output, defaults to CFG['dcae_admin_db_trace_file'] then stderr + -v / --verbose - verbose, defaults to CFG['dcae_admin_db_verbosity'] + +DESCRIPTION + This program is intended to be executed by the DCAE controller manager. + +When creating a database and set of users, execute the equivalent of this: + + CREATE USER tstdb_admin WITH PASSWORD 'tst'; + CREATE USER tstdb_user WITH PASSWORD 'tst'; + CREATE USER tstdb_viewer WITH PASSWORD 'tst'; + + CREATE ROLE testdb_common_user_role; + CREATE ROLE testdb_common_viewer_role; + + CREATE DATABASE testdb with owner tstdb_admin; + + \connect testdb + + REVOKE ALL on DATABASE testdb FROM testdb_common_viewer_role; + REVOKE ALL on DATABASE testdb FROM testdb_common_user_role; + REVOKE ALL on DATABASE testdb FROM tstdb_user; + REVOKE ALL on DATABASE testdb FROM tstdb_viewer; + + GRANT testdb_common_viewer_role TO testdb_common_user_role; /* user can do everything viewer can */ + GRANT testdb_common_user_role TO tstdb_admin; /* admin can do everything user and viewer can */ + + GRANT CONNECT ON DATABASE testdb TO testdb_common_viewer_role; /* viewer, user, admin can connect */ + + CREATE SCHEMA testdb_db_common AUTHORIZATION tstdb_admin; /* create a schema we can optionally use */ + + ALTER ROLE tstdb_admin IN DATABASE testdb SET search_path = public, testdb_db_common; /* search_path is not inherited, so set it here */ + ALTER ROLE testdb_common_user_role IN DATABASE testdb SET search_path = public, testdb_db_common; /* search_path is not inherited, so set it here */ + ALTER ROLE testdb_common_viewer_role IN DATABASE testdb SET search_path = public, testdb_db_common; /* search_path is not inherited, so set it here */ + + GRANT USAGE ON SCHEMA testdb_db_common TO testdb_common_viewer_role; /* viewer,user can select from schema */ + GRANT CREATE ON SCHEMA testdb_db_common TO tstdb_admin; /* admin can create on schema */ + + ALTER DEFAULT PRIVILEGES FOR ROLE tstdb_admin GRANT SELECT ON TABLES TO testdb_common_viewer_role; /* viewer, user, admin can select on tables */ + ALTER DEFAULT PRIVILEGES FOR ROLE tstdb_admin GRANT INSERT, UPDATE, DELETE, TRUNCATE ON TABLES TO testdb_common_user_role; /* user, admin can ins/upd/del/tru on tables */ + ALTER DEFAULT PRIVILEGES FOR ROLE tstdb_admin GRANT USAGE, SELECT, UPDATE ON SEQUENCES TO testdb_common_user_role; /* user, admin can update on sequences */ + + GRANT TEMP ON DATABASE testdb TO testdb_common_user_role; /* user, admin can create temp tables */ + + GRANT testdb_common_user_role TO tstdb_user; + GRANT testdb_common_viewer_role TO tstdb_viewer; + ALTER ROLE tstdb_user IN DATABASE testdb SET search_path = public, testdb_db_common; /* search_path is not inherited, so set it here */ + ALTER ROLE tstdb_viewer IN DATABASE testdb SET search_path = public, testdb_db_common; /* search_path is not inherited, so set it here */ + +""" + +import getopt +import psycopg2 +import sys +import re +import subprocess +import json +import os +import time + +sys.path.append("/opt/app/pgaas/lib") +import CommonLogger + +verbose = 0 +quiet = False +errorOutput = sys.stderr +traceOutput = sys.stderr +errorLogger = debugLogger = auditLogger = metricsLogger = None + +def usage(msg = None): + """ + Print a usage message and exit + """ + sys.stdout = sys.stderr + if msg != None: + print(msg) + print("Usage:") + print("dcae_admin_db.py [options] configurationChanged json-file") + print("dcae_admin_db.py [options] suspend") + print("dcae_admin_db.py [options] resume") + print("dcae_admin_db.py [options] test") + print("") + print("options:") + print("-H / --dbhost= - host name, defaults to CFG['dcae_admin_db_hostname']") + print("-d / --dbdir= - database directory path, defaults to CFG['db_directory']") + print("-c / --dbconf= - database directory path, defaults to CFG['db_configuration']") + print("-D / --dbname= - database name, defaults to CFG['dcae_admin_db_databasename']") + print("-n / --nocreate - do not create the databases / users") + print("-I / --ignoredb - ignore current state of database") + print("-U / --user= - user to login as, defaults to CFG['dcae_admin_db_username']") + print("-P / --password= - password for user, defaults to CFG['dcae_admin_db_password']") + print("-B / --bindir= - postgresql bin directory, defaults to CFG['pg_bin_directory']") + print("-i / --ignorefile= - skip configuration if this file is present, defaults to CFG['skip_configuration_file']") + print("-R / --remove - remove old databases / users") + print("-J / --jsontop= - top of json tree, as in \"['pgaas']\"") + print("-l / --logcfg= - ECOMP DCAE Common Logging configuration file") + print("-e / --errors= - where to redirect error output, defaults to CFG['dcae_admin_db_errors_file'] then stderr") + print("-t / --trace= - where to redirect trace output, defaults to CFG['dcae_admin_db_trace_file'] then stderr") + print("-v - verbose") + sys.exit(2) + +def checkOption(options, name, propname, optletter, encrypted=False, cdfPropname = None): + """ + Check if the specified option exists. If not, grab it from the configuration file. + Complain if it still does not exist. + """ + if name not in options: + ret = getPgaasPropValue(propname, encrypted=encrypted, dflt=None, skipComplaining=True) + if ret is None and cdfPropname is not None: + ret = getCdfPropValue(cdfPropname, encrypted=encrypted) + options[name] = ret + requireOption("either %s or config[%s]" % (optletter, propname), options[name]) + +def reviewOpts(): + """ + Parse the options passed to the command, and return them in the dictionary + """ + try: + opts, args = getopt.getopt(sys.argv[1:], "B:c:D:d:e:H:IJ:l:nP:Rt:U:hv?", + [ "dbhost=", "dbdir=", "dbconf=", + "dbname=", "dbuser=", "dbpassword=", + "bindir=", "errors=", "trace=", "logcfg=", + "nocreate", "ignoredb", "remove", "ignorefile=", + "jsontop=", + "help", "verbose"]) + except getopt.GetoptError as err: + usage(str(err)) + + propVerbosity = getPgaasPropValue("dcae_admin_db_verbosity", dflt='0') + if propVerbosity is not None: + global verbose + verbose = int(propVerbosity) + retOptions = { } + ignoreFile = getPgaasPropValue("skip_configuration_file", dflt=None) + for o, a in opts: + if o in ("-v", "--verbose"): + # global verbose + verbose += 1 + elif o in ("-c", "--dbconf"): + retOptions["dbconf"] = a + elif o in ("-H", "--dbhost"): + retOptions["dbhost"] = a + elif o in ("-d", "--dbdir"): + retOptions["dbdir"] = a + elif o in ("-D", "--dbname"): + retOptions["dbname"] = a + elif o in ("-U", "--dbuser"): + retOptions["dbuser"] = a + elif o in ("-P", "--dbpassword"): + retOptions["dbpassword"] = a + elif o in ("-B", "--bindir"): + retOptions["bindir"] = a + elif o in ("-n", "--nocreate"): + retOptions["nocreate"] = True + elif o in ("-I", "--ignoredb"): + retOptions["ignoredb"] = True + elif o in ("-R", "--remove"): + retOptions["noremove"] = True + elif o in ("-J", "--jsontop"): + retOptions["jsontop"] = a + elif o in ("-l", "--logcfg"): + retOptions["logcfg"] = a + elif o in ("-e", "--errors"): + retOptions["errors"] = a + elif o in ("-i", "--ignorefile"): + ignoreFile = a + elif o in ("-t", "--trace"): + retOptions["trace"] = a + elif o in ("-h", "--help"): + usage() + else: + usage("unhandled option: %s" % o) + if "errors" not in retOptions: + retOptions["errors"] = getPgaasPropValue("dcae_admin_db_errors_file") + if "errors" in retOptions and retOptions["errors"] is not None: + try: + errorOutput = open(retOptions["errors"], "a") + except Exception as e: + die("Cannot open errors file '%s': %s" % (retOptions["errors"], e)) + if ignoreFile is not None: + trace("checking to see if skip_configuration_file(%s) exists" % ignoreFile) + retOptions["ignorefile"] = "yes" if os.path.isfile(ignoreFile) else "no" + trace("ignorefile=%s" % retOptions["ignorefile"]) + else: + retOptions["ignorefile"] = None + if "trace" not in retOptions: + retOptions["trace"] = getPgaasPropValue("dcae_admin_db_trace_file") + if "trace" in retOptions and retOptions["trace"] is not None: + try: + traceOutput = open(retOptions["trace"], "a") + except Exception as e: + die("Cannot open trace file '%s': %s" % (retOptions["trace"], e)) + if "logcfg" not in retOptions: + retOptions["logcfg"] = getPgaasPropValue("dcae_admin_db_common_logger_config") + if "logcfg" in retOptions and retOptions["logcfg"] is not None: + logcfg = retOptions["logcfg"] + import uuid + instanceUUID = uuid.uuid1() + serviceName = "DCAE/pgaas" + # print(">>>>>>>>>>>>>>>> using common logger. UUID=%s, serviceName=%s, cfg=%s" % (instanceUUID, serviceName, logcfg)) + global errorLogger, debugLogger, auditLogger, metricsLogger + errorLogger = CommonLogger.CommonLogger(logcfg, "error", instanceUUID=instanceUUID, serviceName=serviceName) + debugLogger = CommonLogger.CommonLogger(logcfg, "debug", instanceUUID=instanceUUID, serviceName=serviceName) + auditLogger = CommonLogger.CommonLogger(logcfg, "audit", instanceUUID=instanceUUID, serviceName=serviceName) + metricsLogger = CommonLogger.CommonLogger(logcfg, "metrics", instanceUUID=instanceUUID, serviceName=serviceName) + auditLogger.info("using common logger. UUID=%s, serviceName=%s, cfg=%s" % (instanceUUID, serviceName, logcfg)) + + checkOption(retOptions, "dbname", "dcae_admin_db_databasename", "-D") + checkOption(retOptions, "dbuser", "dcae_admin_db_username", "-U") + checkOption(retOptions, "dbpassword", "dcae_admin_db_password", "-P", encrypted=True, cdfPropname="postgres") + checkOption(retOptions, "dbhost", "dcae_admin_db_hostname", "-H") + checkOption(retOptions, "dbdir", "db_directory", "-d") + checkOption(retOptions, "bindir", "pg_bin_directory", "-B") + if "jsontop" not in retOptions: + retOptions["jsontop"] = getPgaasPropValue("dcae_admin_db_jsontop") + trace("env=%s" % str(os.environ)) + trace("ignorefile=%s" % ignoreFile) + return retOptions, args + +def main(): + keyedOptions, args = reviewOpts() + trace("Invoked as: %s" % str(sys.argv)) + audit("Invoked as: %s" % str(sys.argv)) + + if len(args) == 0: + usage("no operation specified") + elif args[0] == "configurationChanged": + if len(args) != 2: + usage("too many arguments") + configurationChanged(keyedOptions, args[1]) + elif args[0] == "suspend": + if len(args) != 1: + usage("too many arguments") + suspendOperations(keyedOptions) + elif args[0] == "resume": + if len(args) != 1: + usage("too many arguments") + resumeOperations(keyedOptions) + elif args[0] == "test": + if len(args) != 1: + usage("too many arguments") + testOperations(keyedOptions) + else: + usage("unrecognized operation '%s'" % args[0]) + +def suspendOperations(options): + """ + Execute the "suspend" sub-command. + """ + runProgram(["pkill", "repmgrd"]) + program = options["bindir"] + "/pg_ctl" + cmd = [program, "stop", "-D", options["dbdir"]] + runProgram(cmd) + audit("suspendOperations") + +def resumeOperations(options): + """ + Execute the "resume" sub-command. + """ + cmd = [options["bindir"] + "/pg_ctl", "start", "-D", options["dbdir"], "-o", "configfile=" + options["dbconf"]] + runProgram(cmd) + runProgram(["/opt/app/pgaas/bin/repmgrcd", "-d"]) + audit("resumeOperations") + +def testOperations(options): + """ + Respond to the "test" sub-command. + """ + program = options["bindir"] + "/pg_ctl" + cmd = [program, "status", "-D", options["dbdir"]] + ret = runProgram(cmd) + # pg_ctl: no server running + # pg_ctl: server is running (PID: 13988) + cmdRepmgr = ["pgrep", "repmgrd"] + retRepmgr = runProgram(cmdRepmgr) + + msg = "????" + if re.search("no server running", ret): + msg = "RED: no PG server running" + elif re.search("server is running", ret) and re.search("[0-9]+", retRepmgr): + msg = "GREEN" + elif re.search("server is running", ret): + msg = "YELLOW: no repmgrd running" + elif re.search("[0-9]+", retRepmgr): + msg = "YELLOW: no PG server running" + else: + msg = "YELLOW: neither PG server nor repmgrd are running" + audit("test: " + msg) + print(msg, end="") + +def runProgram(cmd): + """ + Run the given command, returning the standard output as a string. + If there is an error, return None. + """ + try: + p=subprocess.Popen(cmd,shell=False,stdout=subprocess.PIPE,stderr=subprocess.PIPE) + (stdout, stderr) = p.communicate() + except Exception as e: + print("Error running program because: {0}".format(e), file=errorOutput) + return None + else: + if stderr: + print("Error running program because: {0} ".format(stderr), file=errorOutput) + return None + else: + trace("runProgram() => " + str(stdout), minLevel=2) + return stdout.decode('utf-8').rstrip('\n') + +def configurationChanged(options, jsonFile): + """ + We received a new JSON configuration file + """ + audit("configurationChanged " + jsonFile) + if options["ignorefile"] == "yes": + trace("skipping database reconfiguration because skip_configuration_file exists") + return + + if not os.path.isfile(jsonFile): + die("json file %s does not exist" % jsonFile) + + try: + inp = json.load(open(jsonFile,"r")) + except Exception as e: + die("Cannot open jsonFile '%s': %s" % (jsonFile, e)) + + if verbose: + dumpJSON(inp, "incoming JSON") + + jsonTop = options["jsontop"] + if not jsonTop is None: + e = "inp" + jsonTop + trace("eval(%s)" % e) + inp = eval(e,{"__builtins__":None},{"inp":inp}) + if verbose: + dumpJSON(inp, "modified JSON") + + # trace("version=%s" % requireJSON("version", inp, "version")) + requireJSON("databases", inp, "databases") + con = None + try: + con = dbConnect(database = options["dbname"], user = options["dbuser"], password = options["dbpassword"], host = options["dbhost"]) + setupDatabases(con, options, requireJSON("databases", inp, "databases")) + + except psycopg2.DatabaseError as e: + die('Error %s' % e) + + finally: + if con: + con.commit() + con.close() + +def dumpJSON(js, msg): + tracePrint("vvvvvvvvvvvvvvvv %s" % msg) + tracePrint(json.dumps(js, indent=4)) + tracePrint("^^^^^^^^^^^^^^^^ %s" % msg) + +def setupDatabases(con, options, dbList): + """ + Do what is needed to set up all of the databases + """ + currentDatabases = dbGetFirstColumnAsMap(con, "select datname from pg_database where datistemplate = false") + currentRolenames = dbGetFirstColumnAsMap(con, "select rolname from pg_roles") + trace("currentDatabases = " + str(currentDatabases)) + for dbName in dbList: + trace("dbName='%s'" % str(dbName)) + setupDatabase(con, options, currentDatabases, currentRolenames, dbName, dbList[dbName]) + +def setupDatabase(con, options, currentDatabases, currentRolenames, dbName, dbInfo): + """ + Do what is needed to set up a given databases and its users + """ + + dbOwnerRole = requireJSON("databases[].ownerRole", dbInfo, "ownerRole") + trace("dbName='%s', dbOwnerRole='%s'" % (dbName, dbOwnerRole)) + doesDbExist = dbName in currentDatabases + trace("does %s exist? %s" % (dbName, doesDbExist)) + foundOwnerRole = False + dbRoles = dbInfo["roles"] + for name in dbRoles: + u = dbRoles[name] + if name == dbOwnerRole and u["role"] == "admin": + foundOwnerRole = True + if u["role"] not in ("admin","writer","reader"): + die("For database %s, the role '%s' is not one of admin/writer/reader" % (dbName, u.role)) + if not foundOwnerRole: + die("For database %s, information on the ownerRole '%s' was not found" % (dbName, dbOwnerRole)) + for name in dbRoles: + userInfo = dbRoles[name] + if name in currentRolenames and ("ignoredb" not in options or not options["ignoredb"]): + trace("The role %s already exists, skipping" % name) + updatePassword(con, options, dbName, name, userInfo) + else: + setupUser(con, options, dbName, name, userInfo) + if doesDbExist and ("ignoredb" not in options or not options["ignoredb"]): + trace("The database %s already exists, skipping" % dbName) + else: + makeDatabase(con, options, dbName, dbOwnerRole, dbInfo, dbRoles) + for name in dbRoles: + userInfo = dbRoles[name] + if name in currentRolenames and ("ignoredb" not in options or not options["ignoredb"]): + trace("The role %s already exists, skipping grants" % name) + else: + modifyGrants(con, options, dbName, name, userInfo) + +def makeDatabase(con, options, dbName, dbOwnerRole, dbInfo, dbRoles): + """ + Execute the SQL to create a database + + TODO: verify grants against what is actually there + """ + ownerRole = dbInfo["ownerRole"] + userRole = "{0}_common_user_role".format(dbName) + viewerRole = "{0}_common_viewer_role".format(dbName) + + optionalDbExecute(con, options, "CREATE ROLE {0}".format(userRole)) + optionalDbExecute(con, options, "CREATE ROLE {0}".format(viewerRole)) + + trace("Creating database %s with owner '%s'" % (dbName, ownerRole)) + optionalDbExecute(con, options, "CREATE DATABASE %s WITH OWNER %s" % (dbName, ownerRole)) + con2 = None + try: + con2 = dbConnect(database = dbName, user = options["dbuser"], password = options["dbpassword"], host = options["dbhost"]) + + optionalDbExecute(con2, options, "REVOKE ALL on DATABASE {0} FROM {1}".format(dbName, viewerRole)) + optionalDbExecute(con2, options, "REVOKE ALL on DATABASE {0} FROM {1}".format(dbName, userRole)) + for name in dbRoles: + userInfo = dbRoles[name] + if userInfo["role"] == "writer" or userInfo["role"] == "reader": + optionalDbExecute(con2, options, "REVOKE ALL on DATABASE {0} FROM {1}".format(dbName, name)) + + # user can do everything viewer can + optionalDbExecute(con2, options, "GRANT {0} TO {1}".format(viewerRole, userRole)) + # admin can do everything user and viewer can + optionalDbExecute(con2, options, "GRANT {0} TO {1}".format(userRole, ownerRole)) + + # viewer, user, admin can connect + optionalDbExecute(con2, options, "GRANT CONNECT ON DATABASE {0} TO {1}".format(dbName, viewerRole)) + + # create a schema we can optionally use * + schemaName = "{0}_db_common".format(dbName) + optionalDbExecute(con2, options, "CREATE SCHEMA if not exists {0} AUTHORIZATION {1}".format(schemaName, ownerRole)) + + # search_path is not inherited, so set it here + for role in [ ownerRole, userRole, viewerRole ]: + optionalDbExecute(con2, options, "ALTER ROLE {1} IN DATABASE {0} SET search_path = public, {2}".format(dbName, role, schemaName)) + + # viewer,user can select from schema + optionalDbExecute(con2, options, "GRANT USAGE ON SCHEMA {0} TO {1}".format(schemaName, viewerRole)) + # admin can create on schema + optionalDbExecute(con2, options, "GRANT CREATE ON SCHEMA {0} TO {1}".format(schemaName, ownerRole)) + + # viewer, user, admin can select on tables + optionalDbExecute(con2, options, "ALTER DEFAULT PRIVILEGES FOR ROLE {1} GRANT SELECT ON TABLES TO {0}".format(viewerRole, ownerRole)) + # user, admin can ins/upd/del/tru on tables + optionalDbExecute(con2, options, "ALTER DEFAULT PRIVILEGES FOR ROLE {1} GRANT INSERT, UPDATE, DELETE, TRUNCATE ON TABLES TO {0}".format(userRole, ownerRole)) + # user, admin can update on sequences + optionalDbExecute(con2, options, "ALTER DEFAULT PRIVILEGES FOR ROLE {1} GRANT USAGE, SELECT, UPDATE ON SEQUENCES TO {0}".format(userRole, ownerRole)) + + # user, admin can create temp tables + optionalDbExecute(con2, options, "GRANT TEMP ON DATABASE {0} TO {1}".format(dbName, userRole)) + + for name in dbRoles: + userInfo = dbRoles[name] + if userInfo["role"] == "writer": + optionalDbExecute(con2, options, "GRANT {0} TO {1}".format(userRole, name)) + elif userInfo["role"] == "reader": + optionalDbExecute(con2, options, "GRANT {0} TO {1}".format(viewerRole, name)) + + # search_path is not inherited, so set it here + optionalDbExecute(con2, options, "ALTER ROLE {1} IN DATABASE {0} SET search_path = public, {2}".format(dbName, name, schemaName)) + + except psycopg2.DatabaseError as e: + die('Error %s' % e) + + finally: + if con2: + con2.commit() + con2.close() + +def checkUsername(userName): + """ + A value of type name is a string of 63 or fewer characters1. A name must start + with a letter or an underscore; the rest of the string can contain letters, + digits, and underscores. + """ + trace("checkUsername(%s)" % userName) + if re.match("[A-Za-z_][A-Za-z0-9_]*$", userName): + return True + else: + errorPrint("%s is not a valid userName" % userName) + return False + +def setupUser(con, options, dbName, userName, userInfo): + """ + Do what is needed to to set up a user for a database + """ + if checkUsername(userName): + trace("For dbName='%s', create user '%s'" % (dbName, userName)) + userPassword = userInfo["password"] + optionalDbExecute(con, options, "create user %s with password '%s'" % (userName, userPassword)) + +def updatePassword(con, options, dbName, userName, userInfo): + """ + Do what is needed to update a user's password + """ + if checkUsername(userName): + trace("For dbName='%s', alter user '%s' password" % (dbName, userName)) + userPassword = userInfo["password"] + optionalDbExecute(con, options, "alter user %s with password '%s'" % (userName, userPassword)) + +def modifyGrants(con, options, dbName, userName, userInfo): + """ + Do what is needed to to set up a user for a database with the proper grants + + TODO: if user exist, verify current grants + """ + if checkUsername(userName): + userRole = userInfo["role"] + trace("For dbName='%s', set up user '%s' as a '%s'" % (dbName, userName, userRole)) + if userRole == "writer": + optionalDbExecute(con, options, "grant %s_common_user_role to %s" % (dbName, userName)) + elif userRole == "reader": + optionalDbExecute(con, options, "grant %s_common_viewer_role to %s" % (dbName, userName)) + # elif userRole == "admin": + # optionalDbExecute(con, options, "grant %s_common_admin_role to %s" % (dbName, userName)) + else: + trace("nothing to grant %s" % userName) + +def optionalDbExecute(con, options, cmd): + if "nocreate" in options and options["nocreate"]: + print(cmd) + else: + audit("Running: " + cmd) + dbExecute(con, cmd) + +""" +database utility functions +""" + +# def dbGetMap(con, cmd, args=[], skipTrace=False): +# def dbGetOneRowMap(con, cmd, args=[], skipTrace=False): + +def dbGetFirstRowOneValue(con, cmd, args=[], skipTrace=False): + """ + Do a select and return a single value from the first row + """ + row = dbGetFirstRow(con, cmd, args, skipTrace) + trace("row=" + str(row)) + if row is not None and len(row) > 0: + return row[0] + return None + +def dbGetFirstRow(con, cmd, args=[], skipTrace=False): + """ + Do a select and return the values from the first row + """ + cursor = dbExecute(con, cmd, args, skipTrace) + return cursor.fetchone() + +def dbGetFirstColumn(con, cmd, args=[], skipTrace=False): + """ + Do a select and return the first column's value from each row + """ + ret = [] + cursor = dbExecute(con, cmd, args, skipTrace) + for row in cursor: + for col in row: + ret.append(col) + break + return ret + +def dbGetFirstColumnAsMap(con, cmd, args=[], skipTrace=False, val=1): + """ + Do a select and return the first column's value from each row + """ + ret = {} + cursor = dbExecute(con, cmd, args, skipTrace) + for row in cursor: + for col in row: + ret[col] = val + break + return ret + +def dumpTable(con, tableName, max=-1): + """ + If being extra verbose, print out the entire table + """ + if verbose < 2: + return + print("================ " + tableName + " ================", file=traceOutput) + + cols = dbGetFirstColumn(con, "select column_name from information_schema.columns where table_name='" + tableName + "'", skipTrace=True) + print("num", end="|", file=traceOutput) + for col in cols: + print(col, end="|", file=traceOutput) + print("", file=traceOutput) + + if max > -1: + cursor = dbExecute(con, "select * from " + tableName + " limit " + str(max), skipTrace=True) + else: + cursor = dbExecute(con, "select * from " + tableName, skipTrace=True) + i = 0 + for row in cursor: + print("%d" % i, end="|", file=traceOutput) + i += 1 + for col in row: + print("%s" % (col), end="|", file=traceOutput) + print("", file=traceOutput) + print("================================================", file=traceOutput) + +def dbExecute(con, statement, args=[], skipTrace=False): + """ + Create a cursor, instantiate the arguments into a statement, trace print the statement, and execute the statement. + Return the cursor + """ + cursor = con.cursor() + stmt = cursor.mogrify(statement, args); + if not skipTrace: + trace("executing:" + str(stmt)) + cursor.execute(stmt) + global quiet + if not skipTrace: + trace("statusmessage=" + cursor.statusmessage + ", rowcount=" + str(cursor.rowcount)) + return cursor + +def dbConnect(database, user, password, host, autocommit = True): + """ + Create a connection, logging it in the process + Return the connection + """ + trace("connecting to database %s as %s on host %s" % (database, user, host)) + con =psycopg2.connect(database = database, user = user, password = password, host = host) + con.autocommit = autocommit + return con + +""" +Utility functions +""" + +def die(msg): + """ + Print a message to the error file and exit. + """ + errorPrint(msg) + sys.exit(1) + +def errorPrint(msg, file=errorOutput): + """ + Print a message to the error file. + """ + global errorLogger + # print("----------------> errorLogger=%s" % str(errorLogger)) + if errorLogger is not None: + errorLogger.error(msg) + else: + taggedPrint("ERROR", msg, file=file) + + +def tracePrint(msg, file=traceOutput): + """ + Print a message to the trace file. + """ + global debugLogger + # print("----------------> debugLogger=%s" % str(debugLogger)) + if debugLogger is not None: + debugLogger.debug(msg) + else: + taggedPrint("DEBUG", msg, file=file) + +def taggedPrint(tag, msg, file): + """ + Print a message to the trace file. + """ + dt = time.strftime('%Y-%m-%d %T', time.localtime()) + print("%s %s: %s" % (dt, tag, msg), file=file) + +def requireOption(nm, val): + """ + Die if a program parameter is not set + """ + return require("option", nm, val) + +def requireJSON(prnm, dict, nm): + """ + Die if a JSON value is not set + """ + if nm not in dict: + die("The JSON value '%s' is missing" % prnm) + return dict[nm] + +def require(type, nm, val): + """ + Die if a value is not set + """ + if val is None: + die("The %s '%s' is missing" % (type, nm)) + return val + +def trace(msg, minLevel=1): + """ + Print a message to trace output if verbose is turned on. + """ + global verbose + if verbose >= minLevel: + tracePrint(msg) + +def audit(msg): + """ + Print a message to audit log if one is being used + """ + global auditLogger + if auditLogger is not None: + auditLogger.info(msg) + +def getCdfPropValue(nm, encrypted=False, cfg="/opt/app/cdf/lib/cdf.cfg", dflt=None, skipComplaining=False): + """ + Return a value from the configuration file /opt/app/cdf/lib/cdf.cfg + """ + return getPropValue(nm=nm, encrypted=encrypted, cfg=cfg, dflt=dflt, skipComplaining=skipComplaining) + +def getPgaasPropValue(nm, encrypted=False, cfg="/opt/app/pgaas/lib/pgaas.cfg", dflt=None, skipComplaining=False): + """ + Return a value from the configuration file /opt/app/pgaas/lib/pgaas.cfg + """ + return getPropValue(nm=nm, encrypted=encrypted, cfg=cfg, dflt=dflt, skipComplaining=skipComplaining) + +getPropDict = { } + +def getPropValue(nm, encrypted=False, cfg=None, dflt=None, skipComplaining=False): + """ + Return a value from the specified configuration file + """ + if cfg is None: + return None + global getPropDict + if getPropDict.get(cfg): + savedDate = getPropDict[cfg] + # trace("getPropValue: savedDate[" + cfg + "]=" + str(savedDate)) + cfgDate = os.path.getmtime(cfg) + # trace("getPropValue: cfgDate=" + str(cfgDate)) + if float(savedDate) >= float(cfgDate): # cfg has not changed + val = getPropDict.get(cfg + ":" + nm) + # trace("getPropValue: val=" + val) + if val is not None: + # trace("getPropValue: getPropValue(saved) => '%s'" % str(val)) + return val + else: # clear out any previously saved keys + cfgcolon = cfg + ":" + for k in list(getPropDict.keys()): + if re.match(cfgcolon, k): + del getPropDict[k] + getPropValueProgram = '/opt/app/cdf/bin/getpropvalue' + if encrypted: + cmd = [getPropValueProgram, "-f", cfg, "-x", "-n", nm] + else: + cmd = [getPropValueProgram, "-f", cfg, "-n", nm] + # trace("getPgaasPropValue: cmd=" + str(cmd)) + + try: + with subprocess.Popen(cmd,shell=False,stdout=subprocess.PIPE,stderr=subprocess.PIPE) as p: + (origString, stderrString) = p.communicate() + except Exception as e: + traceback.print_exc() + print("Error decoding string because {0}".format(e), file=errorOutput) + return None + else: + if stderrString: + if not re.search("Configuration property .* must be defined", stderrString.decode('utf-8')) and not skipComplaining: + print("Error decoding string because: {0} ".format(stderr), file=errorOutput) + return dflt + else: + trace("getPgaasPropValue() => " + str(origString), minLevel=2) + return origString.decode('utf-8').rstrip('\n') + +if __name__ == "__main__": + main() diff --git a/pgaas/src/stage/opt/app/pgaas/bin/in.json b/pgaas/src/stage/opt/app/pgaas/bin/in.json new file mode 100755 index 0000000..cad8790 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/in.json @@ -0,0 +1,97 @@ +{ + # sample configuration file for dcae_admin_db + "vmConfiguration": { + "$class": "org.openecomp.dcae.controller.service.storage.postgres.service.PostgresServiceConfiguration", + "state": "master", + "databases": { + "odcit": { + "created": "2016-05-10T01:52:39.431+0000", + "description": "A&AI DCAE Central Inventory", + "ownerRole": "odcit_admin", + "contacts": {"ws4361": { + "created": "2016-05-10T01:52:39.431+0000", + "fullName": "Wen Shang" + }}, + "roles": { + "odcit_admin": { + "created": "2016-05-10T01:52:39.431+0000", + "password": "odcit123", + "role": "admin", + "roleComments": [] + }, + "odcit_user": { + "created": "2016-05-10T01:52:39.431+0000", + "password": "odcit123", + "role": "writer", + "roleComments": [] + }, + "odcit_viewer": { + "created": "2016-05-10T01:52:39.431+0000", + "password": "odcit123", + "role": "reader", + "roleComments": [] + } + } + }, + "dmaap": { + "created": "2016-05-10T01:52:39.431+0000", + "description": "DMAAP Databus Configuration", + "ownerRole": "dmaap_admin", + "contacts": {"dl715d": { + "created": "2016-05-10T01:52:39.431+0000", + "fullName": "Dominic Lunanuova" + }}, + "roles": { + "dmaap_admin": { + "created": "2016-05-10T01:52:39.431+0000", + "password": "dmaap123", + "role": "admin", + "roleComments": [] + }, + "dmaap_user": { + "created": "2016-05-10T01:52:39.431+0000", + "password": "dmaap123", + "role": "writer", + "roleComments": [] + }, + "dmaap_viewer": { + "created": "2016-05-10T01:52:39.431+0000", + "password": "dmaap123", + "role": "reader", + "roleComments": [] + } + } + }, + "dcae_inv": { + "created": "2016-05-10T01:52:39.431+0000", + "description": "Running DCAE Services", + "ownerRole": "dcae_inv_admin", + "contacts": { + "mh677g": { + "created": "2016-05-10T01:52:39.431+0000", + "fullName": "Michael Hwang" + }}, + "roles": { + "dcae_inv_admin": { + "created": "2016-05-10T01:52:39.431+0000", + "password": "dcae_inv123", + "role": "admin", + "roleComments": [] + }, + "dcae_inv_user": { + "created": "2016-05-10T01:52:39.431+0000", + "password": "dcae_inv123", + "role": "writer", + "roleComments": [] + }, + "dcae_inv_viewer": { + "created": "2016-05-10T01:52:39.431+0000", + "password": "dcae_inv123", + "role": "reader", + "roleComments": [] + } + } + } + } + } +}
\ No newline at end of file diff --git a/pgaas/src/stage/opt/app/pgaas/bin/isrw b/pgaas/src/stage/opt/app/pgaas/bin/isrw new file mode 100755 index 0000000..4ec3dcb --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/isrw @@ -0,0 +1,28 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +if [ -d /usr/lib/postgresql/9.5/bin ] +then PATH=$PATH:/usr/lib/postgresql/9.5/bin +elif [ -d /opt/app/postgresql-9.5.2/bin ] +then PATH=$PATH:/opt/app/postgresql-9.5.2/bin +else echo "$0: Cannot find PostgreSQL bin" 1>&2; exit 1 +fi + +export PATH=$PATH:/opt/java/jdk/jdk170/bin:/opt/app/cdf/bin:/opt/app/pgaas/bin:$PATH + +case `show_pg_is_in_recovery` in + *f* ) echo "Master" ;; + *t* ) echo "Secondary" ;; +esac diff --git a/pgaas/src/stage/opt/app/pgaas/bin/list_masters b/pgaas/src/stage/opt/app/pgaas/bin/list_masters new file mode 100755 index 0000000..d922739 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/list_masters @@ -0,0 +1,43 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +# NAME +# list_masters - loop through the nodes in the cluster, using pgwget to determine if any are a master. + +CDF=/opt/app/cdf +if [ -d /opt/app/postgresql-9.5.2 ] +then PGDIR=/opt/app/postgresql-9.5.2 +else PGDIR=/usr/lib/postgresql/9.5 +fi +if [ -d /opt/app/postgresql-config-9.5.2/ ] +then CFGDIR=/opt/app/postgresql-config-9.5.2/ +else CFGDIR=/opt/app/postgresql-config/ +fi +PATH=$PGDIR/bin:$CDF/bin:/opt/app/pgaas/bin:/opt/app/postgresql-prep/bin:$PATH + +# loop through the nodes in the cluster, using pgwget to determine if any are a master. Save in $@ +for i in $(getpropvalue -n pgnodes | sed 's/|/ /g') +do + if pgwget --quiet -O/dev/null http://$i:8000/rw + then set -- "$@" $i + fi +done + +echo "$@" +case $# in + 1 ) exit 0 ;; # one master exists and is running + 0 ) exit 1 ;; # no masters exist + * ) exit 2 ;; # more than one master exist +esac diff --git a/pgaas/src/stage/opt/app/pgaas/bin/makefile b/pgaas/src/stage/opt/app/pgaas/bin/makefile new file mode 100644 index 0000000..877f8ba --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/makefile @@ -0,0 +1,47 @@ +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +all: + +test: + sudo -u postgres ./dcae_admin_db.py configurationChanged in.json + +STAGEDIR=/dev/null +DISTPATH=/opt/app/pgaas + +PYFILES= dcae_admin_db.py +SHFILES= check_cluster isrw list_masters \ + pg_ctl_promote pg_ctl_restart pg_ctl_start pg_ctl_status pg_ctl_stop repmgrc repmgrdc \ + runpsql runpsqll startpsql setpropvalue show_pg_is_in_recovery show_pg_stat_activity show_pg_stat_archiver show_pg_stat_bgwriter \ + show_pg_stat_database show_pg_stat_database_conflicts show_pg_statio_user_functions show_pg_statio_user_indexes \ + show_pg_statio_user_sequences show_pg_statio_user_tables show_pg_stat_user_indexes show_pg_stat_user_tables \ + update_var_run_isrw + +stage: + rm -rf $(STAGEDIR)/$(DISTPATH)/bin + mkdir -p $(STAGEDIR)/$(DISTPATH)/bin + for i in *; do \ + case $$i in \ + *.py ) \ + j=`basename $$i .py`; \ + cp $$i $(STAGEDIR)/$(DISTPATH)/bin/$$j; \ + chmod a+x $(STAGEDIR)/$(DISTPATH)/bin/$$j; \ + ;; \ + makefile | *~ ) ;; \ + * ) \ + cp $$i $(STAGEDIR)/$(DISTPATH)/bin/$$i; \ + chmod a+x $(STAGEDIR)/$(DISTPATH)/bin/$$i; \ + ;; \ + esac; \ + done diff --git a/pgaas/src/stage/opt/app/pgaas/bin/pg_ctl_promote b/pgaas/src/stage/opt/app/pgaas/bin/pg_ctl_promote new file mode 100755 index 0000000..b7d011c --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/pg_ctl_promote @@ -0,0 +1,23 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +if [ -d /usr/lib/postgresql/9.5/bin ] +then PATH=$PATH:/usr/lib/postgresql/9.5/bin +elif [ -d /opt/app/postgresql-9.5.2/bin ] +then PATH=$PATH:/opt/app/postgresql-9.5.2/bin +else echo "$0: Cannot find PostgreSQL bin" 1>&2; exit 1 +fi + +pg_ctl promote -D /dbroot/pgdata/main/ diff --git a/pgaas/src/stage/opt/app/pgaas/bin/pg_ctl_restart b/pgaas/src/stage/opt/app/pgaas/bin/pg_ctl_restart new file mode 100755 index 0000000..db00739 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/pg_ctl_restart @@ -0,0 +1,41 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +if [ -d /usr/lib/postgresql/9.5/bin ] +then PATH=$PATH:/usr/lib/postgresql/9.5/bin +elif [ -d /opt/app/postgresql-9.5.2/bin ] +then PATH=$PATH:/opt/app/postgresql-9.5.2/bin +else echo "$0: Cannot find PostgreSQL bin" 1>&2; exit 1 +fi + +if [ -f /opt/app/postgresql-config/main/postgresql.conf ] +then CONF=/opt/app/postgresql-config/main/postgresql.conf +elif [ -f /opt/app/postgresql-config-9.5.2/main/postgresql.conf ] +then CONF=/opt/app/postgresql-config-9.5.2/main/postgresql.conf +else echo "$0: Cannot find PostgreSQL configuration" 1>&2; exit 1 +fi + +pg_ctl stop -D /dbroot/pgdata/main/ +echo Restarting in 5 +sleep 1 +echo Restarting in 4 +sleep 1 +echo Restarting in 3 +sleep 1 +echo Restarting in 2 +sleep 1 +echo Restarting in 1 +sleep 1 +pg_ctl start -D /dbroot/pgdata/main/ -o "-c config_file=$CONF" diff --git a/pgaas/src/stage/opt/app/pgaas/bin/pg_ctl_start b/pgaas/src/stage/opt/app/pgaas/bin/pg_ctl_start new file mode 100755 index 0000000..8cb831c --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/pg_ctl_start @@ -0,0 +1,30 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +if [ -d /usr/lib/postgresql/9.5/bin ] +then PATH=$PATH:/usr/lib/postgresql/9.5/bin +elif [ -d /opt/app/postgresql-9.5.2/bin ] +then PATH=$PATH:/opt/app/postgresql-9.5.2/bin +else echo "$0: Cannot find PostgreSQL bin" 1>&2; exit 1 +fi + +if [ -f /opt/app/postgresql-config/main/postgresql.conf ] +then CONF=/opt/app/postgresql-config/main/postgresql.conf +elif [ -f /opt/app/postgresql-config-9.5.2/main/postgresql.conf ] +then CONF=/opt/app/postgresql-config-9.5.2/main/postgresql.conf +else echo "$0: Cannot find PostgreSQL configuration" 1>&2; exit 1 +fi + +pg_ctl start -D /dbroot/pgdata/main/ -o "-c config_file=$CONF" diff --git a/pgaas/src/stage/opt/app/pgaas/bin/pg_ctl_status b/pgaas/src/stage/opt/app/pgaas/bin/pg_ctl_status new file mode 100755 index 0000000..416a00e --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/pg_ctl_status @@ -0,0 +1,23 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +if [ -d /usr/lib/postgresql/9.5/bin ] +then PATH=$PATH:/usr/lib/postgresql/9.5/bin +elif [ -d /opt/app/postgresql-9.5.2/bin ] +then PATH=$PATH:/opt/app/postgresql-9.5.2/bin +else echo "$0: Cannot find PostgreSQL bin" 1>&2; exit 1 +fi + +pg_ctl status -D /dbroot/pgdata/main/ diff --git a/pgaas/src/stage/opt/app/pgaas/bin/pg_ctl_stop b/pgaas/src/stage/opt/app/pgaas/bin/pg_ctl_stop new file mode 100755 index 0000000..0d9a23c --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/pg_ctl_stop @@ -0,0 +1,23 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +if [ -d /usr/lib/postgresql/9.5/bin ] +then PATH=$PATH:/usr/lib/postgresql/9.5/bin +elif [ -d /opt/app/postgresql-9.5.2/bin ] +then PATH=$PATH:/opt/app/postgresql-9.5.2/bin +else echo "$0: Cannot find PostgreSQL bin" 1>&2; exit 1 +fi + +pg_ctl stop -D /dbroot/pgdata/main/ diff --git a/pgaas/src/stage/opt/app/pgaas/bin/repmgrc b/pgaas/src/stage/opt/app/pgaas/bin/repmgrc new file mode 100644 index 0000000..57240cf --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/repmgrc @@ -0,0 +1,29 @@ +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +if [ -d /usr/lib/postgresql/9.5/bin ] +then PATH=$PATH:/usr/lib/postgresql/9.5/bin +elif [ -d /opt/app/postgresql-9.5.2/bin ] +then PATH=$PATH:/opt/app/postgresql-9.5.2/bin +else echo "$0: Cannot find PostgreSQL bin" 1>&2; exit 1 +fi + +if [ -f /opt/app/postgresql-config/main/repmgr.conf ] +then CONF=/opt/app/postgresql-config/main/repmgr.conf +elif [ -f /opt/app/postgresql-config-9.5.2/main/repmgr.conf ] +then CONF=/opt/app/postgresql-config-9.5.2/main/repmgr.conf +else echo "$0: Cannot find repmgr configuration" 1>&2; exit 1 +fi + +repmgr -f $CONF "$@" diff --git a/pgaas/src/stage/opt/app/pgaas/bin/repmgrdc b/pgaas/src/stage/opt/app/pgaas/bin/repmgrdc new file mode 100644 index 0000000..cfbaa22 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/repmgrdc @@ -0,0 +1,29 @@ +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +if [ -d /usr/lib/postgresql/9.5/bin ] +then PATH=$PATH:/usr/lib/postgresql/9.5/bin +elif [ -d /opt/app/postgresql-9.5.2/bin ] +then PATH=$PATH:/opt/app/postgresql-9.5.2/bin +else echo "$0: Cannot find PostgreSQL bin" 1>&2; exit 1 +fi + +if [ -f /opt/app/postgresql-config/main/repmgr.conf ] +then CONF=/opt/app/postgresql-config/main/repmgr.conf +elif [ -f /opt/app/postgresql-config-9.5.2/main/repmgr.conf ] +then CONF=/opt/app/postgresql-config-9.5.2/main/repmgr.conf +else echo "$0: Cannot find repmgr configuration" 1>&2; exit 1 +fi + +repmgrd -f $CONF "$@" diff --git a/pgaas/src/stage/opt/app/pgaas/bin/runpsql b/pgaas/src/stage/opt/app/pgaas/bin/runpsql new file mode 100755 index 0000000..be7f705 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/runpsql @@ -0,0 +1,30 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +if [ -d /usr/lib/postgresql/9.5/bin ] +then PATH=$PATH:/usr/lib/postgresql/9.5/bin +elif [ -d /opt/app/postgresql-9.5.2/bin ] +then PATH=$PATH:/opt/app/postgresql-9.5.2/bin +else echo "$0: Cannot find PostgreSQL bin" 1>&2; exit 1 +fi + +export PATH=$PATH:/opt/java/jdk/jdk170/bin:/opt/app/cdf/bin:/opt/app/pgaas/bin + +[ -z "$PGUSER" ] && PGUSER=postgres +[ -z "$PGHOST" ] && PGHOST=`hostname -f` +[ -z "$PGDBNM" ] && PGDBNM=postgres +echo "$@;" | +psql --host=$PGHOST --username=$PGUSER --dbname=$PGDBNM + diff --git a/pgaas/src/stage/opt/app/pgaas/bin/runpsqll b/pgaas/src/stage/opt/app/pgaas/bin/runpsqll new file mode 100755 index 0000000..749ae5d --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/runpsqll @@ -0,0 +1,30 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +if [ -d /usr/lib/postgresql/9.5/bin ] +then PATH=$PATH:/usr/lib/postgresql/9.5/bin +elif [ -d /opt/app/postgresql-9.5.2/bin ] +then PATH=$PATH:/opt/app/postgresql-9.5.2/bin +else echo "$0: Cannot find PostgreSQL bin" 1>&2; exit 1 +fi + +export PATH=$PATH:/opt/java/jdk/jdk170/bin:/opt/app/cdf/bin:/opt/app/pgaas/bin + +[ -z "$PGUSER" ] && PGUSER=postgres +[ -z "$PGHOST" ] && PGHOST=`hostname -f` +[ -z "$PGDBNM" ] && PGDBNM=postgres +echo "$@;" | +psql --tuples-only --host=$PGHOST --username=$PGUSER --dbname=$PGDBNM + diff --git a/pgaas/src/stage/opt/app/pgaas/bin/setpropvalue b/pgaas/src/stage/opt/app/pgaas/bin/setpropvalue new file mode 100755 index 0000000..2b45fa8 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/setpropvalue @@ -0,0 +1,67 @@ +#!/bin/bash + +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +die() +{ + exec 1>&2 + echo "$@" + exit 1 +} + +usage() +{ + exec 1>&2 + [ $# -gt 0 ] && echo "$@" + echo "Usage: $0 -n name -v value [-x]" + echo " -n\tname to configure" + echo " -v\tvalue to set" + echo " -x\tencrypt the value" + exit 1 +} + +NAME= +VAL= +ENCRYPT=false +FILE=/opt/app/pgaas/lib/pgaas.cfg + +while getopts f:n:v:x c +do + case "$c" in + f ) FILE=$OPTARG ;; + n ) NAME=$OPTARG ;; + v ) VAL=$OPTARG ;; + x ) ENCRYPT=true ;; + \?) usage ;; + esac +done +shift $(($OPTIND - 1)) + +[ -n "$NAME" ] || die "-n name is required" +[ -n "$VAL" ] || die "-v value is required" +[ -f "$FILE" -a -w "$FILE" ] || die "-f file must exist and be writable" + +ed $FILE <<-! + H + g/^$NAME[=]/d + g/^$NAME[.]x=/d + w + q +! + +if $ENCRYPT +then /opt/app/cdf/bin/getpropvalue -e AES -n $NAME -v $VAL >> $FILE +else echo "$NAME='$VAL'" >> $FILE +fi diff --git a/pgaas/src/stage/opt/app/pgaas/bin/show_pg_is_in_recovery b/pgaas/src/stage/opt/app/pgaas/bin/show_pg_is_in_recovery new file mode 100755 index 0000000..b26904d --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/show_pg_is_in_recovery @@ -0,0 +1,19 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +export PATH=/opt/app/pgaas/bin:$PATH + +runpsqll "select * from pg_is_in_recovery()" + diff --git a/pgaas/src/stage/opt/app/pgaas/bin/show_pg_stat_activity b/pgaas/src/stage/opt/app/pgaas/bin/show_pg_stat_activity new file mode 100755 index 0000000..d9f43c8 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/show_pg_stat_activity @@ -0,0 +1,19 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +export PATH=/opt/app/pgaas/bin:$PATH + +runpsql "select * from pg_stat_activity" + diff --git a/pgaas/src/stage/opt/app/pgaas/bin/show_pg_stat_archiver b/pgaas/src/stage/opt/app/pgaas/bin/show_pg_stat_archiver new file mode 100755 index 0000000..fac0bdb --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/show_pg_stat_archiver @@ -0,0 +1,19 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +export PATH=/opt/app/pgaas/bin:$PATH + +runpsql "select * from pg_stat_archiver" + diff --git a/pgaas/src/stage/opt/app/pgaas/bin/show_pg_stat_bgwriter b/pgaas/src/stage/opt/app/pgaas/bin/show_pg_stat_bgwriter new file mode 100755 index 0000000..cf6d01a --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/show_pg_stat_bgwriter @@ -0,0 +1,19 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +export PATH=/opt/app/pgaas/bin:$PATH + +runpsql "select * from pg_stat_bgwriter" + diff --git a/pgaas/src/stage/opt/app/pgaas/bin/show_pg_stat_database b/pgaas/src/stage/opt/app/pgaas/bin/show_pg_stat_database new file mode 100755 index 0000000..c74316e --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/show_pg_stat_database @@ -0,0 +1,19 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +export PATH=/opt/app/pgaas/bin:$PATH + +runpsql "select * from pg_stat_database" + diff --git a/pgaas/src/stage/opt/app/pgaas/bin/show_pg_stat_database_conflicts b/pgaas/src/stage/opt/app/pgaas/bin/show_pg_stat_database_conflicts new file mode 100755 index 0000000..73d47bd --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/show_pg_stat_database_conflicts @@ -0,0 +1,19 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +export PATH=/opt/app/pgaas/bin:$PATH + +runpsql "select * from pg_stat_database_conflicts" + diff --git a/pgaas/src/stage/opt/app/pgaas/bin/show_pg_stat_user_indexes b/pgaas/src/stage/opt/app/pgaas/bin/show_pg_stat_user_indexes new file mode 100755 index 0000000..9ff29d9 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/show_pg_stat_user_indexes @@ -0,0 +1,19 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +export PATH=/opt/app/pgaas/bin:$PATH + +runpsql "select * from pg_stat_user_indexes" + diff --git a/pgaas/src/stage/opt/app/pgaas/bin/show_pg_stat_user_tables b/pgaas/src/stage/opt/app/pgaas/bin/show_pg_stat_user_tables new file mode 100755 index 0000000..5eb1393 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/show_pg_stat_user_tables @@ -0,0 +1,19 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +export PATH=/opt/app/pgaas/bin:$PATH + +runpsql "select * from pg_stat_user_tables" + diff --git a/pgaas/src/stage/opt/app/pgaas/bin/show_pg_statio_user_functions b/pgaas/src/stage/opt/app/pgaas/bin/show_pg_statio_user_functions new file mode 100755 index 0000000..dfaf570 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/show_pg_statio_user_functions @@ -0,0 +1,19 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +export PATH=/opt/app/pgaas/bin:$PATH + +runpsql "select * from pg_statio_user_functions" + diff --git a/pgaas/src/stage/opt/app/pgaas/bin/show_pg_statio_user_indexes b/pgaas/src/stage/opt/app/pgaas/bin/show_pg_statio_user_indexes new file mode 100755 index 0000000..6ec3043 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/show_pg_statio_user_indexes @@ -0,0 +1,19 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +export PATH=/opt/app/pgaas/bin:$PATH + +runpsql "select * from pg_statio_user_indexes" + diff --git a/pgaas/src/stage/opt/app/pgaas/bin/show_pg_statio_user_sequences b/pgaas/src/stage/opt/app/pgaas/bin/show_pg_statio_user_sequences new file mode 100755 index 0000000..9d658e4 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/show_pg_statio_user_sequences @@ -0,0 +1,19 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +export PATH=/opt/app/pgaas/bin:$PATH + +runpsql "select * from pg_statio_user_sequences" + diff --git a/pgaas/src/stage/opt/app/pgaas/bin/show_pg_statio_user_tables b/pgaas/src/stage/opt/app/pgaas/bin/show_pg_statio_user_tables new file mode 100755 index 0000000..4017988 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/show_pg_statio_user_tables @@ -0,0 +1,19 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +export PATH=/opt/app/pgaas/bin:$PATH + +runpsql "select * from pg_statio_user_tables" + diff --git a/pgaas/src/stage/opt/app/pgaas/bin/startpsql b/pgaas/src/stage/opt/app/pgaas/bin/startpsql new file mode 100644 index 0000000..5368fc8 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/startpsql @@ -0,0 +1,29 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +if [ -d /usr/lib/postgresql/9.5/bin ] +then PATH=$PATH:/usr/lib/postgresql/9.5/bin +elif [ -d /opt/app/postgresql-9.5.2/bin ] +then PATH=$PATH:/opt/app/postgresql-9.5.2/bin +else echo "$0: Cannot find PostgreSQL bin" 1>&2; exit 1 +fi + +export PATH=$PATH:/opt/java/jdk/jdk170/bin:/opt/app/cdf/bin:/opt/app/pgaas/bin + +[ -z "$PGUSER" ] && PGUSER=postgres +[ -z "$PGHOST" ] && PGHOST=`hostname -f` +[ -z "$PGDBNM" ] && PGDBNM=postgres + +psql --host=$PGHOST --username=$PGUSER --dbname=$PGDBNM diff --git a/pgaas/src/stage/opt/app/pgaas/bin/update_var_run_isrw b/pgaas/src/stage/opt/app/pgaas/bin/update_var_run_isrw new file mode 100755 index 0000000..082c094 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/update_var_run_isrw @@ -0,0 +1,30 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +if [ -d /usr/lib/postgresql/9.5/bin ] +then PATH=$PATH:/usr/lib/postgresql/9.5/bin +elif [ -d /opt/app/postgresql-9.5.2/bin ] +then PATH=$PATH:/opt/app/postgresql-9.5.2/bin +else echo "$0: Cannot find PostgreSQL bin" 1>&2; exit 1 +fi + +export PATH=$PATH:/opt/java/jdk/jdk170/bin:/opt/app/cdf/bin:/opt/app/pgaas/bin + +for i in 1 2 3 4 5 6 +do + isrw > /var/run/postgresql/isrw.tmp 2>&1 && + mv /var/run/postgresql/isrw.tmp /var/run/postgresql/isrw + sleep 10 +done diff --git a/pgaas/src/stage/opt/app/pgaas/bin/verify_pg_privileges b/pgaas/src/stage/opt/app/pgaas/bin/verify_pg_privileges new file mode 100755 index 0000000..628b63d --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/bin/verify_pg_privileges @@ -0,0 +1,188 @@ +#!/bin/bash +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +defdbname="test" +defprefix="tst" +dbname="$defdbname" +prefix="$defprefix" + +usage() +{ + exec 1>&2 + [ -n $# ] && echo " $@" + echo "Usage: $0 -A pswd -U pswd -V pswd [-d dbname] [-p prefix] [-P] [-v]" + echo " -d dbname - database name, defaults to '$defdbname'" + echo " -p prefix - prefix of usernames, defaults to '$defprefix'" + echo " -A pswd - password for admin role" + echo " -U pswd - password for user role" + echo " -V pswd - password for viewer role" + echo " -v verbose" + echo " -P do not print VERIFIED" + exit 1 +} + +PRINTVERIFIED=: +VERBOSE=false +PSWDA= +PSWDU= +PSWDV= +while getopts A:d:p:PU:vV: c +do + case $c in + A ) PSWDA="$OPTARG" ;; + d ) dbname="$OPTARG" ;; + p ) prefix="$OPTARG" ;; + P ) PRINTVERIFIED=false ;; + U ) PSWDU="$OPTARG" ;; + v ) VERBOSE=: ;; + V ) PSWDV="$OPTARG" ;; + '?' ) usage ;; + esac +done +shift `expr $OPTIND - 1` + +[ -n "$PSWDA" ] || usage "-A is missing" +[ -n "$PSWDU" ] || usage "-U is missing" +[ -n "$PSWDV" ] || usage "-V is missing" + +admin="${prefix}_admin" +user="${prefix}_user" +viewer="${prefix}_viewer" + +TMP1=$(mktemp /tmp/vpp1.$$.XXXXXXXXXX) +TMP2=$(mktemp /tmp/vpp2.$$.XXXXXXXXXX) +trap 'rm -f $TMP1 $TMP2' 0 1 2 3 15 + +VERIFIEDCOUNT=0 +FAILEDCOUNT=0 +TOTALCOUNT=0 + +verified() +{ + (( VERIFIEDCOUNT = VERIFIEDCOUNT + 1 )) + (( TOTALCOUNT = TOTALCOUNT + 1 )) + $PRINTVERIFIED && echo "VERIFIED: $@" +} + +failed() +{ + (( FAILEDCOUNT = FAILEDCOUNT + 1 )) + (( TOTALCOUNT = TOTALCOUNT + 1 )) + echo "FAILED: $@" +} + +tabtext() +{ + echo "$@" | sed 's/^/ /' +} + +tabfile() +{ + sed 's/^/ /' "$@" +} + +runtests() +{ + name="$1" + pswd="$2" + while read cmd; read expected + do + echo "$cmd" | psql --host=localhost --dbname="$dbname" --username="$name" > $TMP1 2>&1 + if fgrep "$expected" $TMP1 > /dev/null + then verified "user $name executed $cmd, expected $expected" + $VERBOSE && echo -e "\tGot:" && tabfile "$TMP1" + else failed "user $name executed $cmd, expected $expected, got:"; tabfile $TMP1 + fi + done +} + +psql --host=localhost --dbname="$dbname" --username="$admin" <<EOF > /dev/null + drop table if exists foo; + drop table if exists foou; + drop table if exists fooud; + drop table if exists foouc; + drop table if exists foov; + drop table if exists foovd; + drop table if exists foovc; +EOF + +# tests to be run as admin user +cat <<-EOF > $TMP2 + create table foo ( fooint int ); /* table for admin to add and drop */ + CREATE TABLE + insert into foo (fooint) values (1); /* admin can add values */ + INSERT 0 1 + select count(*) from foo; /* admin can select */ + (1 row) + delete from foo where fooint = '1'; /* admin can delete */ + DELETE 1 + select * from foo; /* admin can select */ + (0 rows) + drop table foo; /* admin can drop */ + DROP TABLE + create table foou (fooint int ); /* table for user to add/delete to */ + CREATE TABLE + create table fooud (fooint int ); /* table for user to try dropping */ + CREATE TABLE + create table foov (fooint int ); /* table for viewer to try adding/deleting from */ + CREATE TABLE + create table foovd (fooint int ); /* table for viewer to try dropping */ + CREATE TABLE +EOF +runtests "$admin" "$PWDA" < $TMP2 + +# tests to be run as writer +cat <<-EOF > $TMP2 + create table foouc ( fooint int ); /* user cannot create a table */ + ERROR: + drop table fooud; /* user cannot drop a table */ + ERROR: + insert into foou (fooint) values (1); /* user can add values */ + INSERT 0 1 + select count(*) from foou; /* user can select values */ + (1 row) + insert into foou (fooint) values (2); /* user can add values */ + INSERT 0 1 + select * from foou; /* user can select values */ + (2 rows) + delete from foou where fooint = '2'; /* user can delete values */ + DELETE 1 + select * from foou; /* user can select values */ + (1 row) +EOF +runtests "$user" "$PWDU" < $TMP2 + +# tests to be run as read-only +cat <<-EOF > $TMP2 + create table foovc ( fooint int ); /* user cannot create a table */ + ERROR: + drop table foovd; /* user cannot drop a table */ + ERROR: + insert into foov (fooint) values (1); /* user can add values */ + ERROR: + select count(*) from foov; /* user can select values */ + (1 row) + insert into foov (fooint) values (2); /* user can add values */ + ERROR: + select * from foov; /* user can select values */ + (0 rows) + delete from foov where fooint = '2'; /* user can delete values */ + ERROR: + select * from foov; /* user can select values */ + (0 rows) +EOF +runtests "$viewer" "$PWDV" < $TMP2 + +echo "$VERIFIEDCOUNT tests passed, $FAILEDCOUNT tests failed, $TOTALCOUNT total tests run" diff --git a/pgaas/src/stage/opt/app/pgaas/etc/create_dcae_rotate.sql b/pgaas/src/stage/opt/app/pgaas/etc/create_dcae_rotate.sql new file mode 100644 index 0000000..2200362 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/etc/create_dcae_rotate.sql @@ -0,0 +1,21 @@ +/* + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this code 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. + +*/ +create table dcae_rotate ( + basetablename varchar(129) not null, /* the base table name to derive other tables from */ + columnname varchar(64) not null, /* which column name to use as the datestamp */ + count int, /* how many periods to keep around */ + period varchar(20) /* one of 'week', 'month' or 'day' */ +); diff --git a/pgaas/src/stage/opt/app/pgaas/etc/dcae_admin_db.cfg b/pgaas/src/stage/opt/app/pgaas/etc/dcae_admin_db.cfg new file mode 100644 index 0000000..139597f --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/etc/dcae_admin_db.cfg @@ -0,0 +1,2 @@ + + diff --git a/pgaas/src/stage/opt/app/pgaas/etc/makefile b/pgaas/src/stage/opt/app/pgaas/etc/makefile new file mode 100644 index 0000000..b997f14 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/etc/makefile @@ -0,0 +1,25 @@ +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +all: + +STAGEDIR=/dev/null +DISTPATH=/opt/app/pgaas + +CFGFILES= create_dcae_rotate.sql + +stage: + rm -rf $(STAGEDIR)/$(DISTPATH)/etc + mkdir -p $(STAGEDIR)/$(DISTPATH)/etc + cp $(CFGFILES) $(STAGEDIR)/$(DISTPATH)/etc diff --git a/pgaas/src/stage/opt/app/pgaas/lib/CommonLogger.py b/pgaas/src/stage/opt/app/pgaas/lib/CommonLogger.py new file mode 100644 index 0000000..d18fc7d --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/lib/CommonLogger.py @@ -0,0 +1,889 @@ +#!/usr/bin/python +# -*- indent-tabs-mode: nil -*- vi: set expandtab: +"""ECOMP Common Logging library in Python. + +CommonLogger.py + +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +Original Written by: Terry Schmalzried +Date written: October 1, 2015 +Last updated: December 1, 2016 + +version 0.8 +""" + +from __future__ import print_function +import os, sys, getopt, logging, logging.handlers, time, re, uuid, socket, threading + +class CommonLogger: + """ECOMP Common Logging object. + + Public methods: + __init__ + setFields + debug + info + warn + error + fatal + """ + + UnknownFile = -1 + ErrorFile = 0 + DebugFile = 1 + AuditFile = 2 + MetricsFile = 3 + DateFmt = '%Y-%m-%dT%H:%M:%S' + + def __init__(self, configFile, logKey, **kwargs): + """Construct a Common Logger for one Log File. + + Arguments: + configFile -- configuration filename. + logKey -- the keyword in configFile that identifies the log filename. + + Keyword arguments: Annotations are d:debug, a=audit, m=metrics, e=error + style -- the log file format (style) to use when writing log messages, + one of CommonLogger.ErrorFile, CommonLogger.DebugFile, + CommonLogger.AuditFile and CommonLogger.MetricsFile, or + one of the strings "error", "debug", "audit" or "metrics". + May also be set in the config file using a field named + <logKey>Style (where <logKey> is the value of the logKey + parameter). The keyword value overrides the value in the + config file. + requestID (dame) -- optional default value for this log record field. + serviceInstanceID (am) -- optional default value for this log record field. + threadID (am) -- optional default value for this log record field. + serverName (am) -- optional default value for this log record field. + serviceName (am) -- optional default value for this log record field. + instanceUUID (am) -- optional default value for this log record field. + severity (am) -- optional default value for this log record field. + serverIPAddress (am) -- optional default value for this log record field. + server (am) -- optional default value for this log record field. + IPAddress (am) -- optional default value for this log record field. + className (am) -- optional default value for this log record field. + timer (am) -- (ElapsedTime) optional default value for this log record field. + partnerName (ame) -- optional default value for this log record field. + targetEntity (me) -- optional default value for this log record field. + targetServiceName (me) -- optional default value for this log record field. + statusCode (am) -- optional default value for this log record field. + responseCode (am) -- optional default value for this log record field. + responseDescription (am) -- optional default value for this log record field. + processKey (am) -- optional default value for this log record field. + targetVirtualEntity (m) -- optional default value for this log record field. + customField1 (am) -- optional default value for this log record field. + customField2 (am) -- optional default value for this log record field. + customField3 (am) -- optional default value for this log record field. + customField4 (am) -- optional default value for this log record field. + errorCategory (e) -- optional default value for this log record field. + errorCode (e) -- optional default value for this log record field. + errorDescription (e) -- optional default value for this log record field. + + Note: the pipe '|' character is not allowed in any log record field. + """ + + self._monitorFlag = False + + # Get configuration parameters + self._logKey = str(logKey) + self._configFile = str(configFile) + self._rotateMethod = 'time' + self._timeRotateIntervalType = 'midnight' + self._timeRotateInterval = 1 + self._sizeMaxBytes = 0 + self._sizeRotateMode = 'a' + self._socketHost = None + self._socketPort = 0 + self._typeLogger = 'filelogger' + self._backupCount = 6 + self._logLevelThreshold = self._intLogLevel('') + self._logFile = None + self._begTime = None + self._begMsec = 0 + self._fields = {} + self._fields["style"] = CommonLogger.UnknownFile + try: + self._configFileModified = os.path.getmtime(self._configFile) + for line in open(self._configFile): + line = line.split('#',1)[0] # remove comments + if '=' in line: + key, value = [x.strip() for x in line.split('=',1)] + if key == 'rotateMethod' and value.lower() in ['time', 'size', 'none']: + self._rotateMethod = value.lower() + elif key == 'timeRotateIntervalType' and value in ['S', 'M', 'H', 'D', 'W0', 'W1', 'W2', 'W3', 'W4', 'W5', 'W6', 'midnight']: + self._timeRotateIntervalType = value + elif key == 'timeRotateInterval' and int( value ) > 0: + self._timeRotateInterval = int( value ) + elif key == 'sizeMaxBytes' and int( value ) >= 0: + self._sizeMaxBytes = int( value ) + elif key == 'sizeRotateMode' and value in ['a']: + self._sizeRotateMode = value + elif key == 'backupCount' and int( value ) >= 0: + self._backupCount = int( value ) + elif key == self._logKey + 'SocketHost': + self._socketHost = value + elif key == self._logKey + 'SocketPort' and int( value ) == 0: + self._socketPort = int( value ) + elif key == self._logKey + 'LogType' and value.lower() in ['filelogger', 'stdoutlogger', 'stderrlogger', 'socketlogger', 'nulllogger']: + self._typeLogger = value.lower() + elif key == self._logKey + 'LogLevel': + self._logLevelThreshold = self._intLogLevel(value.upper()) + elif key == self._logKey + 'Style': + self._fields["style"] = value + elif key == self._logKey: + self._logFile = value + except Exception as x: + print("exception reading '%s' configuration file: %s" %(self._configFile, str(x)), file=sys.stderr) + sys.exit(2) + except: + print("exception reading '%s' configuration file" %(self._configFile), file=sys.stderr) + sys.exit(2) + + if self._logFile is None: + print('configuration file %s is missing definition %s for log file' %(self._configFile, self._logKey), file=sys.stderr) + sys.exit(2) + + + # initialize default log fields + # timestamp will automatically be generated + for key in ['style', 'requestID', 'serviceInstanceID', 'threadID', 'serverName', 'serviceName', 'instanceUUID', \ + 'severity', 'serverIPAddress', 'server', 'IPAddress', 'className', 'timer', \ + 'partnerName', 'targetEntity', 'targetServiceName', 'statusCode', 'responseCode', \ + 'responseDescription', 'processKey', 'targetVirtualEntity', 'customField1', \ + 'customField2', 'customField3', 'customField4', 'errorCategory', 'errorCode', \ + 'errorDescription' ]: + if key in kwargs and kwargs[key] != None: + self._fields[key] = kwargs[key] + + self._resetStyleField() + + # Set up logger + self._logLock = threading.Lock() + with self._logLock: + self._logger = logging.getLogger(self._logKey) + self._logger.propagate = False + self._createLogger() + + self._defaultServerInfo() + + # spawn a thread to monitor configFile for logLevel and logFile changes + self._monitorFlag = True + self._monitorThread = threading.Thread(target=self._monitorConfigFile, args=()) + self._monitorThread.daemon = True + self._monitorThread.start() + + + def _createLogger(self): + if self._typeLogger == 'filelogger': + self._mkdir_p(self._logFile) + if self._rotateMethod == 'time': + self._logHandler = logging.handlers.TimedRotatingFileHandler(self._logFile, \ + when=self._timeRotateIntervalType, interval=self._timeRotateInterval, \ + backupCount=self._backupCount, encoding=None, delay=False, utc=True) + elif self._rotateMethod == 'size': + self._logHandler = logging.handlers.RotatingFileHandler(self._logFile, \ + mode=self._sizeRotateMode, maxBytes=self._sizeMaxBytes, \ + backupCount=self._backupCount, encoding=None, delay=False) + + else: + self._logHandler = logging.handlers.WatchedFileHandler(self._logFile, \ + mode=self._sizeRotateMode, \ + encoding=None, delay=False) + elif self._typeLogger == 'stderrlogger': + self._logHandler = logging.handlers.StreamHandler(sys.stderr) + elif self._typeLogger == 'stdoutlogger': + self._logHandler = logging.handlers.StreamHandler(sys.stdout) + elif self._typeLogger == 'socketlogger': + self._logHandler = logging.handlers.SocketHandler(self._socketHost, self._socketPort) + elif self._typeLogger == 'nulllogger': + self._logHandler = logging.handlers.NullHandler() + + if self._fields["style"] == CommonLogger.AuditFile or self._fields["style"] == CommonLogger.MetricsFile: + self._logFormatter = logging.Formatter(fmt='%(begtime)s,%(begmsecs)03d+00:00|%(endtime)s,%(endmsecs)03d+00:00|%(message)s', datefmt=CommonLogger.DateFmt) + else: + self._logFormatter = logging.Formatter(fmt='%(asctime)s,%(msecs)03d+00:00|%(message)s', datefmt='%Y-%m-%dT%H:%M:%S') + self._logFormatter.converter = time.gmtime + self._logHandler.setFormatter(self._logFormatter) + self._logger.addHandler(self._logHandler) + + def _resetStyleField(self): + styleFields = ["error", "debug", "audit", "metrics"] + if self._fields['style'] in styleFields: + self._fields['style'] = styleFields.index(self._fields['style']) + + def __del__(self): + if self._monitorFlag == False: + return + + self._monitorFlag = False + + if self._monitorThread is not None and self._monitorThread.is_alive(): + self._monitorThread.join() + + self._monitorThread = None + + + def _defaultServerInfo(self): + + # If not set or purposely set = None, then set default + if self._fields.get('server') is None: + try: + self._fields['server'] = socket.getfqdn() + except Exception as err: + try: + self._fields['server'] = socket.gethostname() + except Exception as err: + self._fields['server'] = "" + + # If not set or purposely set = None, then set default + if self._fields.get('serverIPAddress') is None: + try: + self._fields['serverIPAddress'] = socket.gethostbyname(self._fields['server']) + except Exception as err: + self._fields['serverIPAddress'] = "" + + + def _monitorConfigFile(self): + while self._monitorFlag: + try: + fileTime = os.path.getmtime(self._configFile) + if fileTime > self._configFileModified: + self._configFileModified = fileTime + ReopenLogFile = False + logFile = self._logFile + with open(self._configFile) as fp: + for line in fp: + line = line.split('#',1)[0] # remove comments + if '=' in line: + key, value = [x.strip() for x in line.split('=',1)] + if key == 'rotateMethod' and value.lower() in ['time', 'size', 'none'] and self._rotateMethod != value: + self._rotateMethod = value.lower() + ReopenLogFile = True + elif key == 'timeRotateIntervalType' and value in ['S', 'M', 'H', 'D', 'W0', 'W1', 'W2', 'W3', 'W4', 'W5', 'W6', 'midnight']: + self._timeRotateIntervalType = value + ReopenLogFile = True + elif key == 'timeRotateInterval' and int( value ) > 0: + self._timeRotateInterval = int( value ) + ReopenLogFile = True + elif key == 'sizeMaxBytes' and int( value ) >= 0: + self._sizeMaxBytes = int( value ) + ReopenLogFile = True + elif key == 'sizeRotateMode' and value in ['a']: + self._sizeRotateMode = value + ReopenLogFile = True + elif key == 'backupCount' and int( value ) >= 0: + self._backupCount = int( value ) + ReopenLogFile = True + elif key == self._logKey + 'SocketHost' and self._socketHost != value: + self._socketHost = value + ReopenLogFile = True + elif key == self._logKey + 'SocketPort' and self._socketPort > 0 and self._socketPort != int( value ): + self._socketPort = int( value ) + ReopenLogFile = True + elif key == self._logKey + 'LogLevel' and self._logLevelThreshold != self._intLogLevel( value.upper() ): + self._logLevelThreshold = self._intLogLevel(value.upper()) + elif key == self._logKey + 'LogType' and self._typeLogger != value and value.lower() in ['filelogger', 'stdoutlogger', 'stderrlogger', 'socketlogger', 'nulllogger']: + self._typeLogger = value.lower() + ReopenLogFile = True + elif key == self._logKey + 'Style': + self._fields["style"] = value + self._resetStyleField() + elif key == self._logKey and self._logFile != value: + logFile = value + ReopenLogFile = True + if ReopenLogFile: + with self._logLock: + self._logger.removeHandler(self._logHandler) + self._logFile = logFile + self._createLogger() + except Exception as err: + pass + + time.sleep(5) + + + def setFields(self, **kwargs): + """Set default values for log fields. + + Keyword arguments: Annotations are d:debug, a=audit, m=metrics, e=error + style -- the log file format (style) to use when writing log messages + requestID (dame) -- optional default value for this log record field. + serviceInstanceID (am) -- optional default value for this log record field. + threadID (am) -- optional default value for this log record field. + serverName (am) -- optional default value for this log record field. + serviceName (am) -- optional default value for this log record field. + instanceUUID (am) -- optional default value for this log record field. + severity (am) -- optional default value for this log record field. + serverIPAddress (am) -- optional default value for this log record field. + server (am) -- optional default value for this log record field. + IPAddress (am) -- optional default value for this log record field. + className (am) -- optional default value for this log record field. + timer (am) -- (ElapsedTime) optional default value for this log record field. + partnerName (ame) -- optional default value for this log record field. + targetEntity (me) -- optional default value for this log record field. + targetServiceName (me) -- optional default value for this log record field. + statusCode (am) -- optional default value for this log record field. + responseCode (am) -- optional default value for this log record field. + responseDescription (am) -- optional default value for this log record field. + processKey (am) -- optional default value for this log record field. + targetVirtualEntity (m) -- optional default value for this log record field. + customField1 (am) -- optional default value for this log record field. + customField2 (am) -- optional default value for this log record field. + customField3 (am) -- optional default value for this log record field. + customField4 (am) -- optional default value for this log record field. + errorCategory (e) -- optional default value for this log record field. + errorCode (e) -- optional default value for this log record field. + errorDescription (e) -- optional default value for this log record field. + + Note: the pipe '|' character is not allowed in any log record field. + """ + + for key in ['style', 'requestID', 'serviceInstanceID', 'threadID', 'serverName', 'serviceName', 'instanceUUID', \ + 'severity', 'serverIPAddress', 'server', 'IPAddress', 'className', 'timer', \ + 'partnerName', 'targetEntity', 'targetServiceName', 'statusCode', 'responseCode', \ + 'responseDescription', 'processKey', 'targetVirtualEntity', 'customField1', \ + 'customField2', 'customField3', 'customField4', 'errorCategory', 'errorCode', \ + 'errorDescription' ]: + if key in kwargs: + if kwargs[key] != None: + self._fields[key] = kwargs[key] + elif key in self._fields: + del self._fields[key] + + self._defaultServerInfo() + + + def debug(self, message, **kwargs): + """Write a DEBUG level message to the log file. + + Arguments: + message -- value for the last log record field. + + Keyword arguments: Annotations are d:debug, a=audit, m=metrics, e=error + style -- the log file format (style) to use when writing log messages + requestID (dame) -- optional default value for this log record field. + serviceInstanceID (am) -- optional default value for this log record field. + threadID (am) -- optional default value for this log record field. + serverName (am) -- optional default value for this log record field. + serviceName (am) -- optional default value for this log record field. + instanceUUID (am) -- optional default value for this log record field. + severity (am) -- optional default value for this log record field. + serverIPAddress (am) -- optional default value for this log record field. + server (am) -- optional default value for this log record field. + IPAddress (am) -- optional default value for this log record field. + className (am) -- optional default value for this log record field. + timer (am) -- (ElapsedTime) optional default value for this log record field. + partnerName (ame) -- optional default value for this log record field. + targetEntity (me) -- optional default value for this log record field. + targetServiceName (me) -- optional default value for this log record field. + statusCode (am) -- optional default value for this log record field. + responseCode (am) -- optional default value for this log record field. + responseDescription (am) -- optional default value for this log record field. + processKey (am) -- optional default value for this log record field. + targetVirtualEntity (m) -- optional default value for this log record field. + customField1 (am) -- optional default value for this log record field. + customField2 (am) -- optional default value for this log record field. + customField3 (am) -- optional default value for this log record field. + customField4 (am) -- optional default value for this log record field. + errorCategory (e) -- optional default value for this log record field. + errorCode (e) -- optional default value for this log record field. + errorDescription (e) -- optional default value for this log record field. + + Note: the pipe '|' character is not allowed in any log record field. + """ + + self._log('DEBUG', message, **kwargs) + + def info(self, message, **kwargs): + """Write an INFO level message to the log file. + + Arguments: + message -- value for the last log record field. + + Keyword arguments: Annotations are d:debug, a=audit, m=metrics, e=error + style -- the log file format (style) to use when writing log messages + requestID (dame) -- optional default value for this log record field. + serviceInstanceID (am) -- optional default value for this log record field. + threadID (am) -- optional default value for this log record field. + serverName (am) -- optional default value for this log record field. + serviceName (am) -- optional default value for this log record field. + instanceUUID (am) -- optional default value for this log record field. + severity (am) -- optional default value for this log record field. + serverIPAddress (am) -- optional default value for this log record field. + server (am) -- optional default value for this log record field. + IPAddress (am) -- optional default value for this log record field. + className (am) -- optional default value for this log record field. + timer (am) -- (ElapsedTime) optional default value for this log record field. + partnerName (ame) -- optional default value for this log record field. + targetEntity (me) -- optional default value for this log record field. + targetServiceName (me) -- optional default value for this log record field. + statusCode (am) -- optional default value for this log record field. + responseCode (am) -- optional default value for this log record field. + responseDescription (am) -- optional default value for this log record field. + processKey (am) -- optional default value for this log record field. + targetVirtualEntity (m) -- optional default value for this log record field. + customField1 (am) -- optional default value for this log record field. + customField2 (am) -- optional default value for this log record field. + customField3 (am) -- optional default value for this log record field. + customField4 (am) -- optional default value for this log record field. + errorCategory (e) -- optional default value for this log record field. + errorCode (e) -- optional default value for this log record field. + errorDescription (e) -- optional default value for this log record field. + + Note: the pipe '|' character is not allowed in any log record field. + """ + + self._log('INFO', message, **kwargs) + + def warn(self, message, **kwargs): + """Write a WARN level message to the log file. + + Arguments: + message -- value for the last log record field. + + Keyword arguments: Annotations are d:debug, a=audit, m=metrics, e=error + style -- the log file format (style) to use when writing log messages + requestID (dame) -- optional default value for this log record field. + serviceInstanceID (am) -- optional default value for this log record field. + threadID (am) -- optional default value for this log record field. + serverName (am) -- optional default value for this log record field. + serviceName (am) -- optional default value for this log record field. + instanceUUID (am) -- optional default value for this log record field. + severity (am) -- optional default value for this log record field. + serverIPAddress (am) -- optional default value for this log record field. + server (am) -- optional default value for this log record field. + IPAddress (am) -- optional default value for this log record field. + className (am) -- optional default value for this log record field. + timer (am) -- (ElapsedTime) optional default value for this log record field. + partnerName (ame) -- optional default value for this log record field. + targetEntity (me) -- optional default value for this log record field. + targetServiceName (me) -- optional default value for this log record field. + statusCode (am) -- optional default value for this log record field. + responseCode (am) -- optional default value for this log record field. + responseDescription (am) -- optional default value for this log record field. + processKey (am) -- optional default value for this log record field. + targetVirtualEntity (m) -- optional default value for this log record field. + customField1 (am) -- optional default value for this log record field. + customField2 (am) -- optional default value for this log record field. + customField3 (am) -- optional default value for this log record field. + customField4 (am) -- optional default value for this log record field. + errorCategory (e) -- optional default value for this log record field. + errorCode (e) -- optional default value for this log record field. + errorDescription (e) -- optional default value for this log record field. + + Note: the pipe '|' character is not allowed in any log record field. + """ + + self._log('WARN', message, **kwargs) + + def error(self, message, **kwargs): + """Write an ERROR level message to the log file. + + Arguments: + message -- value for the last log record field. + + Keyword arguments: Annotations are d:debug, a=audit, m=metrics, e=error + style -- the log file format (style) to use when writing log messages + requestID (dame) -- optional default value for this log record field. + serviceInstanceID (am) -- optional default value for this log record field. + threadID (am) -- optional default value for this log record field. + serverName (am) -- optional default value for this log record field. + serviceName (am) -- optional default value for this log record field. + instanceUUID (am) -- optional default value for this log record field. + severity (am) -- optional default value for this log record field. + serverIPAddress (am) -- optional default value for this log record field. + server (am) -- optional default value for this log record field. + IPAddress (am) -- optional default value for this log record field. + className (am) -- optional default value for this log record field. + timer (am) -- (ElapsedTime) optional default value for this log record field. + partnerName (ame) -- optional default value for this log record field. + targetEntity (me) -- optional default value for this log record field. + targetServiceName (me) -- optional default value for this log record field. + statusCode (am) -- optional default value for this log record field. + responseCode (am) -- optional default value for this log record field. + responseDescription (am) -- optional default value for this log record field. + processKey (am) -- optional default value for this log record field. + targetVirtualEntity (m) -- optional default value for this log record field. + customField1 (am) -- optional default value for this log record field. + customField2 (am) -- optional default value for this log record field. + customField3 (am) -- optional default value for this log record field. + customField4 (am) -- optional default value for this log record field. + errorCategory (e) -- optional default value for this log record field. + errorCode (e) -- optional default value for this log record field. + errorDescription (e) -- optional default value for this log record field. + + Note: the pipe '|' character is not allowed in any log record field. + """ + + self._log('ERROR', message, **kwargs) + + def fatal(self, message, **kwargs): + """Write a FATAL level message to the log file. + + Arguments: + message -- value for the last log record field. + + Keyword arguments: Annotations are d:debug, a=audit, m=metrics, e=error + style -- the log file format (style) to use when writing log messages + requestID (dame) -- optional default value for this log record field. + serviceInstanceID (am) -- optional default value for this log record field. + threadID (am) -- optional default value for this log record field. + serverName (am) -- optional default value for this log record field. + serviceName (am) -- optional default value for this log record field. + instanceUUID (am) -- optional default value for this log record field. + severity (am) -- optional default value for this log record field. + serverIPAddress (am) -- optional default value for this log record field. + server (am) -- optional default value for this log record field. + IPAddress (am) -- optional default value for this log record field. + className (am) -- optional default value for this log record field. + timer (am) -- (ElapsedTime) optional default value for this log record field. + partnerName (ame) -- optional default value for this log record field. + targetEntity (me) -- optional default value for this log record field. + targetServiceName (me) -- optional default value for this log record field. + statusCode (am) -- optional default value for this log record field. + responseCode (am) -- optional default value for this log record field. + responseDescription (am) -- optional default value for this log record field. + processKey (am) -- optional default value for this log record field. + targetVirtualEntity (m) -- optional default value for this log record field. + customField1 (am) -- optional default value for this log record field. + customField2 (am) -- optional default value for this log record field. + customField3 (am) -- optional default value for this log record field. + customField4 (am) -- optional default value for this log record field. + errorCategory (e) -- optional default value for this log record field. + errorCode (e) -- optional default value for this log record field. + errorDescription (e) -- optional default value for this log record field. + + Note: the pipe '|' character is not allowed in any log record field. + """ + + self._log('FATAL', message, **kwargs) + + def _log(self, logLevel, message, **kwargs): + """Write a message to the log file. + + Arguments: + logLevel -- value ('DEBUG', 'INFO', 'WARN', 'ERROR', 'FATAL', ...) for the log record. + message -- value for the last log record field. + + Keyword arguments: Annotations are d:debug, a=audit, m=metrics, e=error + style -- the log file format (style) to use when writing log messages + requestID (dame) -- optional default value for this log record field. + serviceInstanceID (am) -- optional default value for this log record field. + threadID (am) -- optional default value for this log record field. + serverName (am) -- optional default value for this log record field. + serviceName (am) -- optional default value for this log record field. + instanceUUID (am) -- optional default value for this log record field. + severity (am) -- optional default value for this log record field. + serverIPAddress (am) -- optional default value for this log record field. + server (am) -- optional default value for this log record field. + IPAddress (am) -- optional default value for this log record field. + className (am) -- optional default value for this log record field. + timer (am) -- (ElapsedTime) optional default value for this log record field. + partnerName (ame) -- optional default value for this log record field. + targetEntity (me) -- optional default value for this log record field. + targetServiceName (me) -- optional default value for this log record field. + statusCode (am) -- optional default value for this log record field. + responseCode (am) -- optional default value for this log record field. + responseDescription (am) -- optional default value for this log record field. + processKey (am) -- optional default value for this log record field. + targetVirtualEntity (m) -- optional default value for this log record field. + customField1 (am) -- optional default value for this log record field. + customField2 (am) -- optional default value for this log record field. + customField3 (am) -- optional default value for this log record field. + customField4 (am) -- optional default value for this log record field. + errorCategory (e) -- optional default value for this log record field. + errorCode (e) -- optional default value for this log record field. + errorDescription (e) -- optional default value for this log record field. + + Note: the pipe '|' character is not allowed in any log record field. + """ + + # timestamp will automatically be inserted + style = int(self._getVal('style', '', **kwargs)) + requestID = self._getVal('requestID', '', **kwargs) + serviceInstanceID = self._getVal('serviceInstanceID', '', **kwargs) + threadID = self._getVal('threadID', threading.currentThread().getName(), **kwargs) + serverName = self._getVal('serverName', '', **kwargs) + serviceName = self._getVal('serviceName', '', **kwargs) + instanceUUID = self._getVal('instanceUUID', '', **kwargs) + upperLogLevel = self._noSep(logLevel.upper()) + severity = self._getVal('severity', '', **kwargs) + serverIPAddress = self._getVal('serverIPAddress', '', **kwargs) + server = self._getVal('server', '', **kwargs) + IPAddress = self._getVal('IPAddress', '', **kwargs) + className = self._getVal('className', '', **kwargs) + timer = self._getVal('timer', '', **kwargs) + partnerName = self._getVal('partnerName', '', **kwargs) + targetEntity = self._getVal('targetEntity', '', **kwargs) + targetServiceName = self._getVal('targetServiceName', '', **kwargs) + statusCode = self._getVal('statusCode', '', **kwargs) + responseCode = self._getVal('responseCode', '', **kwargs) + responseDescription = self._noSep(self._getVal('responseDescription', '', **kwargs)) + processKey = self._getVal('processKey', '', **kwargs) + targetVirtualEntity = self._getVal('targetVirtualEntity', '', **kwargs) + customField1 = self._getVal('customField1', '', **kwargs) + customField2 = self._getVal('customField2', '', **kwargs) + customField3 = self._getVal('customField3', '', **kwargs) + customField4 = self._getVal('customField4', '', **kwargs) + errorCategory = self._getVal('errorCategory', '', **kwargs) + errorCode = self._getVal('errorCode', '', **kwargs) + errorDescription = self._noSep(self._getVal('errorDescription', '', **kwargs)) + + detailMessage = self._noSep(message) + if bool(re.match(r" *$", detailMessage)): + return # don't log empty messages + + useLevel = self._intLogLevel(upperLogLevel) + if useLevel >= self._logLevelThreshold: + with self._logLock: + if style == CommonLogger.ErrorFile: + self._logger.log(50, '%s|%s|%s|%s|%s|%s|%s|%s|%s|%s' \ + %(requestID, threadID, serviceName, partnerName, targetEntity, targetServiceName, + errorCategory, errorCode, errorDescription, detailMessage)) + elif style == CommonLogger.DebugFile: + self._logger.log(50, '%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s' \ + %(requestID, threadID, serverName, serviceName, instanceUUID, upperLogLevel, + severity, serverIPAddress, server, IPAddress, className, timer, detailMessage)) + elif style == CommonLogger.AuditFile: + endAuditTime, endAuditMsec = self._getTime() + if self._begTime is not None: + d = { 'begtime': self._begTime, 'begmsecs': self._begMsec, 'endtime': endAuditTime, 'endmsecs': endAuditMsec } + else: + d = { 'begtime': endAuditTime, 'begmsecs': endAuditMsec, 'endtime': endAuditTime, 'endmsecs': endAuditMsec } + self._begTime = None + unused = "" + self._logger.log(50, '%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s' \ + %(requestID, serviceInstanceID, threadID, serverName, serviceName, partnerName, + statusCode, responseCode, responseDescription, instanceUUID, upperLogLevel, + severity, serverIPAddress, timer, server, IPAddress, className, unused, + processKey, customField1, customField2, customField3, customField4, detailMessage), extra=d) + elif style == CommonLogger.MetricsFile: + endMetricsTime, endMetricsMsec = self._getTime() + if self._begTime is not None: + d = { 'begtime': self._begTime, 'begmsecs': self._begMsec, 'endtime': endMetricsTime, 'endmsecs': endMetricsMsec } + else: + d = { 'begtime': endMetricsTime, 'begmsecs': endMetricsMsec, 'endtime': endMetricsTime, 'endmsecs': endMetricsMsec } + self._begTime = None + unused = "" + self._logger.log(50, '%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s' \ + %(requestID, serviceInstanceID, threadID, serverName, serviceName, partnerName, + targetEntity, targetServiceName, statusCode, responseCode, responseDescription, + instanceUUID, upperLogLevel, severity, serverIPAddress, timer, server, IPAddress, + className, unused, processKey, targetVirtualEntity, customField1, customField2, + customField3, customField4, detailMessage), extra=d) + else: + print("!!!!!!!!!!!!!!!! style not set: %s" % self._fields["style"]) + + def _getTime(self): + ct = time.time() + lt = time.localtime(ct) + return (time.strftime(CommonLogger.DateFmt, lt), (ct - int(ct)) * 1000) + + def setStartRecordEvent(self): + """ + Set the start time to be saved for both audit and metrics records + """ + self._begTime, self._begMsec = self._getTime() + + def _getVal(self, key, default, **kwargs): + val = self._fields.get(key) + if key in kwargs: val = kwargs[key] + if val is None: val = default + return self._noSep(val) + + def _noSep(self, message): + if message is None: return '' + return re.sub(r'[\|\n]', ' ', str(message)) + + def _intLogLevel(self, logLevel): + if logLevel == 'FATAL': useLevel = 50 + elif logLevel == 'ERROR': useLevel = 40 + elif logLevel == 'WARN': useLevel = 30 + elif logLevel == 'INFO': useLevel = 20 + elif logLevel == 'DEBUG': useLevel = 10 + else: useLevel = 0 + return useLevel + + def _mkdir_p(self, filename): + """Create missing directories from a full filename path like mkdir -p""" + + if filename is None: + return + + folder=os.path.dirname(filename) + + if folder == "": + return + + if not os.path.exists(folder): + try: + os.makedirs(folder) + except OSError as err: + print("error number %d creating %s directory to hold %s logfile: %s" %(err.errno, err.filename, filename, err.strerror), file=sys.stderr) + sys.exit(2) + except Exception as err: + print("error creating %s directory to hold %s logfile: %s" %(folder, filename, str(err)), file=sys.stderr) + sys.exit(2) + +def __checkTime1(line): + format = r'[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9],[0-9][0-9][0-9][+]00:00[|]' + format = r'[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{3}[+]00:00[|]' + m = re.match(format, line) + if not m: + print("ERROR: time string did not match proper time format, %s" %line) + print("\t: format=%s" % format) + return 1 + return 0 + +def __checkTime2(line, different): + format = '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:([0-9][0-9]),([0-9][0-9][0-9])[+]00:00[|][0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:([0-9][0-9]),([0-9][0-9][0-9])[+]00:00[|]' + format = r'[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:([0-9]{2}),([0-9]{3})[+]00:00[|][0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:([0-9]{2}),([0-9]{3})[+]00:00[|]' + m = re.match(format, line) + if not m: + print("ERROR: time strings did not match proper time format, %s" %line) + print("\t: format=%s" % format) + return 1 + second1 = int(m.group(1)) + msec1 = int(m.group(2)) + second2 = int(m.group(3)) + msec2 = int(m.group(4)) + if second1 > second2: second2 += 60 + t1 = second1 * 1000 + msec1 + t2 = second2 * 1000 + msec2 + diff = t2 - t1 + # print("t1=%d (%d,%d) t2=%d (%d,%d), diff = %d" % (t1, second1, msec1, t2, second2, msec2, diff)) + if different: + if diff < 500: + print("ERROR: times did not differ enough: %s" % line) + return 1 + else: + if diff > 10: + print("ERROR: times were too far apart: %s" % line) + return 1 + return 0 + +def __checkLog(logfile, numLines, numFields): + lineCount = 0 + errorCount = 0 + with open(logfile, "r") as fp: + for line in fp: + # print("saw line %s" % line) + lineCount += 1 + c = line.count('|') + if c != numFields: + print("ERROR: wrong number of fields. Expected %d, got %d: %s" % (numFields, c, line)) + errorCount += 1 + if re.search("should not appear", line): + print("ERROR: a line appeared that should not have appeared, %s" % line) + errorCount += 1 + elif re.search("single time", line): + errorCount += __checkTime1(line) + elif re.search("time should be the same", line): + errorCount += __checkTime2(line, different=False) + elif re.search("time should be different", line): + errorCount += __checkTime2(line, different=True) + else: + print("ERROR: an unknown message appeared, %s" % line) + errorCount += 1 + + if lineCount != numLines: + print("ERROR: expected %d lines, but got %d lines" % (numLines, lineCount)) + errorCount += 1 + return errorCount + +if __name__ == "__main__": + import os + keepLogs = False + spid = str(os.getpid()) + if keepLogs: + spid = "" + logcfg = "/tmp/log" + spid + ".cfg" + errorLog = "/tmp/error" + spid + ".log" + metricsLog = "/tmp/metrics" + spid + ".log" + auditLog = "/tmp/audit" + spid + ".log" + debugLog = "/tmp/debug" + spid + ".log" + + import atexit + def cleanupTmps(): + for f in [ logcfg, errorLog, metricsLog, auditLog, debugLog ]: + try: + os.remove(f) + except: + pass + if not keepLogs: + atexit.register(cleanupTmps) + + with open(logcfg, "w") as o: + o.write("error = " + errorLog + "\n" + + "errorLogLevel = WARN\n" + + "metrics = " + metricsLog + "\n" + + "metricsLogLevel = INFO\n" + + "audit = " + auditLog + "\n" + + "auditLogLevel = INFO\n" + + "debug = " + debugLog + "\n" + + "debugLogLevel = DEBUG\n") + + import uuid + instanceUUID = uuid.uuid1() + serviceName = "testharness" + errorLogger = CommonLogger(logcfg, "error", style=CommonLogger.ErrorFile, instanceUUID=instanceUUID, serviceName=serviceName) + debugLogger = CommonLogger(logcfg, "debug", style=CommonLogger.DebugFile, instanceUUID=instanceUUID, serviceName=serviceName) + auditLogger = CommonLogger(logcfg, "audit", style=CommonLogger.AuditFile, instanceUUID=instanceUUID, serviceName=serviceName) + metricsLogger = CommonLogger(logcfg, "metrics", style=CommonLogger.MetricsFile, instanceUUID=instanceUUID, serviceName=serviceName) + + testsRun = 0 + errorCount = 0 + errorLogger.debug("error calling debug (should not appear)") + errorLogger.info("error calling info (should not appear)") + errorLogger.warn("error calling warn (single time)") + errorLogger.error("error calling error (single time)") + errorLogger.setStartRecordEvent() + time.sleep(1) + errorLogger.fatal("error calling fatal, after setStartRecordEvent and sleep (start should be ignored, single time)") + testsRun += 6 + errorCount += __checkLog(errorLog, 3, 10) + + auditLogger.debug("audit calling debug (should not appear)") + auditLogger.info("audit calling info (time should be the same)") + auditLogger.warn("audit calling warn (time should be the same)") + auditLogger.error("audit calling error (time should be the same)") + auditLogger.setStartRecordEvent() + time.sleep(1) + auditLogger.fatal("audit calling fatal, after setStartRecordEvent and sleep, time should be different)") + testsRun += 6 + errorCount += __checkLog(auditLog, 4, 25) + + debugLogger.debug("debug calling debug (single time)") + debugLogger.info("debug calling info (single time)") + debugLogger.warn("debug calling warn (single time)") + debugLogger.setStartRecordEvent() + time.sleep(1) + debugLogger.error("debug calling error, after SetStartRecordEvent and sleep (start should be ignored, single time)") + debugLogger.fatal("debug calling fatal (single time)") + errorCount += __checkLog(debugLog, 5, 13) + testsRun += 6 + + metricsLogger.debug("metrics calling debug (should not appear)") + metricsLogger.info("metrics calling info (time should be the same)") + metricsLogger.warn("metrics calling warn (time should be the same)") + metricsLogger.setStartRecordEvent() + time.sleep(1) + metricsLogger.error("metrics calling error, after SetStartRecordEvent and sleep, time should be different") + metricsLogger.fatal("metrics calling fatal (time should be the same)") + testsRun += 6 + errorCount += __checkLog(metricsLog, 4, 28) + + print("%d tests run, %d errors found" % (testsRun, errorCount)) diff --git a/pgaas/src/stage/opt/app/pgaas/lib/dcae_admin_db.json b/pgaas/src/stage/opt/app/pgaas/lib/dcae_admin_db.json new file mode 100644 index 0000000..1e869e8 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/lib/dcae_admin_db.json @@ -0,0 +1,42 @@ +{ + "version": "1.0", + + "global": + { + "state": "master", + "sendWalTo": + [ + { + + } + ] + }, + + "databases": + [ + { + "name": "ojcit", + "users": + [ + { + "id": "ojcitadmin", + "password": "bar", + "role": "admin", + "roleComment": "admin|writer|reader" + }, + { + "id": "ojcituser", + "password": "bar", + "role": "writer", + "roleComment": "admin|writer|reader" + }, + { + "id": "ojcitviewer", + "password": "bar", + "role": "reader", + "roleComment": "admin|writer|reader" + } + ] + } + ] +}
\ No newline at end of file diff --git a/pgaas/src/stage/opt/app/pgaas/lib/init-logger.cfg b/pgaas/src/stage/opt/app/pgaas/lib/init-logger.cfg new file mode 100644 index 0000000..0cfae0d --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/lib/init-logger.cfg @@ -0,0 +1,40 @@ +# You may change this file while your program is running and CommonLogger will automatically reconfigure accordingly. +# Changing these parameters may leave old log files lying around. + + +#--- Parameters that apply to all logs +# +# rotateMethod: time or size +#... Note: the following two parameters apply only when rotateMethod=time +# timeRotateIntervalType: S, M, H, D, W0 - W6, or midnight (seconds, minutes, hours, days, weekday (0=Monday), or midnight UTC) +# timeRotateInterval: >= 1 (1 means every timeRotateIntervalType, 2 every other, 3 every third, etc.) +#... Note: the following parameter applies only when rotateMethod=size +# sizeMaxBytes: >= 0 (0 means no limit, else maximum filesize in Bytes) +# backupCount: >= 0 (Number of rotated backup files to retain. If rotateMethod=time, 0 retains *all* backups. If rotateMethod=size, 0 retains *no* backups.) +# +rotateMethod = none +# timeRotateIntervalType = midnight +# timeRotateInterval = 1 +# sizeMaxBytes = 0 +# backupCount = 6 + + +#--- Parameters that define log filenames and their initial LogLevel threshold +#... Note: CommonLogger will exit if your process does not have permission to write to the file. +# + +error = /opt/app/log/postgresql/init/error.log +errorLogLevel = WARN +errorStyle = error + +metrics = /opt/app/log/postgresql/init/metrics.log +metricsLogLevel = INFO +metricsStyle = metrics + +audit = /opt/app/log/postgresql/init/audit.log +auditLogLevel = INFO +auditStyle = audit + +debug = /opt/app/log/postgresql/init/debug.log +debugLogLevel = DEBUG +debugStyle = debug diff --git a/pgaas/src/stage/opt/app/pgaas/lib/makefile b/pgaas/src/stage/opt/app/pgaas/lib/makefile new file mode 100644 index 0000000..a6f3266 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/lib/makefile @@ -0,0 +1,25 @@ +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +all: + +STAGEDIR=/dev/null +DISTPATH=/opt/app/pgaas + +CFGFILES= CommonLogger.py pgaas.cfg init-logger.cfg + +stage: + rm -rf $(STAGEDIR)/$(DISTPATH)/lib + mkdir -p $(STAGEDIR)/$(DISTPATH)/lib + cp $(CFGFILES) $(STAGEDIR)/$(DISTPATH)/lib diff --git a/pgaas/src/stage/opt/app/pgaas/lib/pgaas.cfg b/pgaas/src/stage/opt/app/pgaas/lib/pgaas.cfg new file mode 100644 index 0000000..0d4cc04 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/lib/pgaas.cfg @@ -0,0 +1,31 @@ +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +#### +#### PostgreSQL as a Service Configuration Parameters +#### + +db_directory=/dbroot/pgdata/main +# db_configuration= +# pg_bin_directory= + +dcae_admin_db_hostname=localhost +dcae_admin_db_databasename=postgres +dcae_admin_db_username=postgres +dcae_admin_db_verbosity=1 +dcae_admin_db_jsontop="['vmConfiguration']" +dcae_admin_db_errors_file=/opt/app/log/postgresql/init/error.log +dcae_admin_db_trace_file=/opt/app/log/postgresql/init/trace.log +dcae_admin_db_common_logger_config=/opt/app/pgaas/lib/init-logger.cfg +# skip_configuration_file= diff --git a/pgaas/src/stage/opt/app/pgaas/makefile b/pgaas/src/stage/opt/app/pgaas/makefile new file mode 100644 index 0000000..73232db --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/makefile @@ -0,0 +1,31 @@ +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +STAGEDIR=/dev/null +all: + +stage: + for i in bin lib etc man; do \ + ( cd $$i && $(MAKE) stage STAGEDIR=../$(STAGEDIR) ) \ + done + +clean: + for i in bin lib etc man; do \ + ( cd $$i && $(MAKE) clean ) \ + done + +clobber: + for i in bin lib etc man; do \ + ( cd $$i && $(MAKE) clobber ) \ + done diff --git a/pgaas/src/stage/opt/app/pgaas/man/.gitignore b/pgaas/src/stage/opt/app/pgaas/man/.gitignore new file mode 100644 index 0000000..f7e585b --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/.gitignore @@ -0,0 +1 @@ +*.1 diff --git a/pgaas/src/stage/opt/app/pgaas/man/check_cluster.man b/pgaas/src/stage/opt/app/pgaas/man/check_cluster.man new file mode 100644 index 0000000..dc6fcce --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/check_cluster.man @@ -0,0 +1,34 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH check_cluster 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +check_cluster - check the state of the cluster +.SH SYNOPSIS +check_cluster [-v] [-l] [-t timeout] +.HP 20 +-l +do not check localhost first (and restarting the service if necessary) +.HP 20 +-t timeout +set how long to wait when accessing the servers +.HP 20 +-v +verbose +.SH DESCRIPTION +Loop through the nodes in the cluster, using pgwget to determine how many are masters, secondaries, or not up. +Complain about certain situations. +If there are multiple masters, and this not the first master in the list, then: + +run pg_ctl_restart + +prevent /ro from returning true diff --git a/pgaas/src/stage/opt/app/pgaas/man/dcae_admin_db.man b/pgaas/src/stage/opt/app/pgaas/man/dcae_admin_db.man new file mode 100644 index 0000000..84b7cbb --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/dcae_admin_db.man @@ -0,0 +1,72 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH dcae_admin_db.py 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +dcae_admin_db.py - interface with DCAE controller +.SH SYNOPSIS +dcae_admin_db.py [options] configurationChanged json-file +.br +dcae_admin_db.py [options] suspend +.br +dcae_admin_db.py [options] resume +.br +dcae_admin_db.py [options] test +.SS OPTIONS +.HP 20 +-H / --dbhost= +host name, defaults to CFG['dcae_admin_db_hostname'] +.HP 20 +-d / --dbdir= +database directory path, defaults to CFG['db_directory'] +.HP 20 +-c / --dbconf= +database configuration path, defaults to CFG['db_configuration'] +.HP 20 +-D / --dbname= +database name, defaults to CFG['dcae_admin_db_databasename'] +.HP 20 +-U / --user= +user to login as, defaults to CFG['dcae_admin_db_username'] +.HP 20 +-P / --password= +password for user, defaults to CFG['dcae_admin_db_password'] +.HP 20 +-B / --bindir= +postgresql bin directory, defaults to CFG['pg_bin_directory'] +.HP 20 +-i / --ignorefile= +skip configuration if this file is present, defaults to CFG['skip_configuration_file'] +.HP 20 +-n / --nocreate +do not create the databases / users +.HP 20 +-I / --ignoredb +ignore current state of database +.HP 20 +-R / --remove +remove old databases / users +.HP 20 +-J / --jsontop= +top of json tree, as in \"['pgaas']\" +.HP 20 +-e / --errors= +where to redirect error output, defaults to CFG['dcae_admin_db_errors_file'] then stderr +.HP 20 +-t / --trace= +where to redirect trace output, defaults to CFG['dcae_admin_db_trace_file'] then stderr +.HP 20 +-v / --verbose +verbose, defaults to CFG['dcae_admin_db_verbosity'] +.SH DESCRIPTION +This program is intended to be executed by the DCAE controller manager. +Given a database description json file, update the current VM accordingly diff --git a/pgaas/src/stage/opt/app/pgaas/man/isrw.man b/pgaas/src/stage/opt/app/pgaas/man/isrw.man new file mode 100644 index 0000000..4c4207d --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/isrw.man @@ -0,0 +1,19 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH isrw 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +isrw - check if a running PostgreSQL is a master or secondary +.SH SYNOPSIS +isrw +.SH DESCRIPTION +Either prints Master or Secondary depending on the state of the running PostgreSQL server. diff --git a/pgaas/src/stage/opt/app/pgaas/man/list_masters.man b/pgaas/src/stage/opt/app/pgaas/man/list_masters.man new file mode 100644 index 0000000..be5b2bd --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/list_masters.man @@ -0,0 +1,30 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH list_masters 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +list_masters - loop through the nodes in the cluster, using a remote call to determine if any are a master. +.SH SYNOPSIS +list_masters +.SH DESCRIPTION +List_masters loops through the nodes in the cluster, using a remote call to the iDNS-responder running on each server to determine if any are a master. +The names of the masters are printed (there should only be one). +.SS Exit Codes +.HP 20 +0 +one master exists and is running +.HP 20 +1 +no masters exist +.HP 20 +2 +more than one master exist diff --git a/pgaas/src/stage/opt/app/pgaas/man/makefile b/pgaas/src/stage/opt/app/pgaas/man/makefile new file mode 100644 index 0000000..9cd2090 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/makefile @@ -0,0 +1,97 @@ +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this code 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. + + +.SUFFIXES: .man .1 + +TR2MAN = +%.1 : %.man + $(TR2MAN) + +STAGEDIR=/dev/null +DISTPATH=/opt/app/pgaas + +TRFILES := $(wildcard *.man) +MANFILES := $(patsubst %.man,%.1,$(wildcard *.man)) + +all: $(MANFILES) + +stage: $(MANFILES) + rm -rf $(STAGEDIR)/$(DISTPATH)/man + mkdir -p $(STAGEDIR)/$(DISTPATH)/man + cp -p $(MANFILES) $(STAGEDIR)/$(DISTPATH)/man + +clean: + rm -f *~ + +clobber: clean + rm -f *.1 + +# really should not need to list each of the files individually here with how to make them + +check_cluster.1: check_cluster.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +dcae_admin_db.1: dcae_admin_db.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +isrw.1: isrw.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +list_masters.1: list_masters.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +pg_ctl_promote.1: pg_ctl_promote.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +pg_ctl_restart.1: pg_ctl_restart.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +pg_ctl_start.1: pg_ctl_start.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +pg_ctl_status.1: pg_ctl_status.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +pg_ctl_stop.1: pg_ctl_stop.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +repmgrc.1: repmgrc.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +repmgrdc.1: repmgrdc.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +runpsqll.1: runpsqll.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +runpsql.1: runpsql.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +setpropvalue.1: setpropvalue.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +show_pg_is_in_recovery.1: show_pg_is_in_recovery.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +show_pg_stat_activity.1: show_pg_stat_activity.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +show_pg_stat_archiver.1: show_pg_stat_archiver.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +show_pg_stat_bgwriter.1: show_pg_stat_bgwriter.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +show_pg_stat_database_conflicts.1: show_pg_stat_database_conflicts.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +show_pg_stat_database.1: show_pg_stat_database.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +show_pg_statio_user_functions.1: show_pg_statio_user_functions.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +show_pg_statio_user_indexes.1: show_pg_statio_user_indexes.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +show_pg_statio_user_sequences.1: show_pg_statio_user_sequences.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +show_pg_statio_user_tables.1: show_pg_statio_user_tables.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +show_pg_stat_user_indexes.1: show_pg_stat_user_indexes.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +show_pg_stat_user_tables.1: show_pg_stat_user_tables.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +startpsql.1: startpsql.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ +update_var_run_isrw.1: update_var_run_isrw.man + DATE=$$(date +%Y-%m-%d); sed "1s/ {{DATE}} / $$DATE /" < $< | nroff -Tlp -man > $@ diff --git a/pgaas/src/stage/opt/app/pgaas/man/pg_ctl_promote.man b/pgaas/src/stage/opt/app/pgaas/man/pg_ctl_promote.man new file mode 100644 index 0000000..21d7b82 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/pg_ctl_promote.man @@ -0,0 +1,20 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH pg_ctl_promote 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +pg_ctl_promote - helper function to run pg_ctl promote +.SH SYNOPSIS +pg_ctl_promote +.SH DESCRIPTION +Finds the pg_ctl command, the location of the database and its configurations and runs "pg_ctl promote". + diff --git a/pgaas/src/stage/opt/app/pgaas/man/pg_ctl_restart.man b/pgaas/src/stage/opt/app/pgaas/man/pg_ctl_restart.man new file mode 100644 index 0000000..e6bf6c9 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/pg_ctl_restart.man @@ -0,0 +1,19 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH pg_ctl_restart 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +pg_ctl_restart - helper function to run pg_ctl restart +.SH SYNOPSIS +pg_ctl_restart +.SH DESCRIPTION +Finds the pg_ctl command, the location of the database and its configurations and runs "pg_ctl stop" and "pg_ctl start". diff --git a/pgaas/src/stage/opt/app/pgaas/man/pg_ctl_start.man b/pgaas/src/stage/opt/app/pgaas/man/pg_ctl_start.man new file mode 100644 index 0000000..81f171d --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/pg_ctl_start.man @@ -0,0 +1,19 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH pg_ctl_start 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +pg_ctl_start - helper function to run pg_ctl start +.SH SYNOPSIS +pg_ctl_start +.SH DESCRIPTION +Finds the pg_ctl command, the location of the database and its configurations and runs "pg_ctl start". diff --git a/pgaas/src/stage/opt/app/pgaas/man/pg_ctl_status.man b/pgaas/src/stage/opt/app/pgaas/man/pg_ctl_status.man new file mode 100644 index 0000000..5a6256d --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/pg_ctl_status.man @@ -0,0 +1,19 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH pg_ctl_status 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +pg_ctl_status - helper function to run pg_ctl status +.SH SYNOPSIS +pg_ctl_status +.SH DESCRIPTION +Finds the pg_ctl command, the location of the database and its configurations and runs "pg_ctl status". diff --git a/pgaas/src/stage/opt/app/pgaas/man/pg_ctl_stop.man b/pgaas/src/stage/opt/app/pgaas/man/pg_ctl_stop.man new file mode 100644 index 0000000..ba4e71e --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/pg_ctl_stop.man @@ -0,0 +1,19 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH pg_ctl_stop 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +pg_ctl_stop - helper function to run pg_ctl stop +.SH SYNOPSIS +pg_ctl_stop +.SH DESCRIPTION +Finds the pg_ctl command, the location of the database and its configurations and runs "pg_ctl stop". diff --git a/pgaas/src/stage/opt/app/pgaas/man/repmgrc.man b/pgaas/src/stage/opt/app/pgaas/man/repmgrc.man new file mode 100644 index 0000000..18c8848 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/repmgrc.man @@ -0,0 +1,19 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH repmgr 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +repmgrc - helper function to run repmgr command +.SH SYNOPSIS +repmgrc +.SH DESCRIPTION +Finds the repmgr command and its configurations and runs "repmgr" appropriately. diff --git a/pgaas/src/stage/opt/app/pgaas/man/repmgrdc.man b/pgaas/src/stage/opt/app/pgaas/man/repmgrdc.man new file mode 100644 index 0000000..9d9617f --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/repmgrdc.man @@ -0,0 +1,19 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH repmgrd 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +repmgrdc - helper function to run repmgrd command +.SH SYNOPSIS +repmgrdc +.SH DESCRIPTION +Finds the repmgrd command and its configurations and runs "repmgrd" appropriately. diff --git a/pgaas/src/stage/opt/app/pgaas/man/runpsql.man b/pgaas/src/stage/opt/app/pgaas/man/runpsql.man new file mode 100644 index 0000000..1903d7a --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/runpsql.man @@ -0,0 +1,21 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH runpsql 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +runpsql - run the psql command that is given on the command line +.SH SYNOPSIS +runpsql sql command ... +.SH DESCRIPTION +Locate the psql command and run the command specified as the arguments on the command line. +.SH "SEE ALSO" +runpsqll, startpsql diff --git a/pgaas/src/stage/opt/app/pgaas/man/runpsqll.man b/pgaas/src/stage/opt/app/pgaas/man/runpsqll.man new file mode 100644 index 0000000..2098688 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/runpsqll.man @@ -0,0 +1,22 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH runpsqll 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +runpsqll - run the psql command that is given on the command line, no labels +.SH SYNOPSIS +runpsqll sql command ... +.SH DESCRIPTION +Locate the psql command and run the command specified as the arguments on the command line. +Only output the tuples. +.SH "SEE ALSO" +runpsql, startpsql diff --git a/pgaas/src/stage/opt/app/pgaas/man/setpropvalue.man b/pgaas/src/stage/opt/app/pgaas/man/setpropvalue.man new file mode 100644 index 0000000..d56a2e7 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/setpropvalue.man @@ -0,0 +1,26 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH setpropvalue 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +setpropvalue - set a property in the CDF property file +.SH SYNOPSIS +setpropvalue -n name -v value [-x] +.HP 20 +-n +name to configure +.HP 20 +-v +value to set +.HP 20 +-x +encrypt the value diff --git a/pgaas/src/stage/opt/app/pgaas/man/show_pg_is_in_recovery.man b/pgaas/src/stage/opt/app/pgaas/man/show_pg_is_in_recovery.man new file mode 100644 index 0000000..a4c9474 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/show_pg_is_in_recovery.man @@ -0,0 +1,19 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH show_pg_is_in_recovery 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +show_pg_is_in_recovery - convenience program to extract info from the database +.SH SYNOPSIS +show_pg_is_in_recovery +.SH DESCRIPTION +show_pg_is_in_recovery is a convenience program to extract the pg_is_in_recovery information from the database. diff --git a/pgaas/src/stage/opt/app/pgaas/man/show_pg_stat_activity.man b/pgaas/src/stage/opt/app/pgaas/man/show_pg_stat_activity.man new file mode 100644 index 0000000..ef10efc --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/show_pg_stat_activity.man @@ -0,0 +1,19 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH show_pg_stat_activity 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +show_pg_stat_activity - convenience program to extract info from the database +.SH SYNOPSIS +show_pg_stat_activity +.SH DESCRIPTION +show_pg_stat_activity is a convenience program to extract the pg_stat_activity information from the database. diff --git a/pgaas/src/stage/opt/app/pgaas/man/show_pg_stat_archiver.man b/pgaas/src/stage/opt/app/pgaas/man/show_pg_stat_archiver.man new file mode 100644 index 0000000..f1044e2 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/show_pg_stat_archiver.man @@ -0,0 +1,19 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH show_pg_stat_archiver 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +show_pg_stat_archiver - convenience program to extract info from the database +.SH SYNOPSIS +show_pg_stat_archiver +.SH DESCRIPTION +show_pg_stat_archiver is a convenience program to extract the pg_stat_archiver information from the database. diff --git a/pgaas/src/stage/opt/app/pgaas/man/show_pg_stat_bgwriter.man b/pgaas/src/stage/opt/app/pgaas/man/show_pg_stat_bgwriter.man new file mode 100644 index 0000000..a05a18a --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/show_pg_stat_bgwriter.man @@ -0,0 +1,20 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH show_pg_stat_bgwriter 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +show_pg_stat_bgwriter - convenience program to extract info from the database +.SH SYNOPSIS +show_pg_stat_bgwriter +.SH DESCRIPTION +show_pg_stat_bgwriter is a convenience program to extract the pg_stat_bgwriter information from the database. + diff --git a/pgaas/src/stage/opt/app/pgaas/man/show_pg_stat_database.man b/pgaas/src/stage/opt/app/pgaas/man/show_pg_stat_database.man new file mode 100644 index 0000000..5bbceb5 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/show_pg_stat_database.man @@ -0,0 +1,19 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH show_pg_stat_database 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +show_pg_stat_database - convenience program to extract info from the database +.SH SYNOPSIS +show_pg_stat_database +.SH DESCRIPTION +show_pg_stat_database is a convenience program to extract the pg_stat_database information from the database. diff --git a/pgaas/src/stage/opt/app/pgaas/man/show_pg_stat_database_conflicts.man b/pgaas/src/stage/opt/app/pgaas/man/show_pg_stat_database_conflicts.man new file mode 100644 index 0000000..d5b9b1f --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/show_pg_stat_database_conflicts.man @@ -0,0 +1,19 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH show_pg_stat_database_conflicts 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +show_pg_stat_database_conflicts - convenience program to extract info from the database +.SH SYNOPSIS +show_pg_stat_database_conflicts +.SH DESCRIPTION +show_pg_stat_database_conflicts is a convenience program to extract the pg_stat_database_conflicts information from the database. diff --git a/pgaas/src/stage/opt/app/pgaas/man/show_pg_stat_user_indexes.man b/pgaas/src/stage/opt/app/pgaas/man/show_pg_stat_user_indexes.man new file mode 100644 index 0000000..729e018 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/show_pg_stat_user_indexes.man @@ -0,0 +1,19 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH show_pg_stat_user_indexes 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +show_pg_stat_user_indexes - convenience program to extract info from the database +.SH SYNOPSIS +show_pg_stat_user_indexes +.SH DESCRIPTION +show_pg_stat_user_indexes is a convenience program to extract the pg_stat_user_indexes information from the database. diff --git a/pgaas/src/stage/opt/app/pgaas/man/show_pg_stat_user_tables.man b/pgaas/src/stage/opt/app/pgaas/man/show_pg_stat_user_tables.man new file mode 100644 index 0000000..39fa971 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/show_pg_stat_user_tables.man @@ -0,0 +1,20 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH show_pg_stat_user_indexes 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +show_pg_stat_user_tables - convenience program to extract info from the database +.SH SYNOPSIS +show_pg_stat_user_tables +.SH DESCRIPTION +show_pg_stat_user_tables is a convenience program to extract the pg_stat_user_tables information from the database. + diff --git a/pgaas/src/stage/opt/app/pgaas/man/show_pg_statio_user_functions.man b/pgaas/src/stage/opt/app/pgaas/man/show_pg_statio_user_functions.man new file mode 100644 index 0000000..171c161 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/show_pg_statio_user_functions.man @@ -0,0 +1,19 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH show_pg_statio_user_functions 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +show_pg_statio_user_functions - convenience program to extract info from the database +.SH SYNOPSIS +show_pg_statio_user_functions +.SH DESCRIPTION +show_pg_statio_user_functions is a convenience program to extract the pg_statio_user_functions information from the database. diff --git a/pgaas/src/stage/opt/app/pgaas/man/show_pg_statio_user_indexes.man b/pgaas/src/stage/opt/app/pgaas/man/show_pg_statio_user_indexes.man new file mode 100644 index 0000000..f54f0b5 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/show_pg_statio_user_indexes.man @@ -0,0 +1,19 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH show_pg_statio_user_indexes 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +show_pg_statio_user_indexes - convenience program to extract info from the database +.SH SYNOPSIS +show_pg_statio_user_indexes +.SH DESCRIPTION +show_pg_statio_user_indexes is a convenience program to extract the pg_statio_user_indexes information from the database. diff --git a/pgaas/src/stage/opt/app/pgaas/man/show_pg_statio_user_sequences.man b/pgaas/src/stage/opt/app/pgaas/man/show_pg_statio_user_sequences.man new file mode 100644 index 0000000..cc94f5a --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/show_pg_statio_user_sequences.man @@ -0,0 +1,19 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH show_pg_statio_user_sequences 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +show_pg_statio_user_sequences - convenience program to extract info from the database +.SH SYNOPSIS +show_pg_statio_user_sequences +.SH DESCRIPTION +show_pg_statio_user_sequences is a convenience program to extract the pg_statio_user_sequences information from the database. diff --git a/pgaas/src/stage/opt/app/pgaas/man/show_pg_statio_user_tables.man b/pgaas/src/stage/opt/app/pgaas/man/show_pg_statio_user_tables.man new file mode 100644 index 0000000..14afc43 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/show_pg_statio_user_tables.man @@ -0,0 +1,19 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH show_pg_statio_user_tables 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +show_pg_statio_user_tables - convenience program to extract info from the database +.SH SYNOPSIS +show_pg_statio_user_tables +.SH DESCRIPTION +show_pg_statio_user_tables is a convenience program to extract the pg_statio_user_tables information from the database. diff --git a/pgaas/src/stage/opt/app/pgaas/man/startpsql.man b/pgaas/src/stage/opt/app/pgaas/man/startpsql.man new file mode 100644 index 0000000..dc792f6 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/startpsql.man @@ -0,0 +1,21 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH startpsq 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +startpsql - run the psql command +.SH SYNOPSIS +startpsql +.SH DESCRIPTION +Locate the psql command and run it. +.SH "SEE ALSO" +runpsql, runpsqll diff --git a/pgaas/src/stage/opt/app/pgaas/man/update_var_run_isrw.man b/pgaas/src/stage/opt/app/pgaas/man/update_var_run_isrw.man new file mode 100644 index 0000000..bc5ecc8 --- /dev/null +++ b/pgaas/src/stage/opt/app/pgaas/man/update_var_run_isrw.man @@ -0,0 +1,23 @@ +'\" Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +'\" +'\" Licensed under the Apache License, Version 2.0 (the "License"); +'\" you may not use this code 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. +.TH startpsq 1PG {{DATE}} OpenECOMP OpenECOMP +.SH NAME +update_var_run_isrw - update the /var/run/postgresql/isrw file +.SH SYNOPSIS +update_var_run_isrw +.SH DESCRIPTION +This program updates the /var/run/postgresql/isrw file using the output of the isrw(1PG) command. +The file is updated 6 times separated by 10 seconds. +It is meant to be run from the postgres cron. +.SH "SEE ALSO" +isrw |