Zmiana ustawień programów przy zachowaniu osobistych parametrów

Tło

W jednej organizacji medycznej wdrażano rozwiązania oparte na serwerach PACS Orthanc i kliencie DICOM Radiant. Podczas konfiguracji okazało się, że każdy klient DICOM musi być opisany w serwerach PACS w następujący sposób:

  • Nazwa klienta
  • Nazwa AE (musi być unikalna)
  • Port TCP, który automatycznie otwiera się po stronie klienta i odbiera badania DICOM z serwera PACS (tj. serwer jakby przekazuje je w stronę klienta – inicjując połączenie jako pierwszy)
  • Adres IP

Po skonfigurowaniu klientów Radiant uzyskano następujące informacje do przemyślenia – każdy klient z ustawieniami o podanych powyżej parametrach prowadził do wypełnienia pliku pacs.xml, który znajdował się w profilu użytkownika (ścieżka: %APPDATA%RadiantViewerpacs.xml). Należy przy tym zaznaczyć, że konfiguracja jednego klienta różniła się od drugiego przynajmniej dwoma parametrami (AE-nazwa była różna dla wszystkich, a port zazwyczaj był ten sam, z wyjątkiem klientów terminalowych działających na tym samym serwerze – tam porty również musiały być nadawane różnie).

Przykład pliku pacs.xml wg linkiem:

W ciągu około sześciu miesięcy wszystko działało dobrze, system zaczynał funkcjonować... i wtedy dotarły do nas „podwodne kamienie»:

  • Musimy wprowadzić do eksploatacji kilka nowych serwerów PACS, które zastąpią stare (gdzie zaczynało brakować miejsca na dyskach). Serwery PACS w wirtualnych maszynach, ale to nie o tym;
  • Musimy jakoś centralnie zmienić unikalne konfiguracje (dwiema różnymi parametrami) na 200 maszyn (ich liczba regularnie rosła);
  • Biorąc pod uwagę tempo wzrostu ilości badań, rozwiązanie musi być nie jednorazowe, ale replikowalne i regularne (na przykład co 3-5 miesięcy).

Rozwiązanie poniżej.

Wybór narzędzi do rozwiązania problemu

Na początku były próby znalezienia jakiegoś rozwiązania, które po stronie klienta zmieniało plik pacs.xml, wprowadzając w nim zmiany w liście serwerów PACS, nie ruszając ustawień nazwy AE i portu TCP. Klienci Windows w tamtym czasie działali na systemach zarówno Windows XP, jak i Windows 7 – dlatego próby napisania czegoś opartego na VBScript. Ale niestety – nie udało się zrealizować takiego zadania, z powodu całkowitego braku doświadczenia w pisaniu czegoś skomplikowanego i złożonego w tym języku. Próby znalezienia i przepisania również nie przyniosły sukcesów (należy tutaj zaznaczyć, że w głowie miałem już inny plan, więc nie traciłem więcej niż 3-4 godziny na VBScript).

Ostatecznie zdecydowałem się na następujące rozwiązanie:

  • Zbierz wszystkie pliki pacs.xml w jednym miejscu na dowolnym serwerze w zasobie sieciowym za pomocą polityki grupowej;
  • Zmień pliki masowo (już mieliśmy doświadczenie w rozwiązywaniu takich problemów - z użyciem Perla);
  • Także za pomocą polityk grupowych zaktualizuj ustawienia klientów.

Zbieranie plików za pomocą polityki grupowej

Najprostszą częścią jest to, że po zalogowaniu klienta do swojego profilu, wykonuje on określony plik .bat, w którym jest napisane:

echo off
If exist %APPDATA%RadiantViewerpacs.xml copy %APPDATA%RadiantViewerpacs.xml srv.test.localpconfigs$pacs-%COMPUTERNAME%-%USERNAME%.xml

W ten sposób na serwerze w ukrytym zasobie będą gromadzić się pliki pacs.xml, w których nazwach znajduje się informacja, z jakiego komputera i od jakiego użytkownika został skopiowany dany konfiguracja.

Najtrudniejsze było - poczekać, aż ta polityka zadziała u wszystkich użytkowników.

Zmiana konfiguracji za pomocą skryptu Perl

Będziemy potrzebować Active Perl na systemy Windows od firmy ActiveState oraz moduł XML::Writer, który można zainstalować za pomocą polecenia ppm install XML-Writer.

Sam skrypt okazał się dość prosty:

use XML::Writer;
 
# Otwieramy folder z raportami, przetwarzamy listę (usuwamy zbędne elementy):
	$report_dir = "C:Perl64WORKPACS-xml3";
	opendir(DIR, "$report_dir") or die "Nie mogę otworzyć folderu z raportami!";
	@report_files = readdir DIR;
	shift (@report_files); # usuwamy kropkę z elementów tablicy (.)
	shift (@report_files); # usuwamy dwie kropki z elementów tablicy (..)
#	print "@report_files";
	closedir(DIR);
 
# Zaczynamy przetwarzanie plików - jeden po drugim. Musimy odczytać parametr AET i numer portu do zmiennych.
foreach $analiz_file (@report_files) 
{
	$full_path_to_file="C:Perl64WORKPACS-xml3".$analiz_file;
	open (INFO, $full_path_to_file);
 
	while ($line = )
	{
		# Zmienne $aet i $port zawierają unikalne dane dla każdego pliku XML:
		my ($other1, $aet, $other2, $port, $other3) = split /"/, $line, 5;
		# Jeśli napotkamy linię listener - dotarliśmy do potrzebnej linii i możemy formować nowy XML:
		if ($other1 =~ 'listener')
			{
				# Formujemy nowy XML z potrzebnymi polami i danymi:
				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');
 
				# Umieszczamy gotowy XML w zmiennej:
				my $xml = $writer->end();
				# Przygotowujemy plik do przepisania:
				$rewritexml = $full_path_to_file;
				# Przepisujemy pliki XML nowymi danymi:
				open (NEWXML, "> $rewritexml");
				print NEWXML $xml;
				close (NEWXML);				
			}
	}
 
}

Zasada jego działania:

  • Otwieramy katalog, w którym zebrane zostały konfiguracje pacs.xml od klientów, i umieszczamy listę plików w tablicy skalarów (@report_files);
  • W pętli przetwarzamy jeden plik na raz i odczytujemy go linia po linii;
  • Za pomocą split dzielimy każdą linię na 5 części, używając cudzysłowów jako separatorów;
  • Znajdujemy linię ze słowem listener i umieszczamy w dwóch zmiennych unikalne dla każdego pliku dane (AE-nazwa klienta i numer portu TCP);
  • Następnie po prostu formujemy nowy plik XML, wpisujemy w niego unikalne parametry i następnie wstawiamy potrzebną liczbę serwerów PACS z ich parametrami – to znaczy, powód, dla którego to wszystko zostało zrobione)
  • Przepisywujemy nowy plik XML na stary.

Należy zaznaczyć, że w rzeczywistości używam tego skryptu nie całkowicie automatycznie – w zasadzie kopiuję zbierane konfiguracje do osobnego katalogu, a następnie uruchamiając skrypt zmieniam je wszystkie jednocześnie. Następnie kontrola selektywna – i konfiguracje można z powrotem rozprowadzić po maszynach.

Dystrybucja zmienionych plików pacs.xml do klientów

Najprostsze, co przyszło na myśl – wprowadzenie zmian w już działającym pliku .bat, który zbiera konfiguracje z klientów i dodanie linii:

If exist %APPDATA%RadiantViewerpacs.xml copy /Y srv.test.localpconfigsnew$pacs-%COMPUTERNAME%-%USERNAME%.xml %APPDATA%RadiantViewerpacs.xml

Końcowy plik .bat wygląda tak:

@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

Podsumowanie

Takie oto „doraźne” rozwiązanie. Testowaliśmy to już dwa razy (we wrześniu 2018 i w lutym 2019), jak na razie wszystko działa prawidłowo. Oczywiście nie aktualizuje 100% klientów, ale blisko tej wartości – pozostałych uzbrajamy zdalnie. Skrypt w linkiem.

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster