Antecedentes
En una organización médica, se implementaron soluciones basadas en servidores PACS Orthanc y el cliente DICOM Radiant. Durante la configuración, se descubrió que cada cliente DICOM debe ser descrito en los servidores PACS de la siguiente manera:
- Nombre del cliente
- Nombre AE (debe ser único)
- Puerto TCP que se abre automáticamente en el lado del cliente y recibe los estudios DICOM del servidor PACS (es decir, el servidor por así decirlo empuja los datos hacia el cliente, iniciando primero la conexión)
- Dirección IP
Después de configurar los clientes Radiant, obtuvimos la siguiente información para reflexionar: para cada cliente, la configuración del software con los parámetros mencionados anteriormente llevaba a completar el archivo pacs.xml, que se encontraba en el perfil del usuario (ruta: %APPDATA%RadiantViewerpacs.xml). Sin embargo, la configuración de un cliente se diferenciaba de la de otro por al menos dos parámetros (el nombre AE era diferente para todos, mientras que el puerto generalmente era el mismo, excepto para los clientes terminales que operaban en el mismo servidor; ahí también era necesario asignar puertos diferentes).
Ejemplo del archivo pacs.xml :
Durante aproximadamente seis meses todo estuvo bien, el sistema funcionó… y entonces nos llegaron las «piedras bajo el agua»:
- Necesitamos poner en funcionamiento varios nuevos servidores PACS que reemplazarán a los antiguos (donde el espacio en los discos se estaba agotando). Los servidores PACS están en máquinas virtuales, pero no es de eso de lo que se trata;
- Necesitamos de alguna manera cambiar centralizadamente las configuraciones únicas (con dos parámetros diferenciados) en 200 máquinas (su número aumentaba regularmente);
- Teniendo en cuenta el ritmo de crecimiento en el volumen de estudios, la solución no debe ser puntual, sino replicable y regular (por ejemplo, 1 vez cada 3-5 meses).
La solución a continuación.
Selección de herramientas para resolver la tarea
Al principio se intentó encontrar alguna solución que alterara el archivo pacs.xml en el lado del cliente, y realizara cambios en la lista de servidores PACS, sin tocar las configuraciones del nombre AE y el puerto TCP. En ese momento, los clientes de Windows estaban basados tanto en Windows XP como en Windows 7, por lo que se intentaron escribir cosas así en VBScript. Pero lamentablemente, no se pudo llevar a cabo tal tarea, debido a la completa falta de experiencia en la programación de algo complejo y complejo en este lenguaje. También los intentos de encontrar y reescribir no tuvieron éxito (es necesario mencionar que ya tenía otro plan en mente, por lo que no seguí luchando con VBScript más de 3-4 horas).
Al final, me detuve en la siguiente solución:
- Reunir todas las archivos pacs.xml en un solo lugar en cualquier servidor del recurso de red;
- Modificar los archivos en lote (ya se tiene experiencia resolviendo tareas similares, utilizando Perl);
- También actualizar la configuración de los clientes utilizando políticas de grupo.
Recolección de archivos mediante políticas de grupo
La parte más sencilla es que al ingresar el cliente en su perfil, ejecuta un archivo .bat con los siguientes comandos:
echo off
If exist %APPDATA%RadiantViewerpacs.xml copy %APPDATA%RadiantViewerpacs.xml srv.test.localpconfigs$pacs-%COMPUTERNAME%-%USERNAME%.xml
De este modo, en el servidor en un recurso oculto se irán acumulando archivos pacs.xml, cuyos nombres contienen información sobre desde qué computadora y de qué usuario se copió esta configuración.
Lo más complicado fue esperar a que todos los usuarios aplicaran esta política.
Modificación de configuraciones mediante un script Perl
Necesitaremos para Windows de ActiveState, así como el módulo XML::Writer, que se puede instalar con el comando ppm install XML-Writer.
El script resultó ser bastante simple:
use XML::Writer;
# Abrimos la carpeta de informes, procesamos la lista (eliminamos lo innecesario):
$report_dir = "C:Perl64WORKPACS-xml3";
opendir(DIR, "$report_dir") or die "¡No puedo abrir la carpeta de informes!";
@report_files = readdir DIR;
shift (@report_files); # eliminamos el punto de los elementos del array (.)
shift (@report_files); # eliminamos dos puntos de los elementos del array (..)
# print "@report_files";
closedir(DIR);
# Comenzamos a procesar los archivos - uno a la vez. Necesitamos leer el parámetro AET y el número de puerto en variables.
foreach $analiz_file (@report_files)
{
$full_path_to_file="C:Perl64WORKPACS-xml3".$analiz_file;
open (INFO, $full_path_to_file);
while ($line = )
{
# Las variables $aet y $port contienen datos únicos para cada archivo XML:
my ($other1, $aet, $other2, $port, $other3) = split /"/, $line, 5;
# Si encontramos la cadena listener - hemos llegado a la línea necesaria y podemos formar el nuevo XML:
if ($other1 =~ 'listener')
{
# Formamos el nuevo XML con los campos y datos necesarios:
my $writer = XML::Writer->new(OUTPUT => 'self', DATA_MODE => 1, DATA_INDENT => 2);
$writer->xmlDecl('utf-8');
$writer->startTag('pacs');
$writer->startTag('listener', ae => $aet, port => $port);
$writer->endTag();
$writer->startTag('hosts');
$writer->startTag('host', name => 'MRT', ae => 'ORTHANC', ip => 'XX.YY.214.17', ts => '1.2.840.10008.1.2.1', port => '4242', maxassoc => '1', allpres => '0', search => '1', protocol => '1', searchcharset => '', wildcards => '3', carets => '0');
$writer->endTag();
$writer->startTag('host', name => 'KT', ae => 'ORTHANC2', ip => 'XX.YY.215.253', ts => '1.2.840.10008.1.2.1', port => '4242', maxassoc => '1', allpres => '0', search => '1', protocol => '1', searchcharset => '', wildcards => '3', carets => '0');
$writer->endTag();
$writer->startTag('host', name => 'R', ae => 'ORTHANC3', ip => 'XX.YY.215.252', ts => '1.2.840.10008.1.2.1', port => '4242', maxassoc => '1', allpres => '0', search => '1', protocol => '1', searchcharset => '', wildcards => '3', carets => '0');
$writer->endTag();
$writer->startTag('host', name => 'KT-20180501-20180831', ae => 'ORTHANC4', ip => 'XX.YY.215.251', ts => '1.2.840.10008.1.2.1', port => '4242', maxassoc => '1', allpres => '0', search => '1', protocol => '1', searchcharset => '', wildcards => '3', carets => '0');
$writer->endTag();
$writer->startTag('host', name => 'KT-20180901-20181130', ae => 'ORTHANC5', ip => 'XX.YY.215.250', ts => '1.2.840.10008.1.2.1', port => '4242', maxassoc => '1', allpres => '0', search => '1', protocol => '1', searchcharset => '', wildcards => '3', carets => '0');
$writer->endTag();
$writer->endTag('hosts');
$writer->startTag('presets');
$writer->endTag();
$writer->startTag('lastsearch', dt => '4', mfid => '1048592');
$writer->endTag();
$writer->endTag('pacs');
# Almacenamos el XML listo en una variable:
my $xml = $writer->end();
# Preparamos el archivo para sobrescribir:
$rewritexml = $full_path_to_file;
# Sobrescribimos los archivos XML con los nuevos datos:
open (NEWXML, "> $rewritexml");
print NEWXML $xml;
close (NEWXML);
}
}
}
Principio de su funcionamiento:
- Abrimos el catálogo donde hemos recopilado las configuraciones pacs.xml de los clientes y colocamos la lista de archivos en un array escalar (@report_files);
- En un bucle, procesamos un archivo a la vez y lo leemos línea por línea;
- Con split dividimos cada línea en 5 partes, usando las comillas como separador;
- Encontramos la línea con la palabra listener y ponemos en dos variables únicas para cada archivo los datos (nombre del cliente y número de puerto TCP);
- Después de eso, simplemente formamos un nuevo archivo XML, escribimos en él los parámetros únicos y luego insertamos la cantidad necesaria de servidores PACS con sus parámetros – es decir, lo que se perseguía al final)
- Reescribimos el nuevo archivo XML sobre el antiguo.
Cabe destacar que, en realidad, no utilizo este script de forma completamente automática; en esencia, copio las configuraciones recopiladas en un directorio separado y luego, al ejecutar el script, las modifico todas a la vez. Luego realizo una verificación selectiva, y las configuraciones se pueden redistribuir a las máquinas.
Distribución de los archivos pacs.xml modificados entre los clientes
Lo más simple que se me ocurrió fue hacer cambios en un archivo .bat que ya está en funcionamiento, el cual recopila configuraciones de los clientes y añadir la línea:
If exist %APPDATA%RadiantViewerpacs.xml copy /Y srv.test.localpconfigsnew$pacs-%COMPUTERNAME%-%USERNAME%.xml %APPDATA%RadiantViewerpacs.xml
El archivo .bat final se ve así:
@echo off
If exist %APPDATA%RadiantViewerpacs.xml copy %APPDATA%RadiantViewerpacs.xml srv.test.localpconfigs$pacs-%COMPUTERNAME%-%USERNAME%.xml
If exist %APPDATA%RadiantViewerpacs.xml copy /Y srv.test.localpconfigsnew$pacs-%COMPUTERNAME%-%USERNAME%.xml %APPDATA%RadiantViewerpacs.xml
Conclusión
Este es un «solución improvisada» Hemos probado esto ya dos veces (en septiembre de 2018 y en febrero de 2019), hasta ahora todo funciona bien. Claro que no actualiza el 100% de los clientes, pero está cerca de ese valor — los demás los terminamos de manera remota. El script sobre .
Fuente: habr.com
