Kazuya Akimoto Ten Blue Eyes

Введение


Итак, вы разработали своё приложение на технологиях InterSystems. Теперь его надо развернуть у клиента и часто не один раз. В процессе разработки у вас появилась инструкция по установке – потому что недостаточно просто импортировать классы, нужно ещё и доработать систему напильником провести тонкую настройку среды под ваши нужды.

Для решения этих задач существует утилита %Installer. Эта статья о ней.

%Installer


Эта утилита позволяет определить манифест установки, который описывает целевую конфигурацию Cache, а не шаги к его достижению. Вы описываете, что должно быть, а Cache уже сгенерирует весь необходимый для этого код. Распространяете вы, соответственно, только сам манифест, кодогенерация происходит уже на месте в рамках конкретного сервера Cache.

Для написания манифеста вы создаёте блок XData с описанием желаемой конфигурации, а также метод, который генерирует COS код на основе блока XData (он всегда одинаков). После того, как вы написали манифест, его можно вызвать во время инсталляции Cache, из терминала или COS-кода. Манифест должен исполняться в области %SYS. Манифесту доступны как параметры системы (супер-порт, ОС, mgr директория и др.), так и произвольные параметры, переданные пользователем. Таким образом, класс установщика должен отвечать следующим требованиям:

  • Включать ссылку на %occInclude.inc;
  • Содержать блок XData с конфигурацией сервера Cache;
  • Блок может называться любым корректным именем
  • Добавьте [XMLNamespace = INSTALLER] после имени блока для включения подсказок в студии;
  • Корневой элемент (может быть только один) – <Manifest>, все остальные элементы расположены внутри него;
  • Необходимо определить метод setup(), который выполняет кодогенерацию из блока XData.


Использование


Готовый манифест установки может быть запущен несколькими способами:
  • В области %SYS из терминала или COS кода
    do ##class(MyPackage.MyInstaller).setup()
  • Автоматически при установке Cache. Для этого экспортируйте класс установщика в файл DefaultInstallerClass.xml в папку с дистрибутивом Cache (где находится setup_cache.exe, или cinstall). При установке Cache он будет импортирован в область %SYS и запущен (через метод setup())

Пример


Рассмотрим простой пример. Создадим класс App.Installer c установщиком, который создаёт область с названием, переданным пользователем:

App.Installer
Include %occInclude
Class App.Installer
{
/// Сгенерированный код можно посмотреть в zsetup+1^App.Installer.1
XData 
Install [ XMLNamespace = INSTALLER ]
{
<
Manifest>
    <
If Condition='(##class(Config.Namespaces).Exists("${Namespace}")=0)'>
        <
Log Text="Creating namespace ${Namespace}" Level="0"/>
        <
Namespace Name="${Namespace}" Create="yes" Code="${Namespace}" Ensemble="0" Data="${Namespace}">
            <
Configuration>
                <
Database Name="${Namespace}" Dir="${MGRDIR}/${Namespace}" Create="yes"/>
            </
Configuration>
        </
Namespace>
         <
Log Text="End Creating namespace ${Namespace}" Level="0"/>
    </
If>
</
Manifest>
}
/// Метод, который вызывается для выполнения установки.
/// Во время компиляции класса происходит генерация COS кода
/// После этого установщик запускается с параметрами следующим образом:
/// Set pVars("Namespace")="TempNamespace"
/// Do ##class(App.Installer).setup(.pVars)
ClassMethod 
setup(ByRef pVarspLogLevel As %Integer 0pInstaller As %Installer.InstallerAs %Status CodeMode = objectgenerator, Internal ]
{
     
Quit ##class(%Installer.Manifest).%Generate(%compiledclass%code"Install")
}
}

В этом примере происходит следующее:

  • Проверяем, существует ли область с именем равным значению переменной Namespace (например, значение равно NewNamespace);
  • Если нет, то логируется факт начала создания области NewNamespace;
  • Определение области:
    • C названием NewNamespace;
    • Область нужно создать;
    • БД кода NewNamespace;
    • Ensemble не включаем;
    • БД данных NewNamespace.
  • Создание базы данных
    • C названием NewNamespace;
    • В папке mgr/NewNamespace (заметим, что переменная MGRDIR доступна нам по умолчанию).
  • Запись в лог завершения создания области.

Для запуска из терминала, выполним следующие команды:
    Set pVars("Namespace")="NewNamespace"
    
Do ##class(App.Installer).setup(.pVars)

Что выведет
2015-10-16 16:26:18 0 App.Installer: Installation starting at 2015-10-16 16:26:18, LogLevel=0
2015-10-16 16:26:18 0: Creating namespace NewNamespace
2015-10-16 16:26:19 0: End Creating namespace NewNamespace
2015-10-16 16:26:19 0 App.Installer: Installation succeeded at 2015-10-16 16:26:19
2015-10-16 16:26:19 0 %Installer: Elapsed time .605257s

Список элементов


Манифест формируется из следующих элементов:
Элемент Родительский элемент Атрибуты (значение по умолчанию) Описание
Arg Invoke, Error Value – значение аргумена Передаёт аргумент в метод вызываемый через Invoke или Error
ClassMapping Configuration Package – пакет для отображения
From – имя БД из которой отображаем
Создаёт маппинг классов из БД в облась, внутри элемента Configuration которой мы находимся
Compile Namespace Class – имя класс(ов) для компиляции
Flags – флаги компиляции (ck)
IgnoreErrors – игнорировать ошибки (0)
Компилирует классы. Вызывает $System.OBJ.Compile(Class, Flags)
Configuration Namespace Необходим для создания области и баз данных. Закрывающий тэг активирует маппинги и обновляет cpf файл
CopyClass Namespace Src — исходный класс
Target — целевой класс
Replace — удалять исходный класс (0)
Копирует или перемещает исходный класс в целевой
CopyDir Manifest Src — исходная директория
Targe — целевая директория
IgnoreErrors — игнорировать ошибки (0)
Копирует директорию
CopyFile Manifest Src – исходный файл
Targe – целевой файл
IgnoreErrors – игнорировать ошибки (0)
Копирует файл
Credential Production Name – название реквизита доступа
Username – имя пользователя
Password – пароль
Overwrite – переопределить в случае существования
Создаёт или переопределяет реквизиты доступа
CSPApplication Namespace AuthenticationMethods – доступные методы аутентификации
AutoCompile – автокомпиляция
CSPZENEnabled – флаг CSP/ZEN
ChangePasswordPage – страница изменения пароля
CookiePath – путь для cookie сессии
CustomErrorPage – пользовательская страница ошибок
DefaultSuperclass – супер-класс по умолчанию
DefaultTimeout – таймаут сессии
Description – описание
Directory – путь к CSP-файлам
EventClass – класс события
Grant – список ролей, которые выдаются при входе
GroupById – группировать по идентификатору
InboundWebServicesEnabled – входящие веб-службы
IsNamespaceDefault – приложение для области по умолчанию
LockCSPName – блокировка на имени CSP
LoginClass – страница входа в систему
PackageName – имя пакета
PermittedClasses – разрешенные классы
Recurse – поддиректории (0)
Resource – требуемый ресурс
ServeFiles – служебные файлы
ServeFilesTimeout – таймаут у служебных файлов
TwoFactorEnabled – двухфакторная аутентификация
Url – название веб-приложения
UseSessionCookie – использовать cookie для сессии
Создаёт или изменяет веб-приложение. Подробное описание настроек в документации и классе Security.Applications
Database Configuration BlockSize – размер блока
ClusterMountMode – монтировать БД как часть кластера
Collation – сортировка
Create – создать БД — yes,no,overwrite (yes)
Dir – директория
Encrypted – зашифровать
EncryptionKeyID – ID ключа шифрования
ExpansionSize – расширение
InitialSize – начальный размер
MaximumSize – минимальный размер
MountAtStartup – монтирование при запуске
MountRequired – монтирование обязательно
Name – имя
PublicPermissions – общедоступные права
Resource – ресурс
StreamLocation – расположение потока
Создаёт или изменяет базу данных. Подробное описание настроек в документации и классе Config.Databases
Default Manifest Name – имя переменной
Value – значение переменной
Dir – значение переменной, если это путь к папке/файлу
Определяет значение переменной, если она не определена
Else Manifest, Namespace Выполняется, если проверка if-условия закончилась отрицательно
Error Manifest Status – код ошибки
Source – источник ошибки
Выкидывает исключение. ${} и #{} синтаксис недоступен
ForEach Manifest Index – название переменной
Values – список значений переменной
Оператор совместного цикла
GlobalMapping Configuration Global – имя глобала
From – имя БД из которой отображаем Collation – сортировка (Cache Standard)
Отображает глобал
If Manifest, Namespace Condition – условие Оператор условного перехода
IfDef Manifest, Namespace Var – имя переменной Оператор условного перехода, в случае если переменная определена
IfNotDef Manifest, Namespace Var – имя переменной Оператор условного перехода, в случае если переменная не определена
Import Namespace File – файп/папка для импорта
Flags — флаги компиляции (ck)
IgnoreErrors — игнорировать ошибки (0)
Recurse – рекурсивный импорт (0)
Импортирует файлы. Вызывает:
$System.OBJ.ImportDir(File,,Flags,,Recurse) и $System.OBJ.Load(File, Flags)
Invoke Namespace Class – класс
Method – метод
CheckStatus – проверять возвращаемый статус
Return – записать результат в переменную
Вызывает метод класса, можно передавать аргументы и получить результат исполнения
LoadPage Namespace Name – путь к CSP странице
Dir – папка с CSP страницами
Flags — флаги компиляции (ck)
IgnoreErrors — игнорировать ошибки (0)
Загружает CSP файлы через $System.CSP.LoadPage(Name, Flags) и $System.CSP.LoadPageDir(Dir, Flags)
Log Manifest Level – уровень логирования от 0 (минимум) до 3 (подробно)
Text – текст, до 32000 символов
Добавляет сообщение в лог, если уровень логирования больше или равен атрибуту level
Manifest Корневой элемент. Единственный в манифесте, все остальные элементы располагаются внутри него
Namespace Manifest Name – имя области
Сreate – создавать область – yes,no,overwrite (yes)
Code – БД с кодом
Data – БД с данными
Ensemble – включать Ensemble в области
Прочие атрибуты связаны с веб-приложениями Ensemble
Определяет область работы установщика
Production Namespace Name – имя продукции
AutoStart – автоматический запуск продукции
Настраивает продукцию Ensemble
Resource Manifest Name – имя ресурса
Description – описание
Permission – общедоступные права
Создаёт или изменяет ресурс
Role Manifest Name – имя роли
Description – описание
Resources – ресурсы в виде «MyResource:RW,MyResource1:RWU» RolesGranted – дать сопутствующие роли
Создаёт роль
RoutineMapping Configuration Routines – имя рутин(ы)
Type – один из типов «MAC,INT,INC,OBJ,ALL»
From – из какой БД
Создаёт маппинг рутин
Setting Production Item – настраиваемый элемент
Target – тип настройки: Item, Host, Adapter
Setting – название настройки
Value – значение настройки
Конфигурирует элемент продукции Ensemble. Вызывает метод Ens.Production:ApplySettings
SystemSetting Manifest Name – класс.свойство пакета Config
Value – значение свойства
Устанавливает значение свойств пакета Config (через метод Modify)
User Manifest Username – имя пользователя
PasswordVar – переменная, содержащая пароль
Roles – список ролей пользователя
Fullname – полное имя
Namespace – стартовая область
Routine – стартовая рутина
ExpirationDate – дата, после которой пользователь перестанет быть активированным
ChangePassword – сменить пароль при следующем логине
Enabled – активирован ли пользователь
Создаёт или изменяет пользователя
Var Manifest Name — имя переменной
Value – значение переменной
Определяет значение переменной

Переменные


В качестве значений атрибутов могут выступать переменные, они определяются одним из трёх способов:

  • ${<Имя_переменной>} – во время выполнения манифеста вычисляется значение переменной (переданное пользователем или одна из переменных среды, см. далее);
  • ${#<Имя_параметра>} – во время компиляции заменяются на значение указанного параметра класса установщика;
  • #{<COS_код>} — во время выполнения манифеста вычисляется значение указанного COS выражения. Не забывайте о кавычках.

Значения параметров определяются на этапе компиляции, поэтому они могут быть частью переменой или COS выражения. Интерпретация переменных происходит перед интерпретацией COS-кода, поэтому переменные могут входить в COS-выражение, например: #{$ZCVT("${NAMESPACE}","L")}.

Переменные среды


Всегда доступны следующие переменные:
Переменная Описание Пример значения
SourceDir (Только при установке Cache) Директория, где находится установщик (setup_cache.exe or cinstall) /InterSystems/distr/
ISCUpgrade (Только при установке Cache) Определяет, установка или обновление 0 (установка)
1 (обновление)
CFGDIR См. INSTALLDIR. /InterSystems/Cache/
CFGFILE Путь к cpf файлу /InterSystems/Cache/cache.cpf
CFGNAME Имя инстанса CACHE
CPUCOUNT Количество ядер CPU 4
CSPDIR Директория CSP /InterSystems/Cache/csp/
HOSTNAME Имя веб сервера SCHOOL15
HTTPPORT Порт веб сервера 80
INSTALLDIR Директория, куда устанавливается Cache /InterSystems/Cache/
MGRDIR Директория менеджмента (mgr) /InterSystems/Cache/mgr/
PLATFORM Операционная система UNIX
PORT Порт суперсервера Cache 1972
PROCESSOR Имя платформы x86-64
VERSION Версия Cache 2015.1.1

Отладка


Бывает непонятно, какие значения могут принимать атрибуты. Для выяснения посмотрите на сгенерированный int-код метода setup. Как правило, основной вызов это метод: tInstaller.<ElementName>, т.е. метод класса %Installer.Installer который уже вызывает непосредственно системные методы. Альтернативно, можно посмотреть на код класса %Installer.<ElementName>, атрибуты элемента это свойства его класса. Кодогенерация осуществляется в методах %OnBeforeGenerateCode, %OnGenerateCode, %OnAfterGenerateCode.

Для целей отладки, рекомендую оборачивать вызов установщика в транзакцию. Так с помощью команд TSTART/TROLLBACK можно легко отменить все изменения, сделанные внутри Cache (внешние к Cache изменения, например создание файла БД отменены не будут).

Пример использования


Проект MDX2JSON содержит установщик. Для установки достаточно импортировать в любую область файл installer.xml с классом MDX2JSON.Installer. Импортировать можно или через панель управления или просто переносом класса в студию.

Далее выполните в терминале:

do ##class(MDX2JSON.Installer).setup()

В результате произойдёт загрузка файлов из GitHub-репозитория, установка «по умолчанию» в область MDX2JSON с созданием базы MDX2JSON, маппинга пакета MDX2SJON в %All, создание REST-приложения /MDX2JSON и многое другое, о чём будет написано в терминале.

Ещё примеры


Пример в документации.
Класс Sample.Installer в области Samples.
Проект CacheGitHubCI содержит установщик.
Проект SYSMON Dashboards содержит установщик.
Проект DeepSee Audit содержит установщик.

Выводы


Утилиту %Installer можно использовать для поставки решений на InterSystems Cache и Ensemble.

Ссылки


Документация

Комментарии (1)


  1. morisson
    05.11.2015 15:38
    +1

    Есть еще альтернативный вариант поставки — как в этом проекте. Все компоненты (и Cache и web app) собираются gulp в один файл xml, а при импортировании xml в Cache происходит сборка классов и развертывание веб-приложения. Т.е. для установки и настройки всех компонентов приложения достаточно, например, кинуть xml в окно студии. Например как показано здесь.