Limitaciones de la migración

El software Migrate for Anthos y GKE automatiza el uso del conjunto de herramientas de migración de servidores de aplicaciones de IBM WebSphere para objetos binarios de aplicaciones en el clúster de Anthos o GKE para descubrir, evaluar y generar informes de migración y secuencias de comandos de configuración. Eres el único responsable de obtener, licenciar y usar el kit de herramientas.

La herramienta de análisis binario tiene varias limitaciones que debes tener en cuenta antes de comenzar a migrar apps tradicionales de WAS. En este documento, se describen estas limitaciones y se proporcionan soluciones alternativas que te permiten migrar tus aplicaciones tradicionales de WAS.

Para cada app tradicional de WAS que migras, Migrate for Anthos y GKE crean una secuencia de comandos de Python .py y archivos XML del servidor que se usan cuando se compila el contenedor de la app. Las soluciones alternativas para estas limitaciones requieren que edites la secuencia de comandos .py de Python o el archivo de configuración XML del servidor antes de implementar un contenedor de app. La secuencia de comandos de Python .py y los archivos XML del servidor forman parte de los artefactos de migración. Para obtener instrucciones sobre cómo acceder y descargar el archivo, consulta Antes de comenzar.

No se extrajo la configuración de SSL de JMS para el contenedor de destino tradicional de WAS

La herramienta de análisis de objetos binarios no extrae la información de configuración de SSL de JMS para un Connection Factory en cola y la especificación de la activación. En este procedimiento, se describe cómo migrar una configuración SSL de JMS cuando se usan certificados SSL administrados de forma central en WAS tradicional.

Para obtener más información, consulta la documentación de IBM aquí.

Solución alternativa de configuración de SSL

A fin de editar la secuencia de comandos .py de Python para que la app agregue información de configuración de SSL, agrega la marca -sslType=CENTRAL al nivel de la especificación de activación o del Connection Factory en cola.

A continuación, se muestran ejemplos de la especificación de activación y el Connection Factory en cola de la secuencia de comandos de Python .py:

Especificación de activación:

AdminTask.createWMQActivationSpec(Node, ["-name", "BrownActivationSpecification",
 "-jndiName", "jms/BrownActivationSpecification", "-authAlias", "m4a-twas-ndNode01/BrownAuthAlias",
 "-destinationJndiName", "jms/BrownRequestQueue", "-destinationType", "javax.jms.Queue",
 "-qmgrHostname", "m4a-db2-mq.c.velos-auto-1.internal", "-qmgrName", "LQM1",
 "-qmgrPortNumber", "1414", "-qmgrSvrconnChannel", "CLOUD.APP.SVRCONN",
 "-wmqTransportType", "BINDINGS_THEN_CLIENT"])

Connection Factory en cola:

AdminConfigVar_0=AdminTask.createWMQConnectionFactory(Node, ["-name", "BrownConnectionFactory",
 "-jndiName", "jms/BrownConnectionFactory", "-type", "QCF", "-mappingAlias",
 "DefaultPrincipalMapping", "-containerAuthAlias", "m4a-twas-ndNode01/BrownAuthAlias", "-qmgrName", "LQM1",
 "-qmgrHostname", "m4a-db2-mq.c.velos-auto-1.internal",
 "-qmgrPortNumber", "1414", "-qmgrSvrconnChannel", "CLOUD.APP.SVRCONN",
 "-wmqTransportType", "BINDINGS_THEN_CLIENT"])

En el siguiente ejemplo, se muestran las modificaciones necesarias para agregar la marca -sslType=CENTRAL. Solo tienes que admitir una de estas especificaciones

Especificación de activación:

AdminTask.createWMQActivationSpec(Node, ["-name", "BrownActivationSpecification",
 "-jndiName", "jms/BrownActivationSpecification", "-authAlias", "m4a-twas-ndNode01/BrownAuthAlias",
 "-destinationJndiName", "jms/BrownRequestQueue", "-destinationType", "javax.jms.Queue",
 "-qmgrHostname", "m4a-db2-mq.c.velos-auto-1.internal", "-qmgrName", "LQM1",
 "-qmgrPortNumber", "1414", "-qmgrSvrconnChannel", "CLOUD.APP.SVRCONN",
 "-wmqTransportType", "BINDINGS_THEN_CLIENT", "-sslType", "CENTRAL"])

Connection Factory en cola:

AdminConfigVar_0=AdminTask.createWMQConnectionFactory(Node, ["-name", "BrownConnectionFactory",
 "-jndiName", "jms/BrownConnectionFactory", "-type", "QCF", "-mappingAlias",
 "DefaultPrincipalMapping", "-containerAuthAlias", "m4a-twas-ndNode01/BrownAuthAlias", "-qmgrName", "LQM1",
 "-qmgrHostname", "m4a-db2-mq.c.velos-auto-1.internal",
 "-qmgrPortNumber", "1414", "-qmgrSvrconnChannel", "CLOUD.APP.SVRCONN",
 "-wmqTransportType", "BINDINGS_THEN_CLIENT", "-sslType", "CENTRAL"])

Se omite la información de autenticación de LDAP para el contenedor de destino tradicional de WAS

Cuando una app usa la autenticación de LDAP, la secuencia de comandos de Python .py para la app omite esa información de LDAP. Como solución alternativa, edita la secuencia de comandos .py de Python para agregar la información necesaria.

La información de LDAP se escribe en los archivos appname_server.xml y appname_server_sensitiveData.xml creados para la app. Estos archivos se escriben en la carpeta /deploy del depósito de Cloud Storage que contiene los artefactos de migración.

La información que necesitas se encuentra en un conjunto de variables en estos archivos. Por ejemplo, de appname_server.xml:

<!-- The following variables, which often differ between environments
     have been extracted from the migrated configuration to allow
     for easy substitution. -->
    <variable defaultValue="9080" name="httpEndpoint_port_4"/>
    <variable defaultValue="1389" name="ldapRegistry_port_4"/>
    <variable defaultValue="m4a-db2-mq.c.my-co.internal" name="ldapRegistry_host_4"/>
    <variable defaultValue="9443" name="httpEndpoint_secure_port_4"/>
    <variable defaultValue="*" name="httpEndpoint_host_4"/>
    <variable defaultValue="ou=users,dc=example,dc=org" name="ldapRegistry_baseDN_4"/>

Y desde appname_server_sensitiveData.xml:

<!-- The following variables are used to replace sensitive data in the
     server.xml file for the application. -->
    <variable name="ldapRegistry_bindDN_1" defaultValue="cn=admin,dc=example,dc=org"/>
    <variable name="ldapRegistry_bindPassword_1" defaultValue="PASSWORD"/>

Edita la secuencia de comandos Python de .py para que la app agregue definiciones de variables y comandos adicionales a fin de crear y configurar LDAPUserRegistry, y convertirlo en el registro predeterminado en seguridad global. Agrega estas líneas después de la línea NodeName=AdminControl.getNode():

. . .
NodeName=AdminControl.getNode()

# The following variables are used to replace sensitive data in the
# configuration for the application.
# ============================================================
ldapRegistry_bindDN='cn=admin,dc=example,dc=org'
ldapRegistry_bindPassword='PASSWORD'
# ============================================================

# LDAP related variables
# ============================================================
ldapRegistry_port='1389'
#ldapRegistry_host='m4a-db2-mq.c.my-co.internal'
ldapRegistry_host='35.241.207.81'
ldapRegistry_baseDN='ou=users,dc=example,dc=org'
ldapRegistry_primaryAdminId='cn=user01,ou=users,dc=example,dc=org'
ldapRegistry_userFilter='(&(uid=%v)(objectclass=posixAccount))'
# ============================================================

print 'Starting Creating LDAP Registry'
# https://www.ibm.com/support/knowledgecenter/SSEQTP_8.5.5/com.ibm.websphere.base.iseries.doc/ae/rxml_7securityconfig.html#rxml_7securityconfig__SecurityConfigurationCommands.cmd7
AdminTask.configureAdminLDAPUserRegistry(['-autoGenerateServerId', 'true', '-primaryAdminId', ldapRegistry_primaryAdminId, '-ldapServerType', 'CUSTOM', '-ldapHost',
 ldapRegistry_host, '-ldapPort', ldapRegistry_port, '-baseDN', ldapRegistry_baseDN, '-bindDN', ldapRegistry_bindDN, '-bindPassword', ldapRegistry_bindPassword,
 '-userFilter', ldapRegistry_userFilter, '-groupFilter', '(&(cn=%v)(|(objectclass=groupOfNames)(objectclass=groupOfUniqueNames)))', '-userIdMap',
 '*:uid', '-groupIdMap', '*:cn', '-groupMemberIdMap', 'ibm-allGroups:member;ibm-allGroups:uniqueMember;groupOfNames:member;groupOfUniqueNames:uniqueMember'])

AdminConfig.save()

print 'Starting Creating Admin Security Settings'

# https://www.ibm.com/support/knowledgecenter/SSEQTP_8.5.5/com.ibm.websphere.base.iseries.doc/ae/rxml_7securityconfig.html#rxml_7securityconfig__SecurityConfigurationCommands.cmd8
AdminTask.setAdminActiveSecuritySettings(['-enableGlobalSecurity', 'true', '-cacheTimeout', '300', '-enforceJava2Security', 'false', '-appSecurityEnabled', 'true', '-activeUserRegistry', 'LDAPUserRegistry'])

AdminConfig.save()

. . .

Se omitió la información de control de acceso según la función (RBAC) para el contenedor de destino tradicional de WAS

Cuando una app de WAS está configurada para usar la autorización de control de acceso según la función (RBAC), debes asignar funciones de aplicación a usuarios, grupos o usuarios especiales como Todos o Ninguno. La herramienta de análisis de objetos binarios no extrae esta configuración, pero es necesaria para que la aplicación funcione y aplique la autorización como se espera.

A fin de configurar RBAC para la aplicación, edita el comando de instalación de la aplicación en la secuencia de comandos Python de .py para la aplicación.

A continuación, se muestra un comando de instalación de aplicación de muestra en la secuencia de comandos de Python .py sin las funciones para la asignación de usuarios:

AdminApp.install('/work/config/SuperSnoop.ear', ["-node", NodeName, "-server", "server1", "-appname", "SuperSnoop.ear"])

Para aplicar reglas de asignación de funciones, edita la secuencia de comandos de Python .py para que la app agregue la marca -MapRolesToUsers como se muestra a continuación:

AdminApp.install('/work/config/SuperSnoop.ear', ["-node", NodeName, "-server", "server1", "-appname", "SuperSnoop.ear",
 "-MapRolesToUsers", [["Manager", "AppDeploymentOption.No", "AppDeploymentOption.No",
 "cn=user02,ou=users,dc=example,dc=org", "some_group_name"]]])

Para obtener más información, consulta la documentación de IBM aquí.

Cambia el cargador de clase de la aplicación

Las aplicaciones de WebSphere pueden usar archivos JAR que entran en conflicto con los archivos JAR que proporciona WebSphere. Para superar cualquier conflicto de archivos JAR, puedes controlar el orden de cargador de clase de una aplicación o para un módulo WAR.

Por ejemplo, puedes especificar para usar primero el cargador de clase de la aplicación, o bien usar un cargador de clase único para toda la aplicación en lugar de usar el cargador de clase de WebSphere y el cargador de clase de la aplicación.

Los cambios en el cargador de clase de la aplicación no se extraen con la herramienta de análisis de objetos binarios, por lo que debes editar el comando de instalación de la aplicación en la secuencia de comandos .py de Python para que la app aplique estos cambios.

Configuración del servidor dde muestra

En una aplicación con la configuración del cargador de clase modificada, los cambios se almacenan en el archivo descriptor de la aplicación, deployment.xml. Por ejemplo, el descriptor de implementación tiene la configuración del cargador de clase como se indica a continuación:

<?xml version="1.0" encoding="UTF-8"?>
<appdeployment:Deployment xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:appdeployment="http://www.ibm.com/websphere/appserver/schemas/5.0/appdeployment.xmi" xmi:id="Deployment_1614732697">
  <deployedObject xmi:type="appdeployment:ApplicationDeployment" xmi:id="ApplicationDeployment_1614732697"
    deploymentId="0" startingWeight="1" binariesURL="CurrenciesServices/CurrenciesServices.ear"
    useMetadataFromBinaries="false" enableDistribution="true" warClassLoaderPolicy="SINGLE"
    createMBeansForResources="true" reloadEnabled="false" appContextIDForSecurity="href:was-nd-2Cell01/CurrenciesServices"
    filePermission=".*\.dll=755#.*\.so=755#.*\.a=755#.*\.sl=755" allowDispatchRemoteInclude="false"
    allowServiceRemoteInclude="false" asyncRequestDispatchType="DISABLED" standaloneModule="true" enableClientModule="false">
    <targetMappings xmi:id="DeploymentTargetMapping_1614732697" enable="true" target="ClusteredTarget_1614732697"/>
    <classloader xmi:id="Classloader_1614732697" mode="PARENT_LAST"/>
    <modules xmi:type="appdeployment:WebModuleDeployment" xmi:id="WebModuleDeployment_1614732697" deploymentId="1" startingWeight="10000" uri="CurrenciesServices.war" containsEJBContent="0">
      <targetMappings xmi:id="DeploymentTargetMapping_1614732698" target="ClusteredTarget_1614732697"/>
      <classloader xmi:id="Classloader_1614732698"/>
    </modules>
    <properties xmi:id="Property_1614732697" name="metadata.complete" value="true"/>
  </deployedObject>
  <deploymentTargets xmi:type="appdeployment:ClusteredTarget" xmi:id="ClusteredTarget_1614732697" name="Cluster1"/>
</appdeployment:Deployment>

Las dos secciones relevantes del descriptor de implementación son los valores SINGLE y PARENT_LAST que debes migrar de forma manual. Para aplicar los cambios del cargador de clase, edita la secuencia de comandos .py de Python.

A continuación, se muestra un comando de instalación de aplicación de muestra en la secuencia de comandos .py de Python:

AdminApp.install('/work/app/CurrenciesServices.war',
  [ "-node", NodeName, "-server", "server1", "-appname", "CurrenciesServices.war",
    "-contextroot", "/CurrenciesServices", "-CtxRootForWebMod",
    [["TafnitCurrenciesServices", "CurrenciesServices.war,WEB-INF/web.xml", "/CurrenciesServices"]]])

AdminConfig.save()

Para aplicar los cambios del cargador de clase, edita la secuencia de comandos .py de Python para que la app agregue la configuración como se muestra a continuación:

AdminApp.install('/work/app/CurrenciesServices.war',
  ["-node", NodeName, "-server", "server1", "-appname", "CurrenciesServices.war",
    "-contextroot", "/CurrenciesServices", "-CtxRootForWebMod",
    [["TafnitCurrenciesServices", "CurrenciesServices.war,WEB-INF/web.xml", "/CurrenciesServices"]]])

dep = AdminConfig.getid('/Deployment:CurrenciesServices.war/')
depObject = AdminConfig.showAttribute(dep, 'deployedObject')
classldr = AdminConfig.showAttribute(depObject, 'classloader')
print AdminConfig.showall(classldr)
print AdminConfig.show(depObject, 'warClassLoaderPolicy')
AdminConfig.modify(classldr, [['mode', 'PARENT_LAST']])
AdminConfig.modify(depObject, [['warClassLoaderPolicy', 'SINGLE']])

AdminConfig.save()

Próximos pasos