перадгісторыя
У адной медыцынскай арганізацыі ўкаранялі рашэнні на базе PACS-сервераў Orthanc і DICOM-кліента Radiant. У ходзе наладкі высветлілі, што кожны DICOM-кліент павінен быць апісаны ў PACS-серверах наступным чынам:
- Імя кліента
- AE-імя (павінна быць унікальна)
- TCP-порт, які аўтаматычна адчыняецца на боку кліента і прымае DICOM-абследаванні ад PACS-сервера (г.зн. сервер як бы штурхае іх у бок кліента – ініцыюючы злучэнне першым)
- IP-адрас
Пасля настройкі Radiant кліентаў атрымалі наступную інфармацыю да разважання – у кожнага кліента настройка ПЗ з названымі вышэй параметрамі прыводзіла да запаўнення файла pacs.xml, які размяшчаўся ў профілі карыстальніка (шлях: %APPDATA%RadiantViewerpacs.xml). Пры гэтым канфіг аднаго кліента ад іншага адрозніваўся мінімум двума параметрамі (AE-імя ва ўсіх рознае, а порт у асноўным аднолькавы, акрамя тэрмінальных кліентаў, якія працуюць на адным і тым жа серверы - тамака парты таксама прыходзілася прызначаць рознымі).
Прыклад файла pacs.xml па
Прыкладна паўгода ўсё было добра, сістэма зарабіла…і тут да нас дайшліпадводныя камяні»:
- Нам трэба ўвесці ў строй некалькі новых PACS-сервераў, якія падменяць старыя (дзе стала сканчацца месца на кружэлках). PACS сервера ў віртуальных машынах, але гаворка не пра гэта;
- Нам трэба неяк цэнтралізавана змяніць унікальныя канфігурацыі (двума адрознымі параметрамі) на 200 машынах (іх колькасць рэгулярна павялічвалася);
- Улічваючы тэмпы росту аб'ёмаў абследаванняў, рашэнне трэба не разавае, а якое тыражуецца і рэгулярнае (напрыклад, 1 раз у 3-5 месяцаў).
Выбар інструментара для рашэння задачы
Спачатку былі спробы знайсці нейкае рашэнне, якое на баку кліента змяняла файл pacs.xml, і ўносіла ў яго змены ў спіс PACS-сервераў, не чапаючы налады AE-імя і TCP-порта. Windows кліенты на той момант былі на базе як Windows XP, так і Windows 7 - таму былі спробы напісаць нешта такое на базе VBScript. Але нажаль – здужаць такую задачу не атрымалася, з прычыны поўнай адсутнасці досведу напісання чагосьці складанага і комплекснага на гэтай мове. Спробы ж знайсці і перапісаць таксама не ўвянчаліся поспехам (тут трэба адзначыць, што ў галаве ўжо быў іншы план, таму я не дзяўбіўся з VBScript больш 3-4 гадзін).
У выніку я спыніўся на наступным рашэнні:
- Сабраць групавой палітыкай усе файлы pacs.xml у адным месцы на якім ні будзь серверы ў сеткавым рэсурсе;
- Змяніць файлы гуртам (досвед рашэння такіх задач ужо быў – з выкарыстаннем Perl);
- Таксама з дапамогай групавых палітык абнавіць наладкі кліентаў.
Збор файлаў з дапамогай групавой палітыкі
Самая простая частка - пры ўваходзе кліента ў свой профіль ён са сваімі правамі выконвае нейкі .bat файл, у якім прапісана:
echo off
If exist %APPDATA%RadiantViewerpacs.xml copy %APPDATA%RadiantViewerpacs.xml srv.test.localpconfigs$pacs-%COMPUTERNAME%-%USERNAME%.xml
Такім чынам на серверы ва ўтоеным рэсурсе будуць назапашвацца файлы pacs.xml, у імі якіх ёсць інфармацыя з якога кампутара і з якога карыстача быў скапіяваны дадзены канфіг.
Самае складанае было - дачакацца, калі ва ўсіх карыстальнікаў адпрацуе дадзеная палітыка.
Змяненне канфігурацый з дапамогай Perl скрыпту
Нам спатрэбіцца
Сам жа скрыпт атрымаўся даволі просты.
use XML::Writer;
# Открываем папку с отчетами, обрабатываем ссписок (удаляем лишнее):
$report_dir = "C:Perl64WORKPACS-xml3";
opendir(DIR, "$report_dir") or die "Не могу открыть папку с отчетами!";
@report_files = readdir DIR;
shift (@report_files); # удаляем точку из элементов массива (.)
shift (@report_files); # удаляем две точки из элементов массива (..)
# print "@report_files";
closedir(DIR);
# Начинаем обрабатывать файлы - по одному за раз. Нужно считать параметр AET и номер порта в переменные.
foreach $analiz_file (@report_files)
{
$full_path_to_file="C:Perl64WORKPACS-xml3".$analiz_file;
open (INFO, $full_path_to_file);
while ($line = <INFO>)
{
# Переменные $aet и $port содержат уникальные данные для каждого XML файла:
my ($other1, $aet, $other2, $port, $other3) = split /"/, $line, 5;
# Если встречается строка listener - то мы дошли до нужной строчки и можно формировать новый XML:
if ($other1 =~ 'listener')
{
# Формируем новый XML c нужными полями и данными:
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');
# Помещаем готовый XML в переменную:
my $xml = $writer->end();
# Подготавливаем файл для перезаписи:
$rewritexml = $full_path_to_file;
# Переписываем XML файлы новыми данными:
open (NEWXML, ">$rewritexml");
print NEWXML $xml;
close (NEWXML);
}
}
}
Прынцып яго працы:
- Адкрываем каталог, у якім у нас сабраны канфігурацыі pacs.xml ад кліентаў і змяшчаем спіс файлаў у масіў скаляраў (@report_files);
- У цыкле апрацоўваем па адным файле і счытваем яго парадкова;
- З дапамогай split дробім кожны радок на 5 частак, выкарыстоўваючы двукоссі як падзельнік;
- Знаходзім радок са словам listener і змяшчаем у дзве зменныя ўнікальныя для кожнага файла дадзеныя (AE-імя кліента і нумар TCP-порта);
- Пасля гэтага проста фармуем новы XML-файл, упісваем у яго ўнікальныя параметры і далей устаўляем патрэбную колькасць PACS-сервераў з іх параметрамі – г.зн. тое, дзеля чаго ўсё ладзілася)
- Перапісваем новы XML-файл па-над старым.
Трэба адзначыць, што насамрэч я выкарыстоўваю дадзены скрыпт не цалкам аўтаматычна – у сутнасці я капіюю збіраныя канфігі ў асобны каталог і потым запускаючы скрыпт змяняю іх усім гуртам. Далей выбарачная праверка і канфігі можна разліваць зваротна па машынах.
Распаўсюджванне змененых pacs.xml файлаў па кліентах
Самае простае, што прыйшло ў галаву - унесці змены ва ўжо які працуе .bat файл, які збірае канфігурацыі з кліентаў і дадаць радок:
If exist %APPDATA%RadiantViewerpacs.xml copy /Y srv.test.localpconfigsnew$pacs-%COMPUTERNAME%-%USERNAME%.xml %APPDATA%RadiantViewerpacs.xml
Выніковы .bat файл выглядае так:
@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
Заключэнне
Такое вось «накаленкавы» рашэнне. Выпрабавалі яго ўжо два разы (у верасні 2018 і ў лютым 2019), пакуль палёт нармальны. Вядома абнаўляе не 100% кліентаў, але блізка да гэтага значэння - астатніх дарабляем выдалена. Скрыпт па
Крыніца: habr.com