内容


使用 IBM PureApplication System 将自定义代码注入 Virtual Application Patterns 中

Comments

简介

IBM® PureApplication® System 随带了一组授权的 Virtual Application Patterns (VAPs),可用于创建新 VAP,并为现有模式库做贡献。这些模式的用户可能需要自定义它们,让它们适合特定的用例,他们可能需要在不更改底层模式实现的情况下执行这种自定义,因为他们可能无法访问模式代码,他们的模式许可可能不允许更改模式定义,或者此模式的其他用户可能想要这种自定义。

在其他情况下,您可能需要自定义多种模式类型,注入与特定模式类型实现无关的跨功能代理。例如,您可能需要将一个剖析代理注入到所有部署在应用服务器上的模式类型中。

本文将展示如何在不接触模式插件代码或更改模式定义的情况下扩展现有 VAPs。文中将展示如何构建一个插件,在 VAP 实例上注入和执行自定义代码,以及如何过滤该代码将插入其中的 VAP 实例。本文包含一个示例插件,用于将自定义代码插入到包含 WebSphere® Application Server 角色的 VAP 实例中。

场景

本文使用 Web Application Pattern Type VAP 作为插件注入技术的目标。该场景假设 Web Application Pattern 想要在安装 WebSphere Application Server 的同一个虚拟机上安装一些额外的二进制文件,然后在应用服务器启动后在它之上执行一些额外的配置。假设这些二进制文件需要将 50 GB 的额外磁盘附加到 WebSphere Application Server 虚拟机上,并挂载到文件夹 /dataStorageForAgent 上。该示例将展示如何编写一个 TopologyProcessor 实现来重写未解决的拓扑结构模型(vm-templates 部分)。TopologyProcessor 实现将过滤掉除包含 WebSphere Application Server 角色的部署外的所有 VAP 部署。在包含 WebSphere Application Server 角色的部署上,该实现将添加示例插件脚本包,并注入一个示例插件角色。

通过将示例插件角色 SInstall 添加到 WebSphere Application Server 角色所在的同一个 vm-template 节中,插件的生命周期被注入到 WebSphere Application Server 角色所在的相同虚拟机中。因此将调用示例插件部分 install.py,而且在插件部分安装步骤中,将从 Storehouse 存储库下载插件二进制文件。示例插件 configure.py 脚本将在配置步骤中调用。示例 configure.py 等待应用服务器启动,然后运行一个包含插件二进制文件的示例 shell 脚本。该示例还展示了如何使用 TopologyProcessor 注入需要的额外磁盘空间,并将其挂载到指定的文件夹中。

构建一个 VAP 插件,将自定义代码注入到现有模式中

以下各节将展示如何构建一个 VAP 插件,根据特定的条件将您自己的代码注入到运行的 VAP 实例中。此技术利用了 VAP 转换框架和 com.ibm.maestro.model.transform.TopologyProcessor 接口的一个实现,该实现可用于在部署之前处理和转换 VAP 拓扑结构。构建 VAP 插件:

  1. 创建一个 VAP 插件和相应的模式类型来捕获自定义代码实现。
  2. 在插件配置文件 config.json 中,为辅助模式类型定义个通配符值 “*”,使得该插件能够添加到任何 VAP 部署中。该插件将包含常规 VAP 部分和角色生命周期脚本,比如 install.py、configure.py、start.py 和 stop.py。
  3. 创建一个 TopologyProcessor 实现,它将定义一个过滤条件来识别要自定义的 VAP 实例。
  4. 对于选择要自定义的实例,更新为解决的拓扑结构 JSON 模型,并包含插件的脚本包和角色。
  5. 修改未解决的拓扑结构 JSON 模型,并添加您的代码需要的其他任何定制。例如,您可以修改拓扑结构 JSON 模型,添加一个存储卷,然后将它挂载到一个本地文件夹。

TopologyProcessor

本文中讨论的代码注入技术是使用 com.ibm.maestro.model.transform.TopologyProcessor 接口来实现的,本节将介绍这个接口。后面的几节将介绍插件生命周期脚本,以及包含模式类型二进制文件的插件执行脚本。在 VAP 部署期间,任何参与 VAP 和实现 com.ibm.maestro.model.transform.TopologyProcessor 接口的插件都可处理和修改拓扑结构定义,使该插件能够将任何自定义配置、角色或包注入到 VAP 拓扑结构中,无需对 VAP 模式执行代码更改或更改虚拟应用程序生成器中的模式定义。

在部署期间,PureApplication System 部署框架调用插件的 TopologyProcessor 实现中提供的公共 JSONObject processTopology(JSONObject topology) 方法。该拓扑结构对象方法签名表示要部署的实例的未解决的拓扑结构模型 TopologyProcessor 的插件实现可更改这个未解决的 JSON 模型,然后将更新的模型返回到部署框架。该框架使用返回的已更新拓扑结构 JSON 模型来部署实例。

本文提供了示例用例的 TopologyProcessor 实现。如清单 1 所示,processTopology(JSONObject topology) 方法中的代码首先寻找拓扑结构对象中的 vm-templates 节,以验证部署的实例是否拥有 WebSphere Application Server 角色:

清单 1. 验证 WebSphere Application Server 角色是否包含在部署中
private final String[] agentInjectToRoles = new String[] {"WAS"};
JSONArray templates = (JSONArray)topology.get("vm-templates");
for (Object obj : templates) {	
   if( injectPlugin(template) ) {
      .... inject the sample plug-in role and package here ....
      .... also add new disk and mount to vm folder here ....
      }
}
/** 
 * Return true here if you want the plug-in to attach to this type of role 
 */
protected boolean injectPlugin(JSONObject template)
{
   JSONArray rolesArray = (JSONArray)template.get("roles");
   if (rolesArray == null) {
      return false;    
   }    
   for (Object roleObj : rolesArray) { 
      JSONObject role = (JSONObject) roleObj;
      if(role.get("type") != null) { 
         String roleType = role.get("type").toString(); 
         for(String agentInjectRole : agentInjectToRoles) {
            if( roleType.equals(agentInjectRole))
               return true;	
          }
      } 
   }  
   return false;  
}

然后,如果 vm-template 包含 WebSphere Application Server 角色,那么该代码会添加示例插件角色和脚本包,如清单 2 所示。 示例插件生命周期脚本在实例激活期间调用。

清单 2. 添加角色和脚本包
addRoles(template, new JSONObject[] { sagentRole });
addPackages(template, new String[] { "SInstall" });

该代码还修改了拓扑结构模型定义,以便添加一个新磁盘,并将它挂载到 /dataStorageForAgent 挂载点上,如清单 3 所示:

清单 3. 添加新磁盘
JSONArray vmStorage = null;
if(template.get("storage") == null) {
   vmStorage = new JSONArray();
   template.put("storage", vmStorage);
}
else {
   vmStorage = (JSONArray) template.get("storage");
} 
addVMStorage(vmStorage, "ext-sagentSt1", "/dev/sdb",
   "/dataStorageForAgent");

示例 VAP 插件

除了 TopologyProcessor 实现之外,示例插件还定义了以下生命周期脚本和配置文件。有关 VAP 生命周期脚本和如何使用它们的更多信息,请参阅文章底部的 参考资料

config.json

此配置文件定义了此插件所属的模式类型。清单 4 显示了示例的配置文件。该插件将 SimpleInstallAgent 定义为主要的模式类型。此模式类型用于将插件导入 PureApplication System 中,并在必要时刷新插件。该配置还定义了一个辅助模式 “*”,则会意味着此插件可由系统中的任何模式类型使用。通过拥有一个辅助模式 “*”,插件可附加到任何已部署的 VAP 实例。

清单 4. 示例插件配置文件
"name": "sagent",
"version": "1.0.0.0",
"patterntypes": {
   "primary": {
      "SimpleInstallAgent": "1.0"
   },
   "secondary":[
      {
      "*":"*"
      }
   ] 
}

install.py

部分安装脚本从 Storehouse 存储库下载插件二进制文件并解压该文件,然后将它们转移到 /home/virtuser 文件夹下,如清单 5 所示:

清单 5. 部分安装脚本
# Copy your binary from storehouse into /tmp/downloads
downloadPath = '/tmp/downloads'
logger.debug('creating directory: ' + downloadPath);
maestro.trace_call(logger, ['mkdir', downloadPath])
storehousePath = 'SAgentBinaries/SampleContent.tar.gz'
logger.debug('start downloading AGENT install binaries from storehouse:
   %s to local folder: %s' % (storehousePath, downloadPath))
# Maestro unzip your binary into the location (downloadPath) you specified
installerUrl = urlparse.urljoin(maestro.filesurl, storehousePath)	
maestro.downloadx(installerUrl, downloadPath)
logger.debug('AGENT binaries download completed complete')
# move myproductInstall.sh script to /home/idcuser/ProductFolder
logger.debug('move scripts from /tmp/downloads to /home/virtuser ')
args=['mv', '/tmp/downloads/ProductFolder', '/home/virtuser']
logger.debug(args)
rc = maestro.trace_call(logger, args)
maestro.check_status(rc, 'Failed to move ProductFolder folder')

configure.py

此脚本在 /opt/IBM 文件夹下寻找 WebSphere Application Server startServer.log,并等待一个可用的日志。在找到该文件后,该脚本每隔 60 秒检查是否在文件中找到了消息 “Open for e-business”。找到此消息后,该脚本会使用 WebSphere Application Server 管理员用户凭据调用插件配置脚本 /home/virtuser/ProductFolder/productConfigure.sh。productConfigure.sh 简单地列出了可用的 Java 虚拟机 WebSphere Application Server API。清单 6 显示了 confgure.py 中的代码:

清单 6. 角色配置脚本
template = maestro.node['template']
user_id=''
user_pwd=''
if 'roles' in template:
   roles = template['roles']
   for role in roles:
      if 'name' in role and role['name'] == 'DMGR' and 'parms' in role:
         logger.debug('DMGR parms are %s' % role['parms'])
         for key in role['parms']:
            roleParms = role['parms'][key]
            if key == 'dmgr_user':
               user_id = roleParms
            elif key == 'dmgr_pwd':
               user_pwd = str(maestro.decode(roleParms))
            elif 'name' in role and role['name'] == 'WAS' and 'parms' in role:
               logger.debug('WAS parms are %s' % role['parms'])
               for key in role['parms']:
                  roleParms = role['parms'][key]
                  if key == 'USERID':
                     user_id = roleParms
                  elif key == 'PASSWORD':
                     user_pwd = str(maestro.decode(roleParms))
logPath=''
matches = []
while len(matches) == 0:
   for root, dirnames, filenames in os.walk('/opt/IBM'):
      for filename in fnmatch.filter(filenames, 'startServer.log'):
         matches.append(os.path.join(root, filename))
   time.sleep(60)
if len(matches) > 0:
   logPath = '%s' % matches[0]
wasInstalled = False
while wasInstalled == False:
   logger.debug('wait for the WAS server to start')
   if os.path.isfile(logPath):
      logger.debug('startServer.log file found, check status')
      with open(logPath, 'r') as content_file:
          content = content_file.read()
          if content.rfind('open for e-business') != -1:
             wasInstalled = True
          else:
             logger.debug('WAS start log content does not contain open
                 for e-business message, wait')          
   else:
      logger.debug('%s file not found, wait' % logPath)
   if wasInstalled == False:
      time.sleep(60)
logger.debug("WAS server is running, configure the agent now")
configscript = '/home/virtuser/ProductFolder/productConfigure.sh'
# run productConfigure.sh script
args=[configscript, user_id, user_pwd]
logger.debug('user_id is %s ' % user_id)
rc = maestro.trace_call(logger, args)
maestro.check_status(rc, 'Failed to run install scripts')

示例 VAP 模式类型

模式类型 exportSimpleInstallAgent-1.0.0.0.tgz 将示例二进制文件包装在 files/SampleContent.tar.gz 下。如果下载附加的示例并使用任何有效的解压工具打开此文件,您就会看到该 tar 归档文件包含以下文件:

  • productInstall.sh:该示例 shell 脚本展示如何使用脚本来从 parts install.py 生命周期脚本安装产品二进制文件。此脚本将在示例角色 SInstall 配置步骤之前执行。
  • productConfigure.sh:该示例 shell 脚本展示如何使用应用服务器管理员凭据执行应用服务器配置。此 shell 脚本由 SInstall 角色 configure.py 生命周期脚本调用。此脚本接受两个参数:WebSphere Application Server 管理员用户 ID 和密码。此脚本调用 listJvm.py 来列出 JVM。清单 7 演示了 productConfigure.sh 脚本。
清单 7. 示例应用服务器配置
#!/bin/sh
USER_ID=$1
USER_PWD=$2
echo "Configure the product "
WAS_BIN=`find /opt/IBM -name wsadmin.sh`
echo "WAS_BIN=$WAS_BIN"
echo "Configure agent"
DIR_NAME=$(dirname $0)
echo $DIR_NAME
pushd $DIR_NAME
echo "List JVM "
$WAS_BIN/wsadmin.sh -user $USER_ID -password $USER_PWD -f /home/virtuser/ProductFolder/listJvm.py
echo "End List JVM "
popd

将模式类型导入 PureApplication System 中时,二进制文件的 tar 归档文件将被上传到 Storehouse 存储库。Storehouse for PureApplication System 是一个包含系统和 VAP 工作负载工件的存储库。

要查看存储在 Storehouse 存储库中的工件,可导航到 Workload console => System => Storehouse Browser。 请注意,只有能够访问 System 菜单的用户才能查看 Storehouse Browser。

Storehouse 存储库可用于存储产品二进制文件,可在实例激活期间通过 VAP 实例进行访问。在以下段略中,您将看到如何使用 Storehouse 存储库存储示例插件二进制文件。

将插件二进制文件上传到 Storehouse 存储库

产品二进制文件可上传到 Storehouse 存储库,方法是将该二进制文件与包含 VAP 插件的模式类型包装在一起。我们将使用这种方法将示例二进制文件 SampleContent.tar.gz 上传到以下 Storehouse 存储库位置:/admin/files/SAgentBinaries/。

要将二进制文件 SampleContent.tar.gz 与模式类型包装在一起,首先需要定义模式类型中的文件夹格式,如图 1 所示。请注意,根据执行 Ant 脚本 addStorehouseFiles.xml 的需要,二进制归档文件位于文件夹 \patterntype.sagent\storehouse\files\SAgentBinaries 下,稍后将会解释这一点。

图 1. 模式类型结构
模式类型结构

放置二进制归档文件后,执行以下步骤来创建模式类型归档文件 \patterntype.sagent\exportSimpleInstallAgent-1.0.0.0.tgz:

  1. 构建模式类型和插件代码。要构建模式类型和插件而不使用二进制文件,请右键单击 patterntype.sagent 并选择 IBM Pattern Toolkit => Build
  2. 运行 \patterntype.sagent\addStorehouseFiles.xml:右键单击 \patterntype.sagent\addStorehouseFiles.xml 并选择 运行 As => Ant Build,将二进制文件添加到模式类型归档文件中。执行这个 Ant 脚本将生成一个具有合适的文件夹结构的模式类型,从而将二进制文件上传到 Storehouse 存储库位置 /admin/files/SAgentBinaries/。执行此步骤后,如果使用任何归档文件解压工具打开构建的模式类型,效果如图 2 所示。该归档文件包含一个 files 文件夹,其中包含二进制文件 SampleContent.tar.gz。
    图 2. 包含 Storehouse 二进制文件的模式类型归档文件
    包含 Storehouse 二进制文件的模式类型归档文件
    包含 Storehouse 二进制文件的模式类型归档文件
  3. 构建模式类型后,就可以将它导入 PureApplication System 中。转到 Workload Console,然后选择 Cloud => Pattern Types 链接。使用 plus 操作导入模式类型 tar 文件,该文件位于 /patterntype.sagent\export\SimpleInstallAgent-1.0.0.0.tgz 下。如果导入成功,那么您会在 Storehouse Browser 中看到 SampleContent.tar.gz,如图 3 所示。
    图 3. 导入模式类型后的 Storehouse 内容
    导入模式类型后的 Storehouse 内容
    导入模式类型后的 Storehouse 内容

使用示例

本文提供了以下示例模式类型(包含源代码):patterntype.sagent-1.0.0.0.tgz

将 patterntype.sagent-1.0.0.0.tgz 导入 IBM PureApplication System 中后,您会看到一个文件 /admin/files/SAgentBinaries/SampleContent.tar.gz 被添加到 Storehouse Browser 中,如图 3 所示。您还应该在 Workload Console => Cloud => Pattern Types 下看到名为 sample.sagent-1.0 的模式类型。

导入并启用模式类型 sample.sagent-1.0 后,部署 Web Application 模式类型的一个实例。部署 Web Application 模式类型后,执行以下步骤,验证示例插件角色 SInstall 是否已附加到运行 WebSphere Application Server 的虚拟机上:

  1. 在部署的实例的虚拟机透视图上,单击 Web Application 虚拟机的 Middleware Status 列下的 Show more 链接。您将会看到 SInstall 角色,如图 4 所示,它是示例插件定义的角色。
    图 4. 附加到 WebSphere Application Server 实例的示例角色
    附加到 WebSphere Application Server 实例的示例角色
    附加到 WebSphere Application Server 实例的示例角色
  2. 在同一个虚拟机上,单击 Log 链接。验证是否有一个针对 SInstall 角色的 trace.log。打开此日志(如图 5 所示)并检查示例插件代码是否已按预期调用。
    图 5.示例插件跟踪日志
    示例插件跟踪日志
    示例插件跟踪日志
  3. 在 WebSphere Application Server 实例上,使用 Manage => Operations => ssh 链接添加一个 ssh 密钥,然后使用 virtuser 作为用户名通过 ssh 登录到系统中。执行如图 6 所示的命令 df -h,验证是否能看到一个 50GB 的额外磁盘被附加到 /dataStorageForAgent。
    图 6. 示例挂载文件夹
    示例挂载文件夹
    示例挂载文件夹

结束语

本文介绍了一种自定义现有 VAP 模式并注入您的自定义代码的技术,它不需要更改现有模式插件代码或模式定义。此技术涉及到创建一个实现 TopologyProcessor 接口的新插件,以及创建合适的辅助模式配置,以便可以将该插件用于所有 VAP 模式部署。通过使用 TopologyProcessor 扩展,您了解了如何在部署期间更新任何 VAP 实例的拓扑结构定义,以及如何注入新插件角色和磁盘。


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Cloud computing, WebSphere
ArticleID=976095
ArticleTitle=使用 IBM PureApplication System 将自定义代码注入 Virtual Application Patterns 中
publish-date=06302014