Creating and Using an Installation Manifest
This chapter describes how to use the %Installer utility to create an installation manifest describing a specific Caché configuration and use it to generate code to configure a Caché instance. The chapter discusses the following topics:
Overview of an Installation Manifest
The %Installer utility lets you define an installation manifest that describes a specific Caché configuration, rather than a step-by-step installation process. To do so, you create a class that contains an XData block describing the configuration you want, using variables that contain information usually provided during installation (superserver port, operating system, and so on). You also include in the class a method that uses the XData block to generate code to configure the instance. (You can copy and paste this method from this book.)
Once you have defined the manifest, you can call it during installation, from a Terminal session, or from code. The manifest must be run in the %SYS namespace.
Creating a Class That Defines a Manifest
To create a class that defines an installation manifest, create a class as follows:
-
It must include the %occInclude include file.
-
It must contain an XData block specifying the details of the installation.
You can specify any legal name for the XData block; you use this name later as an argument.
If you use [XMLNamespace = INSTALLER] after the name of the XData block, Studio provides assistance as you type the XData block.
The root element in the XData block must be <Manifest>. For details, see “<Manifest> Tags”.
-
It must define the setup() method, as shown in the following example.
-
The setup() method must refer to the XData block by name as shown in the following example.
The following is an example:
Include %occInclude
Class MyPackage.MyInstaller
{
XData MyInstall [ XMLNamespace = INSTALLER ]
{
<Manifest>
<Var/>
<If/>
<Log/>
<User/>
<Resource/>
<Role/>
<SystemSetting/>
<ForEach>
<!--Code for each iteration of named Index key while looping through values-->
</ForEach>
<CopyDir/>
<CopyFile/>
<Namespace>
<Configuration>
<Database/>
<ForEach>
<!--Code for each iteration of named Index key while looping through values-->
</ForEach>
<Log/>
<GlobalMapping/>
<RoutineMapping/>
<ClassMapping/>
</Configuration>
<Compile/>
<CopyClass/>
<CSPApplication/>
<ForEach>
<!--Code for each iteration of named Index key while looping through values-->
</ForEach>
<If/>
<Import/>
<Invoke/>
</Namespace>
</Manifest>
}
ClassMethod setup(ByRef pVars, pLogLevel As %Integer = 3,
pInstaller As %Installer.Installer,
pLogger As %Installer.AbstractLogger)
As %Status [ CodeMode = objectgenerator, Internal ]
{
#; Let XGL document generate code for this method.
Quit ##class(%Installer.Manifest).%Generate(%compiledclass,
%code, "MyInstall")
}
}
Key Options
The outermost XML tag, <Manifest>, contains all the information for code generation. There can be as many <Namespace> tags as needed within the <Manifest> tag to define namespaces in the manifest.
A <Configuration> tag, which is located inside a <Namespace> tag, is required only if databases and/or mappings are being defined. There must be as many <Database> tags within the <Configuration> tag as are needed to define the namespace. In addition, following each <Database> tag, you can add <GlobalMapping>, <RoutineMapping>, and <ClassMapping> tags as required. The </Configuration> tag activates the defined mappings.
Within the context of a <Namespace> tag — after the databases and their mappings have been defined — globals can be loaded, and routines and classes can be loaded and compiled using <Import> tag. Class methods can be invoked using the <Invoke> tag. Invoked class methods can execute routines and access globals that have been imported.
Optionally, you can define variable pairs with the <Var> tag; each variable must specify a name and value. When the value for the <Var> is needed, the name is referenced by the ${NameAssigned} syntax.
For an example, see “Example” later in this chapter.
Adding Users and Passwords
There are several ways to add users (including their roles and passwords) to the installed instance, as follows:
-
Using the Management Portal after installation is complete, as described in the Caché Security Administration Guide.
-
Using the <User> tag in the manifest, as described in in <Manifest> Tags.
The PasswordVar parameter of the <User> tag specifies the variable containing the password for the user; for example, by defining PasswordVar="Pwd", you are specifying that the value of the variable Pwd is the password for a user. There are a variety of ways to populate this variable, but it is ultimately up to you to do this. You might consider using a remote method invocation to another instance of Caché or a web service; the problem with these approaches is that the server that is installing Caché may need internet access. Other possibilities include importing the method you are using to the instance you are installing, or adding a client-side form to the install that prompts for users and passwords, which can be passed to your manifest.
-
Using the Security.UsersOpens in a new tab class on a staging instance of Caché or Ensemble, as follows:
-
Export the user information by using the Security.Users.Export()Opens in a new tab method.
-
Import the user information by adding the following at the beginning of your manifest class (in the %SYS namespace):
<Invoke Class="Security.Users" Method="Import" CheckStatus="true"> <Arg Value="PathToExportedUserInformation"/> </Invoke>
where PathToExportedUserInformation is the location of the output file specified in the Security.Users.Export()Opens in a new tab method.
-
Adding Messages
You can define messages to be added to the log by incorporating <Log> tags in your class, in the following format:
<Log Level="<level>" Text="<text>"/>
The log level must be in the range of 0 to 3, where 0 is “none” and 3 is “verbose”; if the log level specified in the setup() method is equal to or greater than the Level property in the <Log> tag, the message is logged. The text is limited to 32,000 characters.
You set the log level via the second argument of the setup() method (for more information, see “Using the Manifest” later in this chapter). Since this cannot be passed to the manifest from the install, you must set it in the class as follows:
ClassMethod setup(ByRef pVars, pLogLevel As %Integer = 3,
pInstaller As %Installer.Installer,
pLogger As %Installer.AbstractLogger)
As %Status [ CodeMode = objectgenerator, Internal ]
You can direct where messages are displayed via the fourth argument (%Installer.AbstractLogger) of the setup() method; for example, if you instantiate a %Installer.FileLogger object referencing an operating system file, all %Installer and log messages are directed to that file. (Without this argument, all messages are written to the primary device if setup() is called directly, and are ignored if it is executed by the installer.)
Variables Available within <Manifest>
The following table lists the predefined variables that you can use in the manifest:
Variable Name | Description |
---|---|
SourceDir | (Available only when the installer is run) Directory from which the installation (setup_cache.exe or cinstall) is running. |
ISCUpgrade | (Available only when the installer is run) Indicates whether this is a new installation or an upgrade. This variable is either 0 (new installation) or 1 (upgrade). |
CFGDIR | See INSTALLDIR. |
CFGNAME | Instance name. |
CPUCOUNT | Number of operating system CPUs. |
CSPDIR | CSP directory. |
HOSTNAME | Name of the host server. |
HTTPPORT | Web server port. |
INSTALLDIR | Directory into which Caché is installed. |
MGRDIR | Manager (mgr) directory. |
PLATFORM | Operating system. |
PORT | Caché superserver port. |
PROCESSOR | Processor chip. |
VERSION | Caché version number. |
Using the Manifest
You can use the manifest as follows:
-
In the %SYS namespace, enter the following command in the Terminal:
%SYS>Do ##class(MyPackage.MyInstaller).setup()
You can pass an array by reference to the setup() method where the subscript is used as a variable in the <Manifest> and the node value is the variable <value>. For example:
%SYS>Set vars("SourceDir")="c:\myinstaller" %SYS>Set vars("Updated")="Yes" %SYS>Do ##class(MyPackage.MyInstaller).setup(.vars,3)
In this example, the second argument (3) is the log level.
-
Export the manifest class as DefaultInstallerClass.xml to the same directory where the Caché install (either .msi, setup_cache.exe, or cinstall) is run. It is imported into %SYS and compiled, and the setup() method is executed.
Note that if you use the export technique, you cannot pass arguments directly to the setup() method. However, you can do the following:
-
On Microsoft Windows systems (see the chapter “Installing Caché on Microsoft Windows”), you can modify the .msi install package to pass variable name/value pairs to the setup() method. You can also use command-line arguments with the installer to pass the location of the exported manifest class, variable pairs, log file name, and log level, as shown in the following example:
setup.exe INSTALLERMANIFEST="c:\MyStuff\MyInstaller.xml" INSTALLERMANIFESTPARAMS="SourceDir=c:\mysourcedir,Updated=Yes" INSTALLERMANIFESTLOGFILE="installer_log" INSTALLERMANIFESTLOGLEVEL="2"
Note:Variable names passed using the INSTALLERMANIFESTPARAMS argument may contain only alphabetic and numeric characters (A-Za-z0-9) and underscores (_), and may not start with an underscore.
-
On UNIX®, Linux, macOS systems (see the chapter “Installing Caché on UNIX®, Linux, and macOS”), you can set environment variables to define the location of the exported manifest class, variable name/value pairs, log file name, and log level prior to running either cinstall or cinstall_silent, as shown in the following example:
ISC_INSTALLER_MANIFEST="/MyStuff/MyInstaller.xml" ISC_INSTALLER_PARAMETERS="SourceDir=/mysourcedir,Updated=Yes" ISC_INSTALLER_LOGFILE="installer_log" ISC_INSTALLER_LOGLEVEL="2" ./cinstall
-
Example
The following class creates a namespace (MyNamespace) and three databases; two of the databases are defined as the default databases for globals (MyDataDB) and routines (MyRoutinesDB), while the third database (MyMappingDB) is a globals database that overrides the default database mapping for t* globals in the MyNamespace namespace.
For a more comprehensive example, see the Sample.InstallerOpens in a new tab class in the SAMPLES namespace.
Include %occInclude
/// Simple example of installation instructions (Manifest)
Class MyInstallerPackage.SimpleManifest
{
XData SimpleManifest [ XMLNamespace = INSTALLER ]
{
<Manifest>
<Namespace Name="MyNamespace" Create="yes"
Code="MyRoutinesDB" Data="MyDataDB">
<Configuration>
<Database Name="MyRoutinesDB" Create="yes"
Dir="C:\MyInstallerDir\MyRoutinesDB"/>
<Database Name="MyDataDB" Create="yes"
Dir="C:\MyInstallerDir\MyDataDB"/>
<Database Name="MyMappingDB" Create="yes"
Dir="C:\MyInstallerDir\MyMappingDB"/>
<GlobalMapping Global="t*" From="MyMappingDB"/>
</Configuration>
</Namespace>
</Manifest>
}
/// This is a method generator whose code is generated by XGL.
ClassMethod setup(ByRef pVars, pLogLevel As %Integer = 3,
pInstaller As %Installer.Installer,
pLogger As %Installer.AbstractLogger)
As %Status [ CodeMode = objectgenerator, Internal ]
{
#; Let our XGL document generate code for this method.
Quit ##class(%Installer.Manifest).%Generate(%compiledclass,
%code, "SimpleManifest")
}
}
After the class is compiled, you can invoke it in the Terminal as shown below (assuming you created the class in the USER namespace):
%SYS>znspace "USER"
USER>do ##class(MyInstallerPackage.SimpleManifest).setup()