部署

设计插件时考虑部署的以下方面。

激活

每个映像都包含一个在虚拟机启动之后执行的启动脚本 /0config/0config.sh

在部署期间,会对每个虚拟机都分配一个唯一名称。 会将该名称设置为一个名为 SERVER_NAME 的环境变量。 通过将实例号附加到相应的 vm-template 名称 (例如, application-was.11373380043317application-was.2237183401478347) 来构成该值。 激活过程如下所示:
  1. 从拓扑文档获取此虚拟机的 vm-template (例如,如果 SERVER_NAME == application-was.1) ,然后获取名为 application-wasvm-template
  2. 对于 vm-template 中的每个节点部件:
    1. 下载节点部件 .tgz 文件并解压到 {nodepkgs_root} 目录中。
    2. 调用 {nodepkgs_root}/setup/setup.py(如果该脚本存在)。 拓扑文档中的关联 parms 可用作 maestro.parms
    3. 删除 {nodepkgs_root}/setup/
  3. 以升序数字顺序运行安装脚本 ({nodepkgs_root}/common/install/*.sh|.py)。
  4. 按数字升序运行启动脚本 ({nodepkgs_root}/common/start/*.sh|.py)。
在步骤 2 中,节点部件不得依赖于安装顺序;即,setup/setup.py 脚本必须仅依赖于该节点部件的内容。 一个例外情况是 maestro 模块。 模块初始化脚本到位,因此,setup.py 脚本可使用 maestro HTTP 客户机实用程序方法(例如,maestro.download()maestro.parms)来获取配置参数。

安装脚本和启动脚本都具有一定的顺序。 按照约定,这些脚本使用数字前缀 (例如 5_autoscaling.sh9_agent.sh) 进行命名。 这些脚本被认为位于插槽 5 或插槽 9 中。 插槽 0 中的所有安装脚本都在插槽 1 中的任何安装脚本之前运行。 所有安装脚本都按连续顺序运行,然后所有启动脚本都按连续顺序运行。 对于每个虚拟机,设置和安装脚本运行一次;每次启动或重新启动时,启动脚本都会运行。 有关更多信息,请参阅“恢复:重新引导或进行替换”部分。 工作负载代理程序以节点部件的形式打包并安装。

节点部件

节点部件由激活脚本安装,并且通常包含用于扩充操作系统的二进制文件和脚本文件。 请查看有关节点部件的以下信息:
  • 规范
    节点部件打包为 .tgz 文件。 按照约定,内容组织为目录结构。 下列文件和目录为可选:
    common/python/maestro/{name}.py
    	common/scripts/{name}
    	common/start/{N}_{name}
    	common/stop/{N}_{name}
    {name}/{any files}
    setup/setup.py
    
    对于以下共享文件,根目录为 common/ :
    • common/python
      适用于由工作负载代理程序启动的 Python 脚本,并且包括下列目录:
      • common/python,已添加至 PYTHONPATH

        common/python/maestro/*.py 中的所有文件,添加至 maestro 包

      • common/scripts

        在运行启动脚本之前已添加到 PATH

      • common/start

        包含由激活脚本自动启动的脚本文件;脚本以数字作为名称的前缀,例如,5_autoscaling.sh9_agent.sh,并且以连续顺序运行(从 0_* 开始)。

      • common/stop

        包含由激活脚本自动停止的脚本文件;脚本以数字作为名称的前缀,例如,5_autoscaling.sh9_agent.sh,并且以反向连续顺序运行。

    {name}/ 是节点部件的专用目录。

    setup/ 旨在用于节点部件的一次性设置。 脚本 setup/setup.py 由激活脚本启动,在拓扑文档中指定了相关联的参数。 在 setup/setup.py 脚本返回之后,会删除 setup/ 目录。

  • 设置脚本
    如果存在,那么将使用关联的参数启动 setup/setup.py 脚本。 例如,对于安装位置、IaaS 服务器和命令端口,工作负载代理程序节点部件是可配置的;在拓扑文档中的节点部件对象(例如样本拓扑文档的“应用程序模型和拓扑文档示例”部分中的以下摘录)内指定了参数:
    "node-parts":[
                {
                   'parms':{
                      "iaas-port":"8080",
                      "agent-dir":"\/opt\/IBM\/maestro\/agent",
                      "http-port":9999,
                      "iaas-ip":"127.0.0.1"
                   },
                   "node-part":"https:\/\/localhost:9444\/storehouse\/admin\/plugins\/agent\/nodeparts\/agent-linux-x64.tgz"
                },
    setup/setup.py 脚本可导入 maestro 模块。 配置参数可用作 maestro.parms,例如:
    
    import json
    import os
    import subprocess
    import sys
    
    import maestro
    
    parms = maestro.parms
        
    subprocess.call('chmod +x *.sh', shell=True)
    
    rc = subprocess.call('./setup_agent.sh "%s" %d %s %s' % (parms['agent-dir'], parms['http-port'], parms['iaas-ip'], parms['iaas-port']), shell=True)
    maestro.check_status(rc, 'setup_agent.sh: rc == %s' % rc)
    实现具有任意性。 前面的示例将参数值传递至 shell 脚本,该 shell 脚本转而启动 sed 以在支持脚本中进行令牌替换。
    在部署的解析阶段,会将节点部件添加到 vm-templates通过两种方式将节点部件添加到 vm-template :
    • 显式包括在所指定包中。
    • 隐式包括在匹配的缺省包中。
    例如,以下显示了工作负载代理程序插件中的 config.json 文件:
    {
       "name":"agent",
       "packages":{
          "default":[
             {
                "requires":{
                   "arch":"x86_64",
                   "os":{
                      "RHEL":"*"
                   }
                },
                "node-parts":[
                   {
                      "node-part":"nodeparts/agent-linux-x64.tgz",
                      'parms':{
                         "agent-dir":"/opt/IBM/maestro/agent",
                         "http-port":9999,
                         "iaas-ip":"@IAAS_IP@",
                         "iaas-port":"@IAAS_PORT@"
                      }
                   }
                ]
             }
          ]
       }
    }
    
    通常, config.json 可以定义任意数量的指定包。 前一示例显示了一个名为“default”的包。 每个包都是一个包含任何数目的对象的集合,其中每个对象均是节点部件和/或部件的候选组合。 候选项由 requires、node parts 和 parts 的映射值指定。 包内容在模式类型内将相加。 例如,如果两个插件属于同一模式类型,并且两者在 config.json 内均定义了包“FOO”,那么解析包“FOO”将视为是两个 config.json 文件中的候选项的并集。 在 config.json 中,“default”是特殊包名。 解析阶段将始终包括缺省包;其他指定包将仅在明确指定时才会解析。
  • config.json file
    config.json 文件必须指定以下信息:
    插件名称
    插件名称是字符串。 名称不能包含正斜杠 (/)。 例如:
    "name":"was"
    插件版本
    版本号的格式必须为 N.N.N.N。 例如,有效版本号为 1.0.0.3
    关联的模式类型
    patterntypes 元素中必须至少定义一个模式类型关联,并且它可以是主模式类型也可以是辅助模式类型。 您只能指定一个主模式类型,但是可以指定多个辅助模式类型。 例如, DB2® 插件声明与数据库作为服务模式类型的主要关联,这意味着该插件由作为服务模式类型实体的数据库的许可证和启用所涵盖。 该插件还声明与 Web Application Pattern 类型的辅助关联。 这意味着已启用的 DB2 插件也可用于创建具有 Web Application Pattern 类型的虚拟应用程序模式。
    使用 JSON 对象可定义主模式类型。 例如:
    "patterntypes":{
       "primary":{
          "webapp":"2.0"
        }
    }
    
    使用包含一个或多个 JSON 对象的 JSON 数组来定义一个或多个辅助模式类型。 没有主模式类型的插件示例是 debug 插件。 该插件使用以下配置来指定它具有与所有模式类型的辅助关联。
    "patterntypes" : {
        "secondary" : [ { "*" : "*" } ]
    },
    如果您希望定义与特定辅助模式类型的关联,那么可以将多个模式类型包含在 secondary 元素中。
    "patterntypes" : {
        "secondary" : [ 
            { "pattern1":"2.0" },
            { "pattern2":"2.1" }
        ]
    },

    插件链接

    将插件与模式类型关联的最简单方式是通过直接在 config.json 中定义主要和辅助模式类型。 但是,此方式在插件与模式类型之间创建静态关系。 链接是将模式类型与插件关联的更灵活方式。 在以下示例中, hello 插件声明与 config.json中的 dbaas 模式类型的链接关系。
    "patterntypes": {
         "primary":{
             "hello":"2.0"
         },
         "linked":{
             "dbaas":"1.1"
         }
     }
    导入 hello 插件时,与 dbaas 模式类型 V1.1 关联的任何插件也自动与 hello 模式类型 V2.0 关联。 例如,plugin.com.ibm.db2 plugindbaas 声明为其主模式类型,所以此插件自动与 hello 模式类型关联。
    "patterntypes":{
          "primary":{
             "dbaas":"1.1"
          },
          "secondary":[
             {
                "webapp":"*"
             }
          ]
     },
    没有使用与主要和辅助模式类型关系相同的方式来强制实现链接关系。 对于 hello 插件示例,即使没有安装或启用 dbaas 模式类型,也可以安装 hello 插件。 如果不存在与 虚拟应用程序实例 的活动关联,或者如果没有任何虚拟应用程序锁定到该模式类型,那么也可以除去 dbaas 模式类型。

    需要

    requires 的值是在适用操作系统和体系结构方面对候选项进行限定的对象。 受支持的键和映射值如下:

    Key arch;映射值是字符串或字符串数组。 受支持的字符串包括 x86 和 x86_64 (ESX) 以及 ppc_64 (PowerVM®)。

    例如,
    "arch" : "ppc_64"
    或者
    	"arch" : ["x86", "x86_64"]
    Key OS;映射值是操作系统名称/版本对的对象。 受支持的操作系统名称字符串包括 RHEL 和 AIX®。 以下表达式有效:
    "*"
    匹配所有版本。
    "[a, b]"
    与介于 ab 之间的所有版本匹配(包括 a 和 b)。
    "(a, b)"
    匹配 ab之间的所有版本 (互斥)。
    "[*, b]"
    与不高于 b 的所有版本匹配(包括 b)。
    "[a, *)"
    与所有版本 a 及更高版本匹配。
    包名在所有已安装插件之间必须唯一,保留的缺省包名除外。 缺省包是加成项。 所有插件都可将候选项追加至缺省包,并且在部署的解析阶段期间,会自动对所有候选项进行评估以确定匹配情况。 因此,缺省包是隐式包括的基础;所有其他指定包都仅为显式包括。
  • 标准节点部件
    所有 vm-templates 都包括工作负载代理程序和防火墙节点部件。 其中每个节点部件都定义一个标准接口,以便与其他节点部件集成和由其他节点部件使用。
    • 工作负载代理程序

      工作负载代理程序是基于 OSGi 的应用程序,负责安装部件和驱动插件中角色和依赖项的生命周期。

      工作负载代理程序会处理以下操作序列以针对正在运行的应用程序驱动角色和依赖项:
      1. 从拓扑文档中获取虚拟机 vm-template,例如,如果 SERVER_NAME == application-was.1,那么获取名为 application-wasvm-template
      2. 对于 vm-template 中的每个部件,按顺序运行下列步骤:
        1. 下载部件 .tgz 文件,并将该文件解压缩到 {tmpdir}中。
        2. 启动 {tmpdir}/install.py,从而传递拓扑文档中指定的任何相关联参数。
        3. 删除 {tmpdir}
      3. 对于 vm-template 中的每个角色,同时运行下列步骤:
        1. 启动 {role}/install.py(如果存在)。
        2. 对于该角色的每个依赖项,启动 {role}/{dependency}/install.py(如果存在)。
        3. 启动 {role}/configure.py(如果存在)。
        4. 对于该角色的每个依赖项,启动 {role}/{dependency}/configure.py(如果存在)。
        5. 启动 {role}/start.py(如果存在)。
      4. 对依赖项 ({role}/{dependency}/changed.py) 和同级项 ({role}/changed.py) 中的更改作出反应(如果这些项存在)。 角色状态会自动提升至 CONFIGURING,而不是提升至 RUNNING。 插件脚本必须将角色状态设置为 RUNNING。 角色状态必须仅由 {role}/start.pychanged.py 脚本 (角色或依赖关系) 设置。 角色状态的设置方式如下所示:
        import maestro
        maestro.role_status = 'RUNNING'
      存在工作负载代理程序的若干定制功能:
      • 工作负载代理程序可扩充。
      • 其他节点部件可将功能部件安装到基于 OSGi 的应用程序中。
      请完成下列步骤,以将节点部件功能部件安装到代理程序中:
      1. 提供包含下列文件的 .tgz 文件:
        • lib/{name}.jar -捆绑软件 Java™ 归档文件
        • lib/features/featureset_{name}.blst - 功能部件集的捆绑软件的列表
        • usr/configuration/{name}.cfg - OSGi 配置代码
      2. 在插槽 9 之前提供用于将 .tgz 文件内容安装到代理程序中的启动脚本。
      其他节点部件不需要知道代理程序应用程序的安装位置。 更确切地说,代理程序会提供用于安装定制功能部件的共享脚本 agent_install_ext.sh。 共享脚本始终位于 PATH 上,因此,供节点部件用来安装定制功能部件的典型启动脚本如下所示:
      #!/bin/sh
      
      agent_install_ext.sh ../../autoscaling/autoscaling.tgz
      agent_install_ext.sh 脚本会将所指定 .tgz 文件的内容解压到代理程序应用程序中。 当启动代理程序时,会包括该定制功能部件。
    • 防火墙
      防火墙节点部件会为 shell 脚本和 Python 脚本定义通用 API,以处理虚拟机上的防火墙设置。 Red Hat Enterprise Linux® 的缺省实现基于 iptables; 可以构建其他实现。 firewall.sh 脚本是为 Linux提供的 shell 脚本。 以下内容对 shell 用法进行了概括:
      firewall.sh open in [-p <protocol>] [-src <src>]
      		[-sport <port>] \ [-dest <dest>] [-dport <port>]
      firewall.sh open out [-p <protocol>] [-src <src>]
      		[-sport <port>] \ [-dest <dest>] [-dport <port>]
      firewall.sh open tcpin [-src <src>] [-dport <port>]
      firewall.sh open tcpout [-dest <dest>] [-dport <port>]
      
      firewall.sh close in [-p <protocol>] [-src <src>]
      		[-sport <port>] \ [-dest <dest>] [-dport <port>] 
      firewall.sh close out [-p <protocol>] [-src <src>]
      		[-sport <port>] \ [-dest <dest>] [-dport <port>]
      firewall.sh close tcpin [-src <src>] [-dport <port>]
      firewall.sh open tcpout [-dest <dest>] [-dport <port>] 
      
      open tcpin 伪指令针对 TCP 连接进行定制,并在 INPUT 和 OUTPUT 表中打开相应的规则以允许请求和响应连接。 open in 伪指令仅打开 INPUT 表。 对于 srcdestprivate 是有效值。 此值指示 <src><dest> 仅限于为云定义的 IP 范围。 值 private 在防火墙插件的 config.json 文件中定义,如下所示:
      {
         "name":"firewall",
         "packages":{
            "default":[
               {
                  "requires":{
                     "arch":"x86_64",
                     "os":{
                        "RHEL":"*"
                     }
                  },
                  "node-parts":[
                     {
                        "node-part":"nodeparts/firewall.tgz",
                        'parms':{
                           "private":"PRIVATE_MASK"
                        }
                     }
                  ]
               }
            ]
         }
      }
      
      当前, PRIVATE_MASK 的值是在 maestro 供应步骤中设置的。 在云项目 build.xml 文件中找到特定于云的值,例如 cloud.HSLT/build.xml。 对于 Orion 云,请参阅 PRIVATE_MASK == 10.0.0.0/255.0.0.0
      Python API 类似。 调用者必须导入 maestro 包。 所提供的防火墙方法为如下所示:
      maestro.firewall.open_in(**args) 
      maestro.firewall.open_out(**args) 
      maestro.firewall.open_tcpin(**args) 
      maestro.firewall.open_tcpout(**args)  
      
      maestro.firewall.close_in(**args) 
      maestro.firewall.close_out(**args) 
      maestro.firewall.close_tcpin(**args) 
      maestro.firewall.close_tcpout(**args)
      其中 **args 表示关键字自变量。

      有效关键字如下所示: protocolsrcsportdestdport

      以下示例适用于一个有效调用:
      maestro.firewall.open_tcpin(src='private', dport=8080) 

部件数

部件由工作负载代理程序安装,并且通常包含与角色和依赖关系相关联的二进制文件脚本和生命周期脚本。 请查看有关部件的以下信息:
  • 规范

    所有部件都必须在根目录中具有 install.py 脚本。 允许包含更多文件。

  • 常用脚本
    缺省情况下, maestro 包包含以下函数:
    • maestro.download(url, f): 从 URL 下载资源,并将资源保存为文件 f本地。
    • maestro.downloadx(url, d): 将 .zip.tgz.tar.gz 文件下载并解压缩到目录 d 中。 .tgz.tar.gz 文件通过抽取进行流式传输; 然后下载并抽取 .zip 文件。
    • maestro.decode(s):用于对通过 maestro 编码实用程序(例如从使用 com.ibm.ws.security.utils.XOREncoder.encode(String) 的变换器)编码的字符串进行解码。
    • maestro.install_scripts(d1): 用于将生命周期脚本复制到 {scriptdir} 并使 shell 脚本可执行 (dos2unixchmod +x) 的实用程序函数。
    • maestro.check_status(rc, message): 用于记录和退出非零 rc的脚本的实用程序函数。
  • 数据对象
    当代理程序启动部件安装脚本时,代理程序会将数据对象或字典追加至 maestro 包,如下所示:
    maestro.parturl : fully-qualified URL from which the part .tgz file was obtained (string; RO) 
    maestro.filesurl : fully-qualified URL prefix for the shared files in storehouse (string; RO)  
    maestro.parms : associated parameters specified in the topology document (JSON object; RO)  
    maestro.node['java'] : absolute path to Java executable (string; RO) 
    maestro.node['deployment.id'] : deployment ID, for example,  d-xxx (string; RO) 
    maestro.node['tmpdir'] : absolute path to working directory. This path is cleared after use (string; RO) 
    maestro.node['scriptdir'] : absolute path to the root of the script directory (string; RO) 
    maestro.node['name'] : server name (same as env variable SERVER_NAME) (string; RO) 
    maestro.node['instance'][ 'private-ip'] (string; RO) 
    maestro.node['instance'][ 'public-ip'] (string; RO)  
    maestro.node['parts'] : shared with all Python scripts invoked on this node (JSON object; RW)

角色

角色表示虚拟应用程序实例内的受管实体。 在拓扑文档中,每个角色都由一个 JSON 对象来描述,该对象包含在相应的 vm-template 中,如以下示例中所示:

maestro.role['tmpdir']: 特定于角色的工作目录; 未清除 (字符串; RO)

可导入定制脚本,例如,import my_role/my_lib.py
utilpath = maestro.node['scriptdir'] + '/my_role' 
if not utilpath in sys.path:     
sys.path.append(utilpath) 
import my_lib
以下示例是拓扑文档中的角色:
"roles":[
{
"plugin":"was\/2.0.0.0",
'parms':{
"ARCHIVE":"$$1",
"USERID":"virtuser",
"PASSWORD":"$$6"
},
"depends":[
{
"role":"database-db2.DB2",
'parms':{
"db_provider":"DB2 Universal JDBC Driver Provider",
"jndiName":"TradeDataSource",
"inst_id":1,
"POOLTIMEOUT":"$$11",
"NONTRAN":false,
"db2jarInstallDir":"\/opt\/db2jar",
"db_type":"DB2",
"db_dsname":"db2ds1",
"resourceRefs":[
{
"moduleName":"tradelite.war",
"resRefName":"jdbc\/TradeDataSource"
}
],
"db_alias":"db21"
},
"type":"DB2",
"bindingType":"javax.sql.DataSource"
}
],

角色名称和角色类型

角色名称在 vm-template 中必须唯一。 在拓扑中,角色名称标识 vm-template 中定义了角色参数的特定部分。 角色名称不需要与角色类型匹配。 角色名称标识存储角色脚本的目录。 例如,如果 vm-template 中包含下列各行:
{
	name: A_name
	type: A
	parms:{}
}
在部署虚拟机时,将发生以下操作:
  • 将创建名为 A_name 的角色。
  • 角色 A_name 的 Python 生命周期脚本位于 scripts/A/
  • 生命周期脚本可以使用 maestro.parms 来读取为角色 A_name 定义的参数。
以下示例显示为高速缓存的共享服务部署所生成的部署文档。 每个节点的标准角色名称的格式为
{server name}.{role name}
{server name} 基于在拓扑文档中定义的 vm-template 名称。 {role name} 是在拓扑文档中定义的角色名称,在该名称后面追加了唯一的实例号。
 ROLES: [
    {
      time_stamp: 1319543308833,
      state: "RUNNING",
      private_ip: "172.16.68.128",
      role_type: "CachingContainer",
      role_name: "Caching-Container.11319542242188.Caching",
      display_metrics: true,
      server_name: "Caching-Container.11319542242188",
      pattern_version: "2.0",
      pattern_type: "foundation",
      availability: "NORMAL"
    },
    {
      time_stamp: 1319543269980,
      state: "RUNNING",
      private_ip: "172.16.68.129",
      role_type: "CachingCatalog",
      role_name: "Caching-Catalog.21319542242178.Caching",
      display_metrics: false,
      server_name: "Caching-Catalog.21319542242178",
      pattern_version: "2.0",
      pattern_type: "foundation",
      availability: "NORMAL"
    },
    {
      time_stamp: 1319544107162,
      state: "RUNNING",
      private_ip: "172.16.68.131",
      role_type: "CachingPrimary_node",
      role_name: "Caching-Primary_node.11319542242139.Caching",
      display_metrics: true,
      server_name: "Caching-Primary_node.11319542242139",
      pattern_version: "2.0",
      pattern_type: "foundation",
      availability: "NORMAL"
    },
    {
      time_stamp: 1319543249613,
      state: "RUNNING",
      private_ip: "172.16.68.130",
      role_type: "CachingCatalog",
      role_name: "Caching-Catalog.11319542242149.Caching",
      display_metrics: false,
      server_name: "Caching-Catalog.11319542242149",
      pattern_version: "2.0",
      pattern_type: "foundation",
      availability: "NORMAL"
    }
  ],

角色状态和状况

代理程序会实现通过基本发展过程来驱动每个角色的状态机,如下所示:
  1. INITIAL:角色以初始状态启动。 每个角色的 {role}/install.py 脚本会启动。 对于该角色的每个依赖项,{role}/{dependency}/install.py 会启动(如果存在)。 如果这些脚本成功完成,那么该角色会自动进入到 INSTALLED 状态。 如果 install.py 脚本失败,那么角色将变为 ERROR 状态,并且部署将失败。
  2. INSTALLED:从此状态开始,{role}/configure.py 脚本会运行(如果存在)。 对于该角色的每个依赖项,{role}/{dependency}/configure.py 会启动(如果存在)。 如果这些脚本成功完成,那么该角色会自动进入到 CONFIGURING 状态。 如果 configure.py 脚本失败,那么角色将变为 ERROR 状态,并且部署将失败。
  3. CONFIGURING:从此状态开始,start.py 脚本会运行(如果存在)。 该角色会对依赖角色 ({role}/{dependency}/changed.py) 和同级项 ({role}/changed.py) 中的更改作出反应(如果它们存在)。
    注: 有关 {role}/changed.py{role}/{dependency}/changed.py的更多信息,请参阅 pydoc。
  4. STARTING:自动状态设置将停止。 生命周期脚本必须将角色状态明确设置为 RUNNING。 角色状态的设置方式如下所示:
    import maestro
    maestro.role_status = 'RUNNING'
  5. RUNNING
如果该过程已停止或发生了不可恢复错误,那么该角色会变为 ERROR 状态。 如果错误是可恢复错误,那么可以使角色状态保持为 RUNNING 并将角色状态更改为 FAILED。 例如,如果 WebSphere® Application Server 崩溃,并且 wasStatus.py检测到崩溃,那么 wasStatus.py 脚本集 maestro.role_status = "FAILED"。 当用户从 实例控制台 控制台启动 WebSphere Application Server 时,将发生下列其中一个进程:
  • 如果没有依赖关系,那么 operation.py 将设置 maestro.role_status="RUNNING"
  • 如果 WebSphere Application Server 依赖于其他角色 (例如 DB2) ,请 operation.py 设置 maestro.role_status="CONFIGURING"。 由于角色状态从 FAILED 更改为 CONFIGURINGwas/{dependency}/changed.py 脚本将启动,而该脚本将启动 WebSphere Application Server。 处理来自 maestro.deps 和集合 maestro.role_status="RUNNING"的依赖关系信息。

如果部署已停止或受到破坏,那么 stop.py 脚本会运行,并且该角色会变为 TERMINATED 状态。 通过外部命令,角色仅会变为 TERMINATED 状态。

在转换期间和某个状态内,角色状况可更改。 下表显示了前面部分中描述的状态历程以及启动的状态和生命周期脚本的详细信息:
表 1. 角色状态和状况
角色状态脚本 转换 更新状态 方面 设置角色状态 调用
初始 Initial => INSTALLED 在进入时   INITIAL -
INSTALLED

{role}/install.py 然后全部 {role}/{dep}/install.py

{role}/configure/py 然后全部 {role}/{dep}/configure.py

{role}/start.py

INSTALLED => RUNNING

期间

 

INSTALLING

CONFIGURING

STARTING(由脚本设置角色状态)

 
RUNNING

{role}/start.py

 
  • 在进入时
  • 更改时
 

role_status(由脚本设置)

 

有关整个虚拟应用程序实例的状态的信息,请参阅相关任务

现有资源

插件可与现有资源进行交互。 尽管现有资源不是插件中的受管实体,但是作为角色对其进行建模,这允许采用一致的方法,无论是处理由模式部署的资源还是处理现有资源。 尤其表现在下列方面:
  • 会以两个角色之间的依赖项的形式对资源之间的集成进行建模。 目标角色(由模式部署的或现有)会导出由源上的依赖项脚本 ({role}/{dep}/changed.py) 使用的属性以实现该集成。 此设计会复用该源依赖项脚本。 例如,在 wasdb2 插件中, WAS/DB2/changed.py 脚本管理任何模式部署或现有数据库的 WebSphere Application Server 数据源。
  • Cloud Pak System 部署用户界面中的用户交互对于资源和集成是一致的。 资源(由模式部署的资源或现有资源)表示为角色,这意味着这些资源会显示在产品用户界面中的部署面板的操作选项卡上。 例如,当更改密码时,可查找某个角色。 对于由模式部署的资源,会将该更改应用于该资源,然后将该更改导出以便依赖项作出反应。 对于现有资源,会将更改导出以便依赖项作出反应,如同已在外部更改密码时。

    会通过源角色处理对交互(链接)的配置的管理。

会通过 appmodel/metadata.json 文件中的组件对现有资源进行建模。 必须提供典型的组件属性(例如主机名/IP 地址、端口和应用程序凭证)才能连接到该资源。

会通过 appmodel/metadata.json 文件中的链接对与现有资源的集成进行建模。

如果资源的类型显示为由模式部署的或现有,那么可通过添加角色来进行合并以表示外部资源。 此角色可从现有资源导出可由从属角色(对于资源由模式部署的情况)处理的参数。

请考虑正在使用现有资源(例如 wasdb2imsdbwasctg 插件)的应用程序的情况。 在应用程序模型级别,现有数据库是组件, WebSphere Application Server 代表应用程序将其用作该组件的表示链接。 现有数据库的典型属性是其主机名或 IP 地址和端口以及用于进行访问的用户标识和密码。

在较早的服务方法中,现有数据库组件具有用于构建对这些属性进行存储的 JSON 目标片段的变换,并且链接变换会使用这些属性。 例如,在 IMS中,链接变换使用从组件传递的现有数据库的参数在 WebSphere Application Server 节点中的 WebSphere Application Server 角色中创建依赖关系。 从属角色 configure.py 脚本用于配置 WebSphere Application Server 以使用基于参数的现有数据库,这些参数已足够,但在部署面板中,现有数据库的参数显示在 WebSphere Application Server 角色中,这是不明智的。

在新的角色方法中,目标组件将创建角色 JSON 对象,并且链接变换会将其添加到角色的 WebSphere Application Server 虚拟机模板列表。 wasdb2 插件创建 xDB 角色以连接到现有 DB2 和 Informix® 数据库。 IMS 可以转换为此模型,并将其 configure.pychange.py 脚本移至新的 xIMS 角色。 此处的优势在部署面板中,该面板会在左列中分别列示节点的每个角色,在此情况下,会较好地将该角色的参数与操作分开以便用户访问。

wasdb2 插件提供了 IMS 和 CTG 可能未使用的额外功能。 该插件还支持模式部署的 DB2 实例。 在模式部署方案中, DB2 目标节点是已启动的节点。 正确的模型是从属角色,当源 WebSphere Application Server 和目标 DB2这两个组件启动时,将执行链接配置。 然后,会运行 changed.py 脚本。 对于现有数据库方案, wasdb2 插件将导出与 DB2 插件相同的参数,然后可以在 changed.py 脚本中执行模式部署和现有案例的处理。 IMS 和 wasctg 不需要此过程,并且可以将 configure.py 角色脚本用于新角色。

可重复任务

在运行时,角色可能需要重复地执行某些操作。 例如,记录服务必须以固定周期将本地日志备份至远程服务器。 插件框架允许在所指定时间之后启动某一脚本,以满足此要求。

可以从属于角色的任何生命周期脚本运行任务,例如 install.pyconfigure.pystart.pychanged.py。 调用 maestro.tasks.append() 方法来运行任务。 例如:
task = {}
task['script']='backupLog.py' 
task['interval'] = 10

taskParms={}  
taskParms['hostname'] = hostname
taskParms['directory'] = directory
taskParms['user'] = user
taskParms['keyFile'] = keyFile
task['parms'] = taskParms

maestro.tasks.append(task)

对未能运行的任务进行故障诊断时,先检查使用 maestro.tasks.append() 来调用任务的脚本。

您必须具有名为 task 的字典对象。 可将此名称更改为另一有效名称。 目标脚本由 task['script'] 指定,而时间间隔则由 task['interval'] 指定。 可通过使用 task['parms'] 来将参数添加至该脚本。 对脚本进行的此添加是可选的。 maestro.tasks.append(task) 用来启用此任务。 在此示例中,backupLog.py(位于文件夹 {role}/scripts 中)在当前脚本完成 10 秒之后启动。 通过使用 backupLog.py 脚本,可从 maestro.task['parms'] 中检索到任务参数,而从 maestro.task['interval'] 中检索到时间间隔。 此脚本仅启动一次。 如果需要重复地启动 backupLog.py 脚本,那么必须将相同代码添加到 backupLog.py 脚本中。 当前脚本完成时,会在新的所指定时间间隔和参数之后启动 backupLog.py 脚本。

恢复:重新引导或进行替换?

如果虚拟机意外停止,那么主代理程序会对发生故障的虚拟机进行恢复。 该操作取决于虚拟机类型。 会对持久性虚拟机进行重新引导。 会对其他虚拟机进行替换。

如果虚拟机是持久性属性值为 true 的 vm-template 的实例,那么该虚拟机为持久虚拟机,如下所示:
"vm-templates": [
        {
        	"persistent":true,
            "scaling": {
                "min": 1, 
                "max": 1
            },
存在以下两种方法供插件用来将某个虚拟机标记为持久性虚拟机:
  • 直接

    变换器将持久性属性添加至 vm-template

  • 间接

    包配置指定持久性属性。

直接方法会取代间接方法。 即,如果 vm-template 标记了持久性(truefalse),那么该值是最终值。 如果 vm-template 未标记持久性,那么在部署的解析阶段会根据与该 vm-template 相关联的包来派生该 vm-template 的持久性值。 vm-template 标记为持久或 true (如果有任何程序包声明持久 true)。

间接方法使您能够更灵活地对部件和节点部件进行集成,而不要求对哪些位置上需要持久性有全面了解。 变换器会添加该属性,如下所示:
 "vm-templates": [
        {
        	"persistent":true,
            "scaling": {
                "min": 1, 
                "max": 1
            }, 
            "name": "Caching_Primary_node", 
            "roles": [
                {
                    "depends": [{
                        "role": "Caching_Worker_node.Caching"
                    }],
                    "type": "CachingPrimary_node", 
                    "name": "Caching",
                    'parms':{
                	 "PASSWORD": "$XSAPassword"
                	}
                }
            ], 
            "packages": [
                "CACHING"
            ]
        },
config.json 文件中指定了包配置,如下所示:
{
    "name" : "db2",
    "version" : "1.0.0.0",
    "packages" : {
        "DB2" : [{
            "requires" : {
                "arch" : "x86_64",
                "memory" : 0},
                "persistent" : true,
            "parts" : [
                {"part" : "parts/db2-9.7.0.3.tgz",
                 'parms' : {
                    "installDir" : "/opt/ibm/db2/V9.7"}},
                {"part" : "parts/db2.scripts.tgz"}]
        }]
    }
}

实例控制台

您可以从 实例控制台操作 选项卡管理 虚拟应用程序实例 。 此选项卡显示所选 虚拟应用程序实例 中的角色,并且每个角色都提供底层插件为其定义的操作,例如,检索数据,应用软件更新或修改配置设置。

您可以执行两种类型的操作来管理或修改部署的角色。 这些操作之间的主要区别在于作用域。
操作
对于操作,此操作仅影响当前的已部署角色。 操作是在 operation.json 中定义的。
配置
对于配置,属性更改保存在拓扑中。 如果虚拟机重新启动或者部署了更多虚拟机,那么配置属性值应用于这些虚拟机。 配置是在 tweak.json 中定义。

操作

  • 可定义操作。
    请在 plugin/appmodel 目录中创建名为 operation.json 的 JSON 文件。 每个 operation.json 文件都必须包含一个 JSONObject。 以下代码示例显示了 WebSphere Application Server operation.json 文件的一部分,其中键是角色类型 WAS,值是包含这些操作定义的 JSONArray:
     "WAS":
    [
            {
                "id": "setWASTrace",
                "label": "TRACE_LEVEL_LABEL",
                "description": "TRACE_LEVEL_DESCRIPTION",
                "script": "debug.py setWASTrace",
    		    "attributes": [
                    {
                        "label": "TRACE_STRING_LABEL",
                        "type": "string",
                        "id": "traceString",
                        "description": "TRACE_STRING_DESCRIPTION" 
                    } 
                ] 
            },
    其中:
    • script 对提交操作时启动的操作 debug.py 脚本进行定义。 操作脚本名称还可后跟方法名称(例如包括在前面代码样本中的 setWASTrace)。 稍后,可在操作脚本中检索到该方法名称。 操作脚本必须置于角色脚本路径下,例如 plugin/parts/was.scripts/scripts/WAS
    • attributes 对您必须输入的操作参数进行定义。 稍后,可由操作脚本检索到这些操作参数。
  • 针对多个实例的操作的属性。

    如果角色具有多个实例,那么您可以在操作定义中使用这些属性来控制将操作应用于实例的方式。 如果角色具有多个实例,那么将验证以下属性:
    rolling
    确定某个操作在实例上是顺序应用还是并行应用。
    • 通过设置 "rolling": false并发应用操作。 此设置为缺省设置。
    • 通过设置 "rolling": true按顺序应用操作。
    可以通过添加指定了 group_size 属性的 rolling_config 来配置组更新。 如果设置了 group_size,那么集群中的实例将划分为指定数目的组。 将逐个组地调用此操作。 例如,如果您设置下列属性:
    {
      "rolling":true,
        "rolling_config": {
            "group_size": 2
         }
    }
    在调用此操作时,实例将划分为两个组。 先对组 1 执行此操作。 在对组 1 中的所有实例完成此操作后,将对组 2 中的实例调用此操作。
    目标
    确定某个操作是在单个实例上应用还是在所有实例上应用。
    • 通过设置 "target": All对所有实例应用操作。 此设置为缺省设置。
    • 通过设置 "target": Single 对单个实例应用操作
    请参阅 WebSphere Application Server operation.json 文件以获取示例。
  • 为操作设置特定角色状态。

    缺省情况下,执行某个操作时,角色状态设置为 CONFIGURING,然后在该操作完成时设置回 RUNNING。 此状态更改有时会停止应用程序本身。 某些操作(例如导出日志)不需要角色来将其状态从 RUNNING 更改为其他状态。 对于这些类型的操作,您可以明确设置在操作启动时要使用的角色状态。 例如,要在操作启动时使角色状态保持为 RUNNING,请将以下属性添加至操作定义:

    "preset_status": "RUNNING"

    除非在操作期间发生了错误,否则角色状态将保留为 RUNNING

    请参阅 WebSphere Application Server operation.json 文件以获取示例

  • 操作脚本

    操作脚本可导入 maestro 模块。 在角色生命周期部件脚本中检索到的信息可通过同一方式在部署面板中检索到,例如 maestro.rolemaestro.nodemaestro.parmsmaestro.xparms。 此外,可使用所有实用程序方法(例如 downloaddownloadx)。 会将部署面板上配置的参数传递到脚本中,然后可在 maestro.operation['parms'] 处检索到这些参数。 operation.json 文件中定义的方法名称在 maestro.operation['method']处检索,操作标识在 maestro.operation['id']处检索。

  • 文件下载和上载
    必须将所有已下载的工件置于固定的根路径下。 操作脚本可从 maestro.operation['artifacts_path'] 获取该根路径。 要指定稍后下载的文件,请在该脚本中插入 maestro.return_value="file://key.p12"。 前缀 file:// 指示需要下载某个文件。 在该脚本完成之后,部署面板会显示用于下载该文件的链接。 已上载的文件置于仓库中的部署路径下的临时文件夹中。 操作脚本会检索已上载的文件的完整仓库路径,例如:
    uploaded_file_path=maestro.operation['parms'][{parm_name}]
    在检索到文件路径之后,maestro.download() 方法会下载该文件。 当操作完成时,会删除仓库中的临时文件。 当操作脚本与内核服务和仓库交互时,该脚本会首选使用从用户界面传递的授权令牌,而不使用代理程序令牌,以便稍后可对操作进行审计。 操作脚本必须使用 maestro.operation["user_token"] 来检索从用户界面传递的用户令牌(该令牌包含用户 uuID)。 稍后可在与内核服务和仓库的通信中使用该令牌。 例如,要将文件上载到仓库中,请使用 upload_if_new(url, file),它会使用 agent_token 来生成授权头。 还可使用 upload_if_new(url, file, user_token),在此情况下,传递的 user_token 用来生成头。
  • 操作结果

    可通过使用 maestro.operation['successful']=True/False 来指定操作的结果。 缺省值为 True。 在操作脚本成功完成之后,用户界面会将结果显示为 SUCCESSFAIL。 如果该脚本已运行,但发生故障(例如 return code!=0),那么用户界面结果显示为 ERROR,并且对应的角色会切换至 ERROR 状态。 如果要返回更有意义的结果,请插入 maestro.operation['return_value']="my return value"。 当该脚本完成时,返回值会显示在用户界面上。

    在操作脚本中使用 trycatch 语句以防止角色进入不可恢复的 ERROR 状态。 如果发生了异常,并且 catch 语句捕获到此异常,那么您可以使用 maestro.operation['successful'] = False 来指示未成功完成操作,但是角色状态保持为 RUNNING

  • 如果某项操作会对中间件执行更新,且无法还原该更新,请对该角色添加 "update.revertable": false,以对该用户显示警告。 例如,
    {
        "name": "IM",
        "global": true,
        "update.revertable": false,
        "type": "IM",
        "plugin": "vsys.im/1.0.1.0",
        "dashboard.visible": false},
    如果对于某个角色存在此标志,那么用户在尝试执行更新时将看到警告消息:This update operation is not revertable.
  • Depends-on 角色操作
    在一些情况下,一个角色更新会促使另一角色也需要更新。 此方案称为 depends-on 角色操作。 例如,如果 DB2 更改密码,那么 WebSphere Application Server 也会更新数据源配置。 在操作脚本中,导出已更改的值,例如:maestro.export['DB_PASSWORD']="<XOR>UIK8CNz"。 然后,更改 depends-on 角色 changed.py 脚本,以添加代码来处理其他更新。
    if len(updated)== 1:
    		myrole = updated[0]
    		if deps[myrole] ['is_export_changed'] :
    				print 'export data changed'
    		else:
    				print 'only status changed'
  • 并行运行脚本

    缺省情况下,所有生命周期脚本和操作脚本串行地以某个角色运行以避免冲突。 您也可以并行运行脚本,但是对脚本有一些限制。 对于并行运行的脚本,所有 maestro.* 变量为只读,除了 maestro.operationmaestro.tasks。 对于必须同时运行并且编写一些 maestro.* 的操作,操作脚本可保留能够同时启动的代码,并调度任务来运行必须同时启动的代码。

    下列属性用于配置并行运行脚本:
    parallel
    如果设置为 true,那么脚本将并行地运行。 如果设置为 false,那么脚本串行地运行。
    超时
    对于非并行操作,将操作信息添加到操作队列之后,会立即返回来自操作的响应。 脚本并行运行时,在所有操作脚本都完成之后,才返回响应。 对于耗费很长时间来运行的某些脚本,缺省超时设置可能导致在操作脚本完成之前就发生超时。 要对此问题进行调整,您可以为单位指定合适的超时值,以秒为单位。
  • 测试操作脚本
    在插件开发期间,您可以按照增量方式来测试操作脚本。
    1. 部署应用程序。
    2. 登录具有您要更新的脚本的虚拟机。
    3. 将操作脚本替换为更新的版本。
    4. 通过从部署入口界面运行操作来触发操作脚本。 更新立即生效,然后运行更新的操作脚本。

配置

在部署面板中,会以特殊类型的操作的形式处理配置更新。 配置过程包括下列任务:
  • 定义配置。

    tweak.json 文件添加到插件 plugin/appmodel 文件夹下,以指定在运行时期间可更改哪些配置参数。 这意味着可在运行时更改和验证拓扑模型中的某些参数。 每个 tweak.json 文件都是一个 JSONArray。 每个对象都描述一个可在拓扑模型中调整的参数。 例如,在 WebSphere Application Server 插件中,将以下代码示例添加到 tweak.json 文件。 WAS 角色下面的参数 ARCHIVE 可以调整。

    “标识”的值通过 {role_type}.{parm_name} 组成。 会为用户界面准备其他属性(例如“label”和“description”)。这类似于 metadata.json 文件中的定义,该文件在 /appmodel 目录中。
    {
            "id": "WAS.ARCHIVE",
            "label":"WAR/EAR File",
            "description":"Specifies the web/enterprise application to be uploaded. ",
            "type":"file",
            "extensions":[
    	         "war",
    	         "ear"
            ]
        }
    对于 depends 部分下的参数,“标识”的值通过 {role_type}.{depends_role_type}.{parm_name} 组成:
    
        {
          "id": "WAS.DB2.MINPOOLSIZE",
          "type": "number"
      }
    
    要启用此功能,必须将以下代码添加至 operation.json 文件:
    {
    "id": "configuration",
    "label": "CONFIGURATION_LABEL",
    "description": "CONFIGURATION_DESCRIPTION",
    "script": "change.py" 
    },
    
    {
    "id": "your_id",
    "type": "configuration"
    "label": "CONFIGURATION_LABEL",
    "description": "CONFIGURATION_DESCRIPTION",
    "script": "change.py" 
    },
    

    "configuration" 值指示必须保存参数。

    配置脚本:change.py

    除了下列几点之外,change.py 脚本类似于操作脚本:
    • 脚本名称必须为 change.py
    • 当使用 depends 角色配置时,会将 change.py 脚本置于 plugin/parts/{parts_package}/scripts/{role_type}/{depends_role_type} 路径下。
    • 在成功启动该脚本之后,已更改的值会自动持久保存至仓库。
    • 对于工件类型配置更新 (例如,当您更新 WebSphere Application Server ARCHIVE时) ,如果 change.py 脚本成功完成,那么会将仓库中临时文件夹中的工件克隆到 /deployment/{deployment_id}/artifacts 路径中,然后再将其删除。
  • 非角色组件 (例如,远程 DB2 和 Tivoli ® Directory Service) 的配置。

    如果变换器需要进行配置,请使用 wasxdb2,如以下示例中所示:

    XDB2Transformer.java中:

    更改
    result.put("service", attributes);
    result.put("attributes", attributes);
    result.put("service", prefix);
    WASXDB2Transformer.java中:
    更改
    JSONObject serviceParms = (JSONObject) targetFragment.get("service');
    JSONObject serviceParms = (JSONObject) targetFragment.get("attributes');
    并添加下面的行:
    //WASxDB2 acts as an extension, not a dependency (so, no role defined)
    depend.put("type", "xDB2");
    depend.put("service", targetFragment.get (service));
  • 两个组件 (例如远程 WebSphere Application Server 和 Tivoli Directory Service) 之间的多链路配置。
    除了 tweak.json 文件之外,变换器还需要特定代码以处理此情况。 目标拓扑片段应类似以下所示:
      "depends": [
            {
                "role": "User_Registry-tds.TDS1",
                "deps_key_id": "WAS.xLDAP.xLDAP_ROLE_MAPPING",
                'parms': {
                    "manager": {
                        "SPECIALSUBJECTS_xLDAP_ROLE_MAPPING": "None",
                        "GROUP_xLDAP_ROLE_MAPPING": "manager",
                        "xLDAP_ROLE_MAPPING": "manager",
                        "USER_xLDAP_ROLE_MAPPING": ""
                    },
                    "employee": {
                        "USER_xLDAP_ROLE_MAPPING": "",
                        "GROUP_xLDAP_ROLE_MAPPING": "employee",
                        "xLDAP_ROLE_MAPPING": "employee",
                        "SPECIALSUBJECTS_xLDAP_ROLE_MAPPING": "None"
                    }
                }
            }
        ]    ]
    parms 为嵌套结构,并且您必须指定“deps_key_id”作为 parms 中的子组的键。 您可以使用基于 Java 的代码或模板来完成变换器。 在部件脚本 changed.pychange.py 中,可检索到使用“for 循环”的参数,如下所示:
    for key in parms:
       roleParms = parms[key]
       print key
       print roleParms['xLDAP_ROLE_USER_MAPPING'] 
       print roleParms['xLDAP_ROLE_GROUP_MAPPING'] 
       print roleParms['xLDAP_SPECIAL_SUBJECTS_MAPPING']