Skip to content

Commit

Permalink
Merge pull request #108 from ibotlold/postgresql
Browse files Browse the repository at this point in the history
Creating database using postgres
  • Loading branch information
liviuchircu authored Oct 17, 2023
2 parents 161b5ea + 16ba5fd commit af872f0
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 36 deletions.
2 changes: 1 addition & 1 deletion docs/modules/database.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Consider the following configuration file:
#database_modules: acc clusterer dialog dialplan dispatcher domain rtpproxy usrloc
database_modules: ALL
#database_admin_url: postgres://root@localhost
#database_admin_url: postgresql://root@localhost
database_admin_url: mysql://root@localhost
```

Expand Down
50 changes: 23 additions & 27 deletions opensipscli/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@

SUPPORTED_BACKENDS = [
"mysql",
"postgres",
"postgresql",
"sqlite",
"oracle",
]
Expand Down Expand Up @@ -225,7 +225,7 @@ def __init__(self, db_url, db_name):
raise
except:
logger.error("unexpected parsing exception")
elif self.dialect == "postgres" and \
elif self.dialect == "postgresql" and \
(("authentication" in se.args[0] and "failed" in se.args[0]) or \
("no password supplied" in se.args[0])):
raise osdbAccessDeniedError
Expand All @@ -243,7 +243,7 @@ def alter_role(self, role_name, role_options=None, role_password=None):
alter attributes of a role object
"""
# TODO: is any other dialect using the "role" concept?
if self.dialect != "postgres":
if self.dialect != "postgresql":
return False

# TODO: do this only for SQLAlchemy
Expand Down Expand Up @@ -277,7 +277,7 @@ def connect(self, db_name=None):
# TODO: do this only for SQLAlchemy

try:
if self.dialect == "postgres":
if self.dialect == "postgresql":
self.db_url = self.set_url_db(self.db_url, self.db_name)
if sqlalchemy_utils.database_exists(self.db_url) is True:
engine = sqlalchemy.create_engine(self.db_url, isolation_level='AUTOCOMMIT')
Expand Down Expand Up @@ -312,7 +312,7 @@ def create(self, db_name=None):
self.db_name, self.dialect)

# all good - it's time to create the database
if self.dialect == "postgres":
if self.dialect == "postgresql":
self.__conn.connection.connection.set_isolation_level(0)
try:
self.__conn.execute("CREATE DATABASE {}".format(self.db_name))
Expand Down Expand Up @@ -408,7 +408,7 @@ def ensure_user(self, db_url):
logger.exception("failed to flush privileges")
return False

elif url.drivername.lower() == "postgres":
elif url.drivername.lower() == "postgresql":
if not self.exists_role(url.username):
logger.info("creating role %s", url.username)
if not self.create_role(url.username, url.password):
Expand Down Expand Up @@ -437,7 +437,7 @@ def create_role(self, role_name, role_password, update=False,
create a role object (PostgreSQL secific)
"""
# TODO: is any other dialect using the "role" concept?
if self.dialect != "postgres":
if self.dialect != "postgresql":
return False

# TODO: do this only for SQLAlchemy
Expand Down Expand Up @@ -517,7 +517,7 @@ def drop_role(self, role_name):
drop a role object (PostgreSQL specific)
"""
# TODO: is any other dialect using the "role" concept?
if self.dialect != "postgres":
if self.dialect != "postgresql":
return False

# TODO: do this only for SQLAlchemy
Expand Down Expand Up @@ -615,7 +615,7 @@ def exists_role(self, role_name=None):
check for existence of a role object (PostgreSQL specific)
"""
# TODO: is any other dialect using the "role" concept?
if self.dialect != "postgres":
if self.dialect != "postgresql":
return False

# TODO: do this only for SQLAlchemy
Expand Down Expand Up @@ -696,7 +696,7 @@ def get_role(self, role_name="opensips"):
get attibutes of a role object (PostgreSQL specific)
"""
# TODO: is any other dialect using the "role" concept?
if self.dialect != "postgres":
if self.dialect != "postgresql":
return False

# TODO: do this only for SQLAlchemy
Expand All @@ -716,39 +716,35 @@ def get_role(self, role_name="opensips"):
print (key + ": " + dict[key])
logger.debug("role_elements: %s", dict)

def grant_db_options(self, role_name="opensips", role_options="ALL PRIVILEGES"):
def grant_db_options(self, role_name, on_statement, privs="ALL PRIVILEGES"):
"""
assign attibutes to a role object (PostgreSQL specific)
"""
# TODO: is any other dialect using the "role" concept?
if self.dialect != "postgres":
if self.dialect != "postgresql":
return False

# TODO: do this only for SQLAlchemy
if not self.__conn:
raise osdbError("connection not available")

return True

def grant_table_options(self, role, table, privs="ALL PRIVILEGES"):
if self.dialect != "postgres":
return False

if not self.__conn:
raise osdbError("connection not available")

sqlcmd = "GRANT {} ON TABLE {} TO {}".format(privs, table, role)

sqlcmd = "GRANT {} {} TO {}".format(privs, on_statement, role_name)
logger.info(sqlcmd)

try:
result = self.__conn.execute(sqlcmd)
self.__conn.execute(sqlcmd)
except Exception as e:
logger.exception(e)
logger.error("failed to grant '%s' to '%s' on table '%s'",
privs, role, table)
logger.error("failed to grant '%s' '%s' to '%s'", privs, on_statement, role_name)
return False

return True

def grant_public_schema(self, role_name):
self.grant_db_options(role_name, "ON SCHEMA public")

def grant_table_options(self, role, table, privs="ALL PRIVILEGES"):
self.grant_db_options(role, "ON TABLE {}".format(table))

def has_sqlalchemy():
"""
Expand Down Expand Up @@ -963,7 +959,7 @@ def get_url_driver(url, capitalize=False):
driver = make_url(url).drivername.lower()
capitalized = {
'mysql': 'MySQL',
'postgres': 'PostgreSQL',
'postgresql': 'PostgreSQL',
'sqlite': 'SQLite',
'oracle': 'Oracle',
}
Expand Down
35 changes: 28 additions & 7 deletions opensipscli/modules/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -499,12 +499,12 @@ def get_admin_db_url(self, db_name):

if cfg.exists('database_admin_url'):
admin_url = cfg.get("database_admin_url")
if engine == "postgres":
if engine == "postgresql":
admin_url = osdb.set_url_db(admin_url, 'postgres')
else:
admin_url = osdb.set_url_db(admin_url, None)
else:
if engine == 'postgres':
if engine == 'postgresql':
if getuser() != "postgres":
logger.error("Command must be run as 'postgres' user: "
"sudo -u postgres opensips-cli ...")
Expand All @@ -513,7 +513,7 @@ def get_admin_db_url(self, db_name):
"""
For PG, do the initial setup using 'postgres' as role + DB
"""
admin_url = "postgres://postgres@localhost/postgres"
admin_url = "postgresql://postgres@localhost/postgres"
else:
admin_url = "{}://root@localhost".format(engine)

Expand Down Expand Up @@ -707,12 +707,15 @@ def create_tables(self, db_name, db_url, admin_db, tables=[],
username = osdb.get_url_user(db_url)
admin_db.connect(db_name)

if db.dialect == "postgresql":
self.pg_grant_schema(username, admin_db)

# create tables from SQL schemas
for module, table_file in table_files.items():
logger.info("Running {}...".format(os.path.basename(table_file)))
try:
db.create_module(table_file)
if db.dialect == "postgres":
if db.dialect == "postgresql":
self.pg_grant_table_access(table_file, username, admin_db)
except osdbModuleAlreadyExistsError:
logger.error("{} table(s) are already created!".format(module))
Expand Down Expand Up @@ -772,7 +775,7 @@ def do_drop(self, params=None, modifiers=None):
if db_url is None:
return -1

if db_url.lower().startswith("postgres"):
if db_url.lower().startswith("postgresql"):
db_url = osdb.set_url_db(db_url, 'postgres')
else:
db_url = self.get_db_url(db_name)
Expand Down Expand Up @@ -931,8 +934,20 @@ def get_schema_path(self, backend="mysql"):
logger.error("path '{}' to OpenSIPS DB scripts is not a directory!".
format(db_path))
return None

schema_path = os.path.join(db_path, backend)

def build_schema_path(db_path, backend):
"""
Replaces schema path of postgresql to old postgre schema path if exists.
Should be deleted after opensips main repo refactors folder name to the new backend name.
"""
if backend == "postgresql":
old_postgre_path = os.path.join(db_path, "postgres")
if os.path.isdir(old_postgre_path):
return old_postgre_path
schema_path = os.path.join(db_path, backend)
return schema_path

schema_path = build_schema_path(db_path, backend)
if not os.path.isdir(schema_path):
logger.error("invalid OpenSIPS DB scripts dir: '{}'!".
format(schema_path))
Expand Down Expand Up @@ -962,3 +977,9 @@ def pg_grant_table_access(self, sql_file, username, admin_db):
if res:
seq = res.group(1)
admin_db.grant_table_options(username, seq)

def pg_grant_schema(self, username, admin_db):
"""
Grant access to public schema of DB
"""
admin_db.grant_public_schema(username)
2 changes: 1 addition & 1 deletion test/test-database.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ CLI_CFG=/tmp/.__cli.cfg
DB_NAME=_opensips_cli_test

MYSQL_URL=mysql://opensips:opensipsrw@localhost
PGSQL_URL=postgres://opensips:opensipsrw@localhost
PGSQL_URL=postgresql://opensips:opensipsrw@localhost

TESTS=(
test_mysql_drop_1_prompt
Expand Down

0 comments on commit af872f0

Please sign in to comment.