This is part III of the article, see Part I here and Part II here.

Creating the seed docbase

See dbi services for its source. Hereafter, only some salient steps are presented, refer to the script for the details.

As its name implies, the script create_docbase.sh is used to create a docbase optionally to be used later as a seed. Its usage is:

$ ./create_docbase.sh [stem]

where the optional stem in global_parameters defaults to DCTM0 and points to the docbase’s required settings. It is executed as the installation owner, usually dmadmin.

After the global_parameters file is sourced with the given stem, the installation directory is created and all the needed software packages (the JDK, the Oracle Instant Client and SQL*Plus if the Oracle RDBMS is chosen, the PostgreSQL source tarball global_parameters.${postgresql_package} otherwise) are downloaded into the directory global_parameters.${dctm_software}, only if they are not there yet. After their downloading, the packages are expanded and the software installed and configured as advised in the OpenText documentation. For example, the anonymous algorithm for secure communication with the content server is reinstated in the JDK from its default disabled state.

If the selected RDBMS is PostgreSQL, its installation is completely customized. In effect, the platform’s standard PostgreSQL package is normally installed system-wide by root with pieces scattered in several locations, e.g. /var/lib and /usr/lib. As we want to embed this RDBMS with the repository and under the dmadmin ownership, this is not convenient; we want all the pieces in one directory tree root. In order to make this possible, we need to compile the source code specifying the installation directory ${ACTIVE_DOCBASE_ROOT}/postgresql. The binary and data files will all be installed under this directory, which will later be included in the compressed tar ball when the script completes executing. As the compilation takes several minutes and even though it only needs to be done once, a pre-compiled tarball global_parameters.${postgresql_custom_package} is available so this step can be skipped, unless global_parameters.${postgresql_compile} is set to “yes“.

After the PostgreSQL binaries have been extracted or compiled, the ODBC connectivity is configured. Surprisingly, Documentum’s configuration program imperatively needs a connect string named postgres and defined in /etc/odbc.ini as if it were hard-coded. Apparently, it reads this file explicitly instead of relying on the ODBC API which looks for any specified connect string first in ~/.odbc.ini and lastly in /etc/odbc.ini. Also, it requires the running PostgresSQL server to be listening on the default port 5432 instead of any port defined in the ini file. Strangely enough, and this is visible when using the configuration program interactively, ~/.odbc.ini is correctly used and validated but only until the program effectively starts creating the docbase, where it switches to /etc/odbc.ini and the weird behavior. The documentation mentions changes to be done in ODBC.INI but does not say where it is (it’s in /etc but ~/.odbc.ini should be used preferably). Also, it incorrectly says that the connect string should be [MyPostgres] whereas it should be anything, although only [postgres] works at this stage. All this suggests that the ODBC part is not well mastered by developpers of the installation program, or that it was ported without much attention from some other O/S. Fortunately, these idiosyncrasies are abandoned after the docbase is created and all the parameters set in the installer owner’s ~/.odbc.ini are honored, e.g. custom connect string and database server port.

Here is how /etc/odbc.ini must look for the docbase creation to start:

[postgres]
Description = PostgreSQL connection to postgres
Driver = PostgreSQL Unicode
Database = postgres
Servername = ${db_server_host_alias}
UserName = ${dctm_owner}
# hard-coded in the server configuration tool;
Port = 5432

and here is the final ~/.odbc.ini file defined after the docbase creation, including some of the recommended database settings:

[${db_connect_string}]
Description = PostgreSQL connection to ${ACTIVE_DOCBASE}
Driver = PostgreSQL Unicode
Database = ${ACTIVE_DOCBASE}
Servername = ${db_server_host_alias}
UserName = ${dctm_owner}
Port = ${ACTIVE_DB_SERVER_PORT}
Protocol = $(echo ${postgresql_custom_package} | sed -E 's/.+-([0-9]+).*$/\1/')
ReadOnly = No
RowVersioning = No
ShowSystemTables = No
ShowOidColumn = No
FakeOidIndex = No
UpdateableCursors = Yes

The shell variables get expanded when the file is saved.

Another requirement with the postgreSQL RDBMS is that the installer demands a directory named db_${ACTIVE_DOCBASE}_dat.dat for the datafile to be created beforehand; if not found, the installer fails.

When using the Oracle RDBMS, a global_parameters.${dctm_root}/docbase/oracle/instantclient_21_7/network/admin/tnsnames.ora file gets created with the following content:

${db_connect_string} =
   (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)
                             (HOST = ${db_server_host_alias})(PORT = ${db_listener_port}
                             )
                  )
                  (CONNECT_DATA =
                     (SERVER = DEDICATED)
                     (SERVICE_NAME = ${db_service_name})
                  )
   )

Next, the data and index tablespaces are created and finally the schema account with the required grants. Here is a summary of the database requirements for Oracle:

select TABLESPACE_NAME, ALLOCATION_TYPE from dba_tablespaces order by 1;
TABLESPACE_NAME          ALLOCATION_TYPE
------------------------------ ---------------------------
DCTM1_DATA            SYSTEM
DCTM1_INDEX           SYSTEM
...
SEED_DATA             SYSTEM
SEED_INDEX            SYSTEM

SQL> select privilege from dba_sys_privs where grantee = upper('dctm1');
GRANTEE                        PRIVILEGE                      ADMIN_OPT COMMON
------------------------------ ------------------------------ --------- ---------
DCTM1                          CREATE VIEW                    NO        NO
DCTM1                          CREATE ANY VIEW                NO        NO
DCTM1                          CREATE SEQUENCE                NO        NO
DCTM1                          CREATE PROCEDURE               NO        NO
DCTM1                          CREATE TABLE                   NO        NO

SQL> select * from dba_role_privs where grantee = upper('dctm1');
GRANTEE                        GRANTED_ROLE                   ADMIN_OPT DEFAULT_R COMMON
------------------------------ ------------------------------ --------- --------- ---------
DCTM1                          CONNECT                        NO        YES       NO
DCTM1                          RESOURCE                       NO        YES       NO
DCTM1                          SELECT_CATALOG_ROLE            NO        YES       NO

SQL> select TABLESPACE_NAME, STATUS, ALLOCATION_TYPE, SEGMENT_SPACE_MANAGEMENT from user_tablespaces;
TABLESPACE_NAME                STATUS                      ALLOCATION_TYPE             SEGMENT_SPACE_MANA
------------------------------ --------------------------- --------------------------- ------------------
DCTM1_DATA                     ONLINE                      SYSTEM                      AUTO
DCTM1_INDEX                    ONLINE                      SYSTEM                      AUTO

After the database steps have been completed, the documentum’s installer program serverSetup.bin is launched with the following generated on-the-fly response file:

INSTALLER_UI=silent
KEEP_TEMP_FILE=true
common.installOwner.password=dmadmin
SERVER.SECURE.ROOT_PASSWORD=root

# documentum binaries;
SERVER.DOCUMENTUM=${ACTIVE_ROOT}/documentum
APPSERVER.SERVER_HTTP_PORT=${ACTIVE_SERVER_HTTP_PORT}
APPSERVER.SECURE.PASSWORD=tomcat

# java;
PATH_TO_JAVA=$(ls -d ${ACTIVE_ROOT}/java/amazon-corretto-11*-linux-x64)

This step takes several minutes to complete but it does not matter; as said previously, the real optimization occurs in the instantiation step, not in the installation of the binaries or the creation of the model docbase; those steps are done only once (unless it is done outside the context of this project).

Method servers are dedicated to each docbase and receive a distinct base port number defined as global_properties.${stem_SERVER_HTTP_PORT}. Later during the instantiation, their memory sizing will be configured as set in global_properties.${stem_SERVER_HTTP_MEMORY}.

It has been noticed that the method server creates several cache directories (e.g. felix-cache and activemq-data) in the directory it is started from; to move them out of the way and prevent cluttering, the command cd ${DM_JMS_HOME}/temp is later inserted in startMethodServer.sh before tomcat’s startup.sh script is invoked.

After the binaries have been installed, a connectivity check using documentum’s dmdbtest is performed to confirm that the database is reachable via SQL*Net for Oracle or via ODBC for PostgreSQL. This test differs from the ones previously done directly at the database level in that it is performed by documentum. Its output resembles the following one:

if [[ "${ACTIVE_RDBMS}" == "oracle" ]]; then
   ${DOCUMENTUM}/product/*/bin/dmdbtest -Dxx -S${db_connect_string} -U${ACTIVE_DOCBASE} -P${ACTIVE_DOCBASE}
else
   ${DOCUMENTUM}/product/*/bin/dmdbtest -Dpostgres -Spostgres -U${dctm_owner} -Pxxx
fi
Database successfully opened.
Test table successfully created.
Test view successfully created.
Test index successfully created.
Insert into table successfully done.
Index successfully dropped.
View successfully dropped.
Database case sensitivity test successfully past.
Table successfully dropped.

Note that the above test needs an extra step when using Oracle RDBMS because although the sqlplus executable is installed in Instant Client’s ${ORACLE_HOME} and ${ORACLE_HOME} is in the ${PATH}, the installer expects it in the non-existing ${ORACLE_HOME}/bin. So, that directory must be created beforehand and sqlplus symlinked there. Evidently, sqlplus’ expected location is hard-coded and the ${ORACLE_HOME} environment variable is either not passed to the java programs invoked by the installer script, or ignored when looking for it. This quirk can be half-forgiven as it is a documented requirement.

Since several docbases can potentially be instantiated and run on the same machine, an environment file named docbase_name.env for each of them is prepared to allow switching easily between them. This file notably defines the ${DOCUMENTUM} and ${PATH} variables, invokes documentum’s own dm_set_server_env.sh, and should be sourced prior to working with a given docbase. To simplify this, the bash function swr() (which stands for SWitch Repository) has been defined in the installation owner’s ~/.profile. Other useful management functions such as sur()and sdr(), have also been defined in docbase_name.env, see down below.

Next, another response file is prepared to install the docbroker. docbrokers too are dedicated to each docbase and defined in the global_properties file with parameters stem_DOCBROKER_NAME and stem_DOCBROKER_PORT. Make sure there is no port conflict when creating/instantiating new docbases. Here is an example of this response file:

KEEP_TEMP_FILE=true
PATH_TO_JAVA=$(ls -d ${ACTIVE_ROOT}/java/amazon-corretto-11*-linux-x64)
INSTALLER_UI=silent
common.aek.algorithm=AES_128_CBC

# docbroker;
SERVER.CONFIGURATOR.BROKER=TRUE
SERVER.DOCBROKER_ACTION=CREATE
SERVER.DOCBROKER_PORT=${ACTIVE_DOCBROKER_PORT}
SERVER.DOCBROKER_NAME=${ACTIVE_DOCBROKER_NAME}
SERVER.PROJECTED_DOCBROKER_HOST=$(hostname)
SERVER.PROJECTED_DOCBROKER_PORT=${ACTIVE_DOCBROKER_PORT}
SERVER.DOCBROKER_CONNECT_MODE=native
SERVER.USE_CERTIFICATES=false

Make sure the docbroker name does not contains any non alphanumeric characters as the installer is quite restrictive in this regard. For example, the name docbroker_01 is rejected because it contains an underscore.

Documentum’s dm_launch_server_config_program.sh is then invoked with that response file and the docbroker gets created and started along with the method server.

Next, another response file is prepared for the repository. Its most complicated part is the conditional definitions for Oracle and PostgreSQL:

$ cat - <<eot > ${ACTIVE_DOCBASE}.properties
INSTALLER_UI=silent
KEEP_TEMP_FILE=true
...
############################### database stuff #######################################
SERVER.USE_EXISTING_DATABASE_ACCOUNT=$(if [[ "${ACTIVE_RDBMS}" == "oracle" ]]; then echo "true"; else echo "false"; fi)
$(if [[ "${ACTIVE_RDBMS}" == "postgres" ]]; then echo "SERVER.DATABASE_NAME=${ACTIVE_DOCBASE}"; fi)
SERVER.INDEXSPACE_NAME=$(if [[ "${ACTIVE_RDBMS}" == "oracle" ]]; then echo "${ACTIVE_DOCBASE}_INDEX"; else echo "db_${ACTIVE_DOCBASE}_log"; fi)
# postgres is hard-coded in the server configuration script;
SERVER.DATABASE_CONNECTION=$(if [[ "${ACTIVE_RDBMS}" == "oracle" ]]; then echo "${db_connect_string}"; else echo "postgres"; fi)
SERVER.DOCBASE_OWNER_NAME=${ACTIVE_DOCBASE}
SERVER.SECURE.DOCBASE_OWNER_PASSWORD=${ACTIVE_DOCBASE}
SERVER.DATABASE_ADMIN_NAME=$(if [[ "${ACTIVE_RDBMS}" == "oracle" ]]; then echo "${ACTIVE_DOCBASE}"; else echo "${dctm_owner}"; fi)
SERVER.SECURE.DATABASE_ADMIN_PASSWORD=$(if [[ "${ACTIVE_RDBMS}" == "oracle" ]]; then echo "${ACTIVE_DOCBASE}"; else echo "${dctm_password}"; fi)
$(if [[ "${ACTIVE_RDBMS}" == "postgres" ]]; then echo "SERVER.POSTGRES_USE_DEFAULT_SPACE=false"; fi)
...

Refer to the code on dbi services‘s git for the complete settings. Detailed explanations about the content server’s response file parameters can also be found here Documentum – Silent Install – Docbases/Repositories. There are articles on our blog site about the response files for other Documentum components too, so it may be worth giving them a look. Links to all of them can be found here.

After the configuration program is invoked with the above response file and completes, the documentum processes are shut down and, if using Oracle, the resulting seed’s database schema will be extracted using the traditional exp utility. Although the exp and imp utilities have been superseded by the data pump for a while now, they do their job well enough for repositories’ schemas. Of course, the more modern data pump can also be used instead under certain conditions, but it may need some preliminary work on the database’s side to accommodate it. The same applies if using the Instant Client’s exp and imp utilities when these tools’ version differs from the database’s. For example, one of our test database is a v12.1.0.1.0 one but there are no downloadable exp and imp tools with that version for the Instant Client as they started being included only in v12.2.0.x (cf. https://download.oracle.com/otn/linux/instantclient/122010/instantclient-basic-linux.x64-12.2.0.1.0.zip and https://download.oracle.com/otn/linux/instantclient/122010/instantclient-tools-linux.x64-12.2.0.1.0.zip). And since those versions differ from the database’s, a PL/SQL package must be executed so they can be used. All this is quite complicated and to simplify the data extraction and import tasks, we will use the exp and imp utilities bundled with the RDBMS; those will always work as-is so no additional download nor configuration are necessary. However, those tools need to be invoked from within a remote session, hence the settings global_parameters.${db_server_host_*}, unless those steps are delegated to the DBAs. As already discussed, Oracle RDBMS is a proprietary, closed-source and quite complex software. Starting with the licensing, it requires some careful planning. Sometimes, databases are even shared between several applications. Therefore, it is mostly managed by specialized people in an organization and installed in dedicated machines. For those reasons, the Oracle part takes up a large chunk of the procedure dedicated to the RDBMS and, for faster and more agile configuration, the leaner but sufficient PostgreSQL RDBMS is preferred. As precedently written, the postgreSQL source is compiled so it can be embedded with the docbase that uses it and the whole binaries and database get copied into the tar ball, which is a considerable simplification at a measly cost of 276 Mb.

After the compressed tar ball is produced, it is renamed to ${ACTIVE_DOCBASE}_${ACTIVE_RDBMS}.tgz and moved to the ${scripts_dir} if one with the same name does not exist there yet (otherwise, the move is not performed), ready to be instantiated as needed.

A useful by-product of this project, although it won’t benefit from the optimized provision time, the generic script create_docbase.sh creates any docbase whose parameters are set in global_parameters. Once created, this docbase can be used stand-alone, or taken a snapshot of and used as a seed for future instantiations, or both. It can even be uncompressed in several places on the same machine or on different machines as distinct clones, provided resource conflicts are resolved and the usual well-known adjustments post-cloning are applied. The script can create several docbases to be used as models for different purposes after further customizations; edit the script as required.

It is possible to specify as many docbases to be created (or instantiated, see later) in global_parameters.${dctm_machine} as needed by specifying their stems on the command-line. So, if several docbases need be created, define them all in global_parameters and invoke the creation script as follows:

# Example:
$ for i in {1..10}; do
   ./create_docbase.sh "DCTM${i}"
done
where DCTM1_* to DCTM10_* are the respective docbases's stem "pointing" to the settings defined in the global_properties file.

# Another example with unrelated stems:
./create_docbase.sh bookstore
./create_docbase.sh product_catalog
./create_docbase.sh research_papers

Concurrent docbase creation would be another useful by-product of the project and should be possible because each created docbase is normally stand-alone (i.e. no dependency on other services such as the docbroker or the method server) and has a distinct ${DOCUMENTUM} directory under global_parameters.${dctm_root}/docbase_name. Unfortunately, Documentum’s installer program does not permit more than one running instance of itself:

Installing the CS binaries documentum_server_22.4_linux64_oracle.tar ...
Preparing to install
Extracting the installation resources from the installer archive...
Configuring the installer for this system's environment...

Launching installer...

Multiple launches of this installer is not allowed. It will now quit.

The configuration program dm_launch_server_config_program.sh, however, does not have this limitation, probably because it is enough for it to run in its own ${DOCUMENTUM}.

Granted, when using PostgreSQL , since the docbase creation demands a server listening on port 5432, there may be a short period of time when a server gets commonly used by several instances of dm_launch_server_config_program.sh. Also, multiple database server instances get started on port 5432, but with only the first one succeeding. Still, this should not be an issue since the databases and their locations are distinct. This glitch does not happen at instantiation time as the PostgreSQL server is always started from the beginning with a custom port.

The additional cost is 2 Gb of disk space since the documentum binaries are not shared between the repositories (i.e. each repository has its own ${DOCUMENTUM} and its own copy of the binaries), but disk space is so cheap these days that this is not prohibitive. When using Oracle, the above concurrency behavior does not apply.

As mentioned before, create_docbase.sh sets up a sourceable script to define a working docbase’s environment and several useful functions, global_properties.${dctm_root}/docbase/docbase.env. In particular, it defines:

${ACTIVE_DOCBASE}, ${ACTIVE_ROOT}, ${JAVA_HOME}, ${DOCUMENTUM} and ${PATH}, and sources documentum’s own dm_set_server_env.sh. ${ACTIVE_DOCBASE} is the name of the current repository and ${ACTIVE_ROOT} the root directory that contains that docbase’s ${JAVA_HOME}, ${DOCUMENTUM} and the postgres root directory if that RDBMS is used. ${ACTIVE_ROOT} is also equal to global_properties.${dctm_root}/docbase.

In addition to those environment variables, several management functions are defined too; see the paragraph Management Commands in Part V.

For more comfort, the environment file also changes the shell’s prompt to something nicer, e.g.:

dmadmin@cs2:[/u01/dctm/repo03][repo03] $

The prompt shows the currently logged user and the machine it is logged on, the current working directory, and the current active docbase, which is useful to prevent manipulating the wrong docbase when several of them coexist in the machine.

See Part IV here