ПишСм GUI к 1Б RAC, или снова о Tcl/Tk

По ΠΌΠ΅Ρ€Π΅ вникания Π² Ρ‚Π΅ΠΌΡƒ Ρ€Π°Π±ΠΎΡ‚Ρ‹ 1Π‘-овских ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚ΠΎΠ² Π² срСдС linux, обнаруТился ΠΎΠ΄ΠΈΠ½ нСдостаток β€” отсутствиС ΡƒΠ΄ΠΎΠ±Π½ΠΎΠ³ΠΎ графичСского ΠΌΡƒΠ»ΡŒΡ‚ΠΈΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΠ΅Π½Π½ΠΎΠ³ΠΎ инструмСнта для управлСния кластСром сСрвСров 1Π‘. И Ρ€Π΅ΡˆΠ΅Π½ΠΎ Π±Ρ‹Π»ΠΎ этот нСдостаток ΠΈΡΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ, ΠΏΡƒΡ‚Ρ‘ΠΌ написания GUI для консольной ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Ρ‹ rac. Π―Π·Ρ‹ΠΊΠΎΠΌ для Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π±Ρ‹Π» Π²Ρ‹Π±Ρ€Π°Π½ tcl/tk ΠΊΠ°ΠΊ, Π½Π° ΠΌΠΎΠΉ взгляд, Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ подходящий для этой Π·Π°Π΄Π°Ρ‡ΠΈ. И Π²ΠΎΡ‚, Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ интСрСсныС аспСкты Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ Ρ…ΠΎΡ‡Ρƒ ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²ΠΈΡ‚ΡŒ Π² Π΄Π°Π½Π½ΠΎΠΌ ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»Π΅.

Для Ρ€Π°Π±ΠΎΡ‚Ρ‹ понадобятся дистрибутивы tcl/tk ΠΈ 1Π‘. А Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ я Ρ€Π΅ΡˆΠΈΠ» максимально ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ возмоТности Π±Π°Π·ΠΎΠ²ΠΎΠΉ поставки tcl/tk Π±Π΅Π· примСнСния сторонних ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ², Ρ‚ΠΎ понадобится вСрсия 8.6.7, ΠΊΡƒΠ΄Π° Π²Ρ…ΠΎΠ΄ΠΈΡ‚ ttk β€” ΠΏΠ°ΠΊΠ΅Ρ‚ с Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌΠΈ графичСскими элСмСнтами, ΠΈΠ· ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Π½Π°ΠΌ потрСбуСтся, Π² основном, ttk::TreeView, ΠΎΠ½ позволяСт Π²Ρ‹Π²ΠΎΠ΄ΠΈΡ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅ ΠΊΠ°ΠΊ Π² Π²ΠΈΠ΄Π΅ Π΄Ρ€Π΅Π²ΠΎΠ²ΠΈΠ΄Π½ΠΎΠΉ структуры Ρ‚Π°ΠΊ ΠΈ Π² Π²ΠΈΠ΄Π΅ Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹ (списка). Π•Ρ‰Ρ‘, Π² Π½ΠΎΠ²ΠΎΠΉ вСрсии ΠΏΠ΅Ρ€Π΅Π΄Π΅Π»Π°Π½Π° Ρ€Π°Π±ΠΎΡ‚Π° с ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡΠΌΠΈ (ΠΊΠΎΠΌΠ°Π½Π΄Π° try, которая Π² ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΏΡ€ΠΈ запускС Π²Π½Π΅ΡˆΠ½ΠΈΡ… ΠΊΠΎΠΌΠ°Π½Π΄).

ΠŸΡ€ΠΎΠ΅ΠΊΡ‚ состоит ΠΈΠ· Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… Ρ„Π°ΠΉΠ»ΠΎΠ² (хотя Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ ΠΌΠ΅ΡˆΠ°Π΅Ρ‚ всё ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ ΠΎΠ΄Π½ΠΈΠΌ):

rac_gui.cfg β€” Π΄Π΅Ρ„ΠΎΠ»Ρ‚Π½Ρ‹ΠΉ ΠΊΠΎΠ½Ρ„ΠΈΠ³
rac_gui.tcl β€” основной скрипт запуска
Π’ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³Π΅ lib Π»Π΅ΠΆΠ°Ρ‚ Ρ„Π°ΠΉΠ»Ρ‹ автоматичСски Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌΡ‹Π΅ ΠΏΡ€ΠΈ стартС:
function.tcl β€” Ρ„Π°ΠΉΠ» с ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π°ΠΌΠΈ
gui.tcl β€” основной графичСский интСрфСйс
images.tcl β€” Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ Π² base64

Π€Π°ΠΉΠ» rac_gui.tcl, собствСнно, запускаСт ΠΈΠ½Ρ‚Π΅Ρ€ΠΏΡ€Π΅Ρ‚Π°Ρ‚ΠΎΡ€, ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅, Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅Ρ‚ ΠΌΠΎΠ΄ΡƒΠ»ΠΈ, ΠΊΠΎΠ½Ρ„ΠΈΠ³ΠΈ ΠΈ Ρ‚Π°ΠΊ Π΄Π°Π»Π΅Π΅. Π‘ΠΎΠ΄Π΅Ρ€ΠΆΠΈΠΌΠΎΠ΅ Ρ„Π°ΠΉΠ»Π° с коммСнтариями:

rac_gui.tcl

#!/bin/sh
exec wish "$0" -- "$@"

# УстанавливаСм Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³
set dir(root) [pwd]
# УстанавливаСм Ρ€Π°Π±ΠΎΡ‡ΠΈΠΉ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³, Ссли Π΅Π³ΠΎ Π½Π΅Ρ‚ Ρ‚ΠΎ создаём
set dir(work) [file join $env(HOME) .rac_gui]
if {[file exists $dir(work)] == 0 } {
    file mkdir $dir(work)    
}
# ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ с модулями
set dir(lib) "[file join $dir(root) lib]"

# Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΠΉ ΠΊΠΎΠ½Ρ„ΠΈΠ³, Ссли ΠΎΠ½ отсутствуСт, Ρ‚ΠΎ ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅ΠΌ Π΄Π΅Ρ„ΠΎΠ»Ρ‚Π½Ρ‹ΠΉ
if {[file exists [file join $dir(work) rac_gui.cfg]] ==0} {
    file copy [file join [pwd] rac_gui.cfg] [file join $dir(work) rac_gui.cfg]
} 
source [file join $dir(work) rac_gui.cfg]
# Код ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ наличия rac ΠΈ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΡΡ‚ΠΈ указания ΠΏΡƒΡ‚ΠΈ Π² ΠΊΠΎΠ½Ρ„ΠΈΠ³Π΅
# Ссли ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Π½Π΅ Π½Π°ΠΉΠ΄Π΅Π½Π° Ρ‚ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π²Π΅Π΄Π΅Π½ Π΄ΠΈΠ°Π»ΠΎΠ³ для указания ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΠ³ΠΎ ΠΏΡƒΡ‚ΠΈ
# ΠΈ этот ΠΏΡƒΡ‚ΡŒ Π±ΡƒΠ΄Π΅Ρ‚ записан Π² ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΠΉ ΠΊΠΎΠ½Ρ„ΠΈΠ³
if {[file exists $rac_cmd] == 0} {
    set rac_cmd [tk_getOpenFile -initialdir $env(HOME) -parent . -title "Π£ΠΊΠ°ΠΆΠΈΡ‚Π΅ ΠΏΡƒΡ‚ΡŒ Π΄ΠΎ rac" -initialfile rac]
    file copy [file join $dir(work) rac_gui.cfg] [file join $dir(work) rac_gui.cfg.bak] 
    set orig_file [open [file join $dir(work) rac_gui.cfg.bak] "r"]
    set file [open [file join $dir(work) rac_gui.cfg] "w"]
    while {[gets $orig_file line] >=0 } {
        if {[string match "set rac_cmd*" $line]} {
            puts $file "set rac_cmd $rac_cmd"
        } else {
            puts $file $line
        }
    }
    close $file
    close $orig_file
    #return "$host:$port"
    file delete [file join $dir(work) 1c_srv.cfg.bak] 
} else {
    puts "Found $rac_cmd"
}

set cluster_user ""
set cluster_pwd ""
set agent_user ""
set agent_pwd ""
## LOAD FILE ##
# Π—Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌ ΠΌΠΎΠ΄ΡƒΠ»ΠΈ ΠΊΡ€ΠΎΠΌΠ΅ gui.tcl Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ Π΅Π³ΠΎ Π½Π°Π΄ΠΎ Π·Π°Π³Ρ€ΡƒΠ·ΠΈΡ‚ΡŒ послСдним
foreach modFile [lsort [glob -nocomplain [file join $dir(lib) *.tcl]]] {
    if {[file tail $modFile] ne "gui.tcl"} {
        source $modFile
        puts "Loaded module $modFile"
    }
}
source [file join $dir(lib) gui.tcl]
source [file join $dir(work) rac_gui.cfg]

# Π§ΠΈΡ‚Π°Π΅ΠΌ Ρ„Π°ΠΉΠ» со списком сСрвСров 1Π‘
# ΠΈ добавляСм Π² Π΄Π΅Ρ€Π΅Π²ΠΎ
if [file exists [file join $dir(work) 1c_srv.cfg]] {
    set f [open [file join $dir(work) 1c_srv.cfg] "RDONLY"]
    while {[gets $f line] >=0} {
        .frm_tree.tree insert {} end -id "server::$line" -text "$line" -values "$line"
    }    
}

ПослС Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ всСго, Ρ‡Ρ‚ΠΎ трСбуСтся ΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ наличия ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Ρ‹ rac, Π±ΡƒΠ΄Π΅Ρ‚ Π·Π°ΠΏΡƒΡ‰Π΅Π½ΠΎ графичСскоС ΠΎΠΊΠ½ΠΎ. Π˜Π½Ρ‚Π΅Ρ€Ρ„Π΅ΠΉΡ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ состоит ΠΈΠ· Ρ‚Ρ€Ρ‘Ρ… элСмСнтов:

ПанСль инструмСнтов, Π΄Π΅Ρ€Π΅Π²ΠΎ ΠΈ список

Π‘ΠΎΠ΄Π΅Ρ€ΠΆΠΈΠΌΠΎΠ΅ Β«Π΄Π΅Ρ€Π΅Π²Π°Β» я сдСлал максимально ΠΏΠΎΡ…ΠΎΠΆΠΈΠΌ Π½Π° ΡˆΡ‚Π°Ρ‚Π½ΡƒΡŽ windows-оснастку ΠΎΡ‚ 1Π‘.

ПишСм GUI к 1Б RAC, или снова о Tcl/Tk

Основной ΠΊΠΎΠ΄ Ρ„ΠΎΡ€ΠΌΠΈΡ€ΡƒΡŽΡ‰ΠΈΠΉ Π΄Π°Π½Π½ΠΎΠ΅ ΠΎΠΊΠ½ΠΎ содСрТится Π² Ρ„Π°ΠΉΠ»Π΅
lib/gui.tcl

# установка Ρ€Π°Π·ΠΌΠ΅Ρ€Π° ΠΈ полоТСния основного ΠΎΠΊΠ½Π°
# ΠΌΠΎΠΆΠ½ΠΎ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ Π² ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ topLevelGeometry Π² ΠΊΠΎΠ½Ρ„ΠΈΠ³ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹
if {[info exists topLevelGeometry]} {
    wm geometry . $topLevelGeometry
} else {
    wm geometry . 1024x768
}
# Π—Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ ΠΎΠΊΠ½Π°
wm title . "1C Rac GUI"
wm iconname . "1C Rac Gui"
# ΠΈΠΊΠΎΠ½ΠΊΠ° ΠΎΠΊΠ½Π° (бСрСтся ΠΈΠ· Ρ„Π°ΠΉΠ»Π° lib/imges.tcl)
wm iconphoto . tcl
wm protocol . WM_DELETE_WINDOW Quit
wm overrideredirect . 0
wm positionfrom . user

ttk::style theme use clam

# ПанСль инсрумСнтов
set frm_tool [frame .frm_tool]
pack $frm_tool -side left -fill y 
ttk::panedwindow .panel -orient horizontal -style TPanedwindow
pack .panel -expand true -fill both
pack propagate .panel false

ttk::button $frm_tool.btn_add  -command Add  -image add_grey_32
ttk::button $frm_tool.btn_del  -command Del -image del_grey_32
ttk::button $frm_tool.btn_edit  -command Edit -image edit_grey_32
ttk::button $frm_tool.btn_quit -command Quit -image quit_grey_32

pack $frm_tool.btn_add $frm_tool.btn_del $frm_tool.btn_edit -side top -padx 5 -pady 5
pack $frm_tool.btn_quit  -side bottom -padx 5 -pady 5

# Π”Π΅Ρ€Π΅Π²ΠΎ с полосами ΠΏΡ€ΠΎΠΊΡ€ΡƒΡ‚ΠΊΠΈ
set frm_tree [frame .frm_tree]

ttk::scrollbar $frm_tree.hsb1 -orient horizontal -command [list $frm_tree.tree xview]
ttk::scrollbar $frm_tree.vsb1 -orient vertical -command [list $frm_tree.tree yview]
set tree [ttk::treeview $frm_tree.tree -show tree 
-xscrollcommand [list $frm_tree.hsb1 set] -yscrollcommand [list $frm_tree.vsb1 set]]

grid $tree -row 0 -column 0 -sticky nsew
grid $frm_tree.vsb1 -row 0 -column 1 -sticky nsew
grid $frm_tree.hsb1 -row 1 -column 0 -sticky nsew
grid columnconfigure $frm_tree 0 -weight 1
grid rowconfigure $frm_tree 0 -weight 1

# Π½Π°Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ° наТатия ΠΊΠ½ΠΎΠΏΠΊΠΎΠΉ ΠΌΡ‹ΡˆΠΈ
bind $frm_tree.tree <ButtonRelease> "TreePress $frm_tree.tree"

# Бписок для Π΄Π°Π½Π½Ρ‹Ρ… (Ρ‚Π°Π±Π»ΠΈΡ†Π°)
set frm_work [frame .frm_work]
ttk::scrollbar $frm_work.hsb -orient horizontal -command [list $frm_work.tree_work xview]
ttk::scrollbar $frm_work.vsb -orient vertical -command [list $frm_work.tree_work yview]
set tree_work [
    ttk::treeview $frm_work.tree_work 
    -show headings  -columns "par val" -displaycolumns "par val"
    -xscrollcommand [list $frm_work.hsb set] 
    -yscrollcommand [list $frm_work.vsb set]
]
# Установка Ρ†Π²Π΅Ρ‚ΠΎΠ² для чСрСдования Π² Ρ‚Π°Π±Π»ΠΈΡ†Π΅
$tree_work tag configure dark -background $color(dark_table_bg)
$tree_work tag configure light -background $color(light_table_bg)

# Π Π°Π·ΠΌΠ΅Ρ‰Π΅Π½ΠΈΠ΅ элСмСнтов Π½Π° Ρ„ΠΎΡ€ΠΌΠ΅
grid $tree_work -row 0 -column 0 -sticky nsew
grid $frm_work.vsb -row 0 -column 1 -sticky nsew
grid $frm_work.hsb -row 1 -column 0 -sticky nsew
grid columnconfigure $frm_work 0 -weight 1
grid rowconfigure $frm_work 0 -weight 1
pack $frm_tree $frm_work -side left -expand true -fill both

#.panel add $frm_tool -weight 1
.panel add $frm_tree -weight 1 
.panel add $frm_work -weight 1

Алгоритм Ρ€Π°Π±ΠΎΡ‚Ρ‹ с ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΎΠΉ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ:

1. Π’ Π½Π°Ρ‡Π°Π»Π΅, Π½Π°Π΄ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ основной сСрвСр кластСра (Ρ‚.Π΅. сСрвСр управлСния кластСром (Π² linux ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ запускаСтся ΠΊΠΎΠΌΠ°Π½Π΄ΠΎΠΉ «/opt/1C/v8.3/x86_64/ras cluster —daemon»)).

Для этого ΠΆΠΌΡ‘Ρ‚ Π½Π° ΠΊΠ½ΠΎΠΏΠΊΡƒ «+» ΠΈ Π² ΠΎΡ‚ΠΊΡ€Ρ‹Π²ΡˆΠ΅ΠΌΡΡ ΠΎΠΊΠ½Π΅, Π²Π²ΠΎΠ΄ΠΈΠΌ адрСс сСрвСра ΠΈ ΠΏΠΎΡ€Ρ‚:

ПишСм GUI к 1Б RAC, или снова о Tcl/Tk

ПослС, Π² Π΄Π΅Ρ€Π΅Π²Π΅ появится наш сСрвСр ΠΏΠΎ Ρ‰Π΅Π»Ρ‡ΠΊΡƒ Π½Π° ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ, откроСтся список кластСров Π»ΠΈΠ±ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π²Π΅Π΄Π΅Π½Π° ошибка соСдинСния.

2. Π©Π΅Π»ΠΊΠ½ΡƒΠ² Π½Π° имя кластСра откроСтся список Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ доступный для Π½Π΅Π³ΠΎ.

3.…

Ну ΠΈ Ρ‚Π°ΠΊ Π΄Π°Π»Π΅Π΅, Ρ‚.Π΅. Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Π½ΠΎΠ²Ρ‹ΠΉ кластСр, выдСляСм любой доступный Π² спискС ΠΈ Π½Π°ΠΆΠΈΠΌΠ°Π΅ΠΌ ΠΊΠ½ΠΎΠΏΠΊΡƒ «+» Π² ΠΏΠ°Π½Π΅Π»ΠΈ инструмСнтов ΠΈ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π²Π΅Π΄Π΅Π½ Π΄ΠΈΠ°Π»ΠΎΠ³ добавлСния Π½ΠΎΠ²ΠΎΠ³ΠΎ:

ПишСм GUI к 1Б RAC, или снова о Tcl/Tk

Кнопки Π² ΠΏΠ°Π½Π΅Π»ΠΈ инструмСнтов Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π² зависимости ΠΎΡ‚ контСкста, Ρ‚.Π΅. ΠΎΡ‚ Ρ‚ΠΎΠ³ΠΎ ΠΊΠ°ΠΊΠΎΠΉ элСмСнт Π΄Π΅Ρ€Π΅Π²Π° ΠΈΠ»ΠΈ списка Π²Ρ‹Π±Ρ€Π°Π½, Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π° Ρ‚Π° ΠΈΠ»ΠΈ иная ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π°.

Рассмотрим Π½Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ ΠΊΠ½ΠΎΠΏΠΊΠΈ добавлСния («+»):

Код формирования ΠΊΠ½ΠΎΠΏΠΊΠΈ:

ttk::button $frm_tool.btn_add  -command Add  -image add_grey_32

Π’ΡƒΡ‚ Π²ΠΈΠ΄ΠΈΠΌ, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΈ Π½Π°ΠΆΠ°Ρ‚ΠΈΠΈ ΠΊΠ½ΠΎΠΏΠΊΠΈ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π° ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π° Β«AddΒ», Π΅Ρ‘ ΠΊΠΎΠ΄:

proc Add {} {
    global active_cluster host
    # ΠžΠΏΡ€Π΅Π΄Π΅Π»ΡΠ΅ΠΌ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ Π²Ρ‹Π΄Π΅Π»Π΅Π½Π½ΠΎΠ³ΠΎ элСмСнта
    set id  [.frm_tree.tree selection] 
    # ΠžΠΏΡ€Π΅Π΄Π΅Π»ΡΠ΅ΠΌ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ этого элСмСнта
    set values [.frm_tree.tree item [.frm_tree.tree selection] -values]
    set key [lindex [split $id "::"] 0]
    # Π² зависимости ΠΎΡ‚ Ρ‚ΠΎΠ³ΠΎ Ρ‡Ρ‚ΠΎ Π²Ρ‹Π΄Π΅Π»ΠΈΠ»ΠΈ Π±ΡƒΠ΄Π΅Ρ‚ Π·Π°ΠΏΡƒΡ‰Π΅Π½Π° нуТная ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π°
    if {$key eq "" || $key eq "server"} {
        set host [ Add::server ]
        return
    }
    Add::$key .frm_tree.tree $host $values
}

Π’ΠΎΡ‚ ΠΈ проглядываСт ΠΎΠ΄ΠΈΠ½ ΠΈΠ· плюсов тикля β€” Π² качСствС ΠΈΠΌΠ΅Π½ΠΈ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρ‹ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ:

Add::$key .frm_tree.tree $host $values

Π’.Π΅., ΠΊ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρƒ, Ссли ΠΌΡ‹ Ρ‚ΠΊΠ½Ρ‘ΠΌ Π² основной сСрвСр ΠΈ Π½Π°ΠΆΠΌΡ‘ΠΌ «+» Ρ‚ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ Π·Π°ΠΏΡƒΡ‰Π΅Π½Π° ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π° Add::server, Ссли Π² кластСр β€” Add::cluster ΠΈ Ρ‚Π°ΠΊ Π΄Π°Π»Π΅Π΅ (ΠΎ Ρ‚ΠΎΠΌ ΠΎΡ‚ΠΊΡƒΠ΄Π° бСрутся Π½ΡƒΠΆΠ½Ρ‹Π΅ Β«ΠΊΠ»ΡŽΡ‡ΠΈΒ» Π½Π°ΠΏΠΈΡˆΡƒ Ρ‡ΡƒΡ‚ΡŒ Π½ΠΈΠΆΠ΅), пСрСчислСнныС ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρ‹ ΠΎΡ‚Ρ€ΠΈΡΠΎΠ²Ρ‹Π²Π°ΡŽΡ‚ графичСскиС элСмСнты ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ контСксту.

Как Π²Ρ‹ ΡƒΠΆΠ΅ ΠΌΠΎΠ³Π»ΠΈ Π·Π°ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ, Ρ„ΠΎΡ€ΠΌΡ‹ ΠΏΠΎΡ…ΠΎΠΆΠΈ ΠΏΠΎ ΡΡ‚ΠΈΠ»ΡŽ β€” это ΠΈ Π½Π΅ ΡƒΠ΄ΠΈΠ²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ, вСдь ΠΎΠ½ΠΈ выводятся ΠΎΠ΄Π½ΠΎΠΉ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€ΠΎΠΉ, Ρ‚ΠΎΡ‡Π½Π΅Π΅ основной каркас Ρ„ΠΎΡ€ΠΌΡ‹ (ΠΎΠΊΠ½ΠΎ, ΠΊΠ½ΠΎΠΏΠΊΠΈ, ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅, ΠΌΠ΅Ρ‚ΠΊΠ°), Π½Π°Π·Π²Π°Π½ΠΈΠ΅ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρ‹ AddTopLevel

proc AddToplevel {lbl img {win_name .add}} {
    set cmd "destroy $win_name"
    if [winfo exists $win_name] {destroy $win_name}
    toplevel $win_name
    wm title $win_name $lbl
    wm iconphoto $win_name tcl
    # ΠΌΠ΅Ρ‚ΠΊΠ° с ΠΈΠΊΠΎΠ½ΠΊΠΎΠΉ
    ttk::label $win_name.lbl -image $img
    # Ρ„Ρ€Π΅ΠΉΠΌ с полями Π²Π²ΠΎΠ΄Π°
    set frm [ttk::labelframe $win_name.frm -text $lbl -labelanchor nw]
    
    grid columnconfigure $frm 0 -weight 1
    grid rowconfigure $frm 0 -weight 1
    # Ρ„Ρ€Π΅ΠΉΠΌ ΠΈ ΠΊΠ½ΠΎΠΏΠΊΠΈ
    set frm_btn [frame $win_name.frm_btn -border 0]
    ttk::button $frm_btn.btn_ok -image ok_grey_24 -command { }
    ttk::button $frm_btn.btn_cancel -command $cmd -image quit_grey_24 
    grid $win_name.lbl -row 0 -column 0 -sticky nw -padx 5 -pady 10
    grid $frm -row 0 -column 1 -sticky nw -padx 5 -pady 5
    grid $frm_btn -row 1 -column 1 -sticky se -padx 5 -pady 5
    pack  $frm_btn.btn_cancel  -side right
    pack  $frm_btn.btn_ok  -side right -padx 10
    return $frm
}

ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ Π²Ρ‹Π·ΠΎΠ²Π°: Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ, Π½Π°Π·Π²Π°Π½ΠΈΠ΅ изобраТСния для ΠΈΠΊΠΎΠ½ΠΊΠΈ ΠΈΠ· Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ (lib/images.tcl) ΠΈ ΠΎΠΏΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½Ρ‹ΠΉ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ имя ΠΎΠΊΠ½Π° (ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ .add). Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, Ссли Π±Ρ€Π°Ρ‚ΡŒ Π²Ρ‹ΡˆΠ΅ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½Ρ‹Π΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ для добавлСния основного сСрвСра ΠΈ кластСра Ρ‚ΠΎ Π²Ρ‹Π·ΠΎΠ² Π±ΡƒΠ΄Π΅Ρ‚ соотвСтствСнно:

AddToplevel "Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ основного сСрвСра" server_grey_64

ΠΈΠ»ΠΈ

AddToplevel "Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ кластСра" cluster_grey_64

Ну ΠΈ ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠΈΠ² с этим ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°ΠΌΠΈ ΠΏΠΎΠΊΠ°ΠΆΡƒ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ выводят Π΄ΠΈΠ°Π»ΠΎΠ³ΠΈ добавлСния для сСрвСра ΠΈΠ»ΠΈ кластСра.

Add::server

proc Add::server {} {
    global default
    # Π²Ρ‹Π²ΠΎΠ΄ΠΈΠΌ ΠΎΡΠ½ΠΎΠ²Π½ΡƒΡŽ Ρ„ΠΎΡ€ΠΌΡƒ
    set frm [AddToplevel "Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ основного сСрвСра" server_grey_64]
    # добавляСм Π΅Ρ‚ΠΊΠΈ ΠΈ поля Π²Π²ΠΎΠ΄Π° Π½Π° эту Ρ„ΠΎΡ€ΠΌΡƒ
    label $frm.lbl_host -text "АдрСс сСрвСра"
    entry  $frm.ent_host
    label $frm.lbl_port -text "ΠŸΠΎΡ€Ρ‚"
    entry $frm.ent_port 
    $frm.ent_port  insert end $default(port)
    grid $frm.lbl_host -row 0 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_host -row 0 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_port -row 1 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_port -row 1 -column 1 -sticky nsew -padx 5 -pady 5
    grid columnconfigure $frm 0 -weight 1
    grid rowconfigure $frm 0 -weight 1
    #set frm_btn [frame .add.frm_btn -border 0]
    # пСрСопрСдСляСм ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ наТатия ΠΊΠ½ΠΎΠΏΠΊΠΈ
    .add.frm_btn.btn_ok configure -command {
        set host [SaveMainServer [.add.frm.ent_host get] [.add.frm.ent_port get]]
        .frm_tree.tree insert {} end -id "server::$host" -text "$host" -values "$host"
        destroy .add
        return $host
    }
    return $frm
}

Add::cluster

proc Add::cluster {tree host values} {
    global default lifetime_limit expiration_timeout session_fault_tolerance_level
    global max_memory_size max_memory_time_limit errors_count_threshold security_level
    global load_balancing_mode kill_problem_processes 
    agent_user agent_pwd cluster_user cluster_pwd auth_agent
    if {$agent_user ne "" && $agent_pwd ne ""} {
        set auth_agent "--agent-user=$agent_user --agent-pwd=$agent_pwd"
    } else {
        set auth_agent ""
    }
    # устанавливаСм Π³Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹Π΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ ()
    set lifetime_limit $default(lifetime_limit)
    set expiration_timeout $default(expiration_timeout)
    set session_fault_tolerance_level $default(session_fault_tolerance_level)
    set max_memory_size $default(max_memory_size)
    set max_memory_time_limit $default(max_memory_time_limit)
    set errors_count_threshold $default(errors_count_threshold)
    set security_level [lindex $default(security_level) 0]
    set load_balancing_mode [lindex $default(load_balancing_mode) 0]
    
    set frm [AddToplevel "Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ кластСра" cluster_grey_64]
    
    label $frm.lbl_host -text "АдрСс основного сСрвСра"
    entry  $frm.ent_host
    label $frm.lbl_port -text "ΠŸΠΎΡ€Ρ‚"
    entry $frm.ent_port 
    $frm.ent_port  insert end $default(port)
    label $frm.lbl_name -text "НазваниС кластСра"
    entry  $frm.ent_name
    label $frm.lbl_secure_connect -text "Π—Π°Ρ‰ΠΈΡ‰Ρ‘Π½Π½ΠΎΠ΅ соСдинСниС"
    ttk::combobox $frm.cb_security_level -textvariable security_level -values $default(security_level)
    label $frm.lbl_expiration_timeout -text "ΠžΡΡ‚Π°Π½Π°Π²Π»ΠΈΠ²Π°Ρ‚ΡŒ Π²Ρ‹ΠΊΠ»ΡŽΡ‡Π΅Π½Π½Ρ‹Π΅ процСссы Ρ‡Π΅Ρ€Π΅Π·:"
    entry  $frm.ent_expiration_timeout -textvariable expiration_timeout
    label $frm.lbl_session_fault_tolerance_level -text "Π£Ρ€ΠΎΠ²Π΅Π½ΡŒ отказоустойчивости"
    entry  $frm.ent_session_fault_tolerance_level -textvariable session_fault_tolerance_level
    label $frm.lbl_load_balancing_mode -text "Π Π΅ΠΆΠΈΠΌ распрСдСлСния Π½Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ"
    ttk::combobox $frm.cb_load_balancing_mode -textvariable load_balancing_mode 
    -values $default(load_balancing_mode)
    label $frm.lbl_errors_count_threshold -text "ДопустимоС ΠΎΡ‚ΠΊΠ»ΠΎΠ½Π΅Π½ΠΈΠ΅ количСства ошибок сСрвСра, %"
    entry  $frm.ent_errors_count_threshold -textvariable errors_count_threshold
    label $frm.lbl_processes -text "Π Π°Π±ΠΎΡ‡ΠΈΠ΅ процСссы:"
    label $frm.lbl_lifetime_limit -text "ΠŸΠ΅Ρ€ΠΈΠΎΠ΄ пСрСзапуска, сСк."
    entry  $frm.ent_lifetime_limit -textvariable lifetime_limit
    label $frm.lbl_max_memory_size -text "Допустимый ΠΎΠ±ΡŠΡ‘ΠΌ памяти, ΠšΠ‘"
    entry  $frm.ent_max_memory_size -textvariable max_memory_size
    label $frm.lbl_max_memory_time_limit -text "Π˜Π½Ρ‚Π΅Ρ€Π²Π°Π» ΠΏΡ€Π΅Π²Ρ‹ΡˆΠ΅Π½ΠΈΡ допустимого ΠΎΠ±ΡŠΡ‘ΠΌΠ° памяти, сСк."
    entry  $frm.ent_max_memory_time_limit -textvariable max_memory_time_limit
    label $frm.lbl_kill_problem_processes -justify left -anchor nw -text "ΠŸΡ€ΠΈΠ½ΡƒΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ½Ρ‹Π΅ процСссы"
    checkbutton $frm.check_kill_problem_processes -variable kill_problem_processes -onvalue yes -offvalue no    
    
    grid $frm.lbl_host -row 0 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_host -row 0 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_port -row 1 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_port -row 1 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_name -row 2 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_name -row 2 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_secure_connect -row 3 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.cb_security_level -row 3 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_expiration_timeout -row 4 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_expiration_timeout -row 4 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_session_fault_tolerance_level -row 5 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_session_fault_tolerance_level -row 5 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_load_balancing_mode -row 6 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.cb_load_balancing_mode -row 6 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_errors_count_threshold -row 7 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_errors_count_threshold -row 7 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_processes -row 8 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.lbl_lifetime_limit -row 9 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_lifetime_limit -row 9 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_max_memory_size -row 10 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_max_memory_size -row 10 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_max_memory_time_limit -row 11 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_max_memory_time_limit -row 11 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_kill_problem_processes -row 12 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.check_kill_problem_processes -row 12 -column 1 -sticky nw -padx 5 -pady 5
    # пСрСопрСдСляСм ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ
    .add.frm_btn.btn_ok configure -command {
        RunCommand "" "cluster insert 
        --host=[.add.frm.ent_host get] 
        --port=[.add.frm.ent_port get] 
        --name=[.add.frm.ent_name get] 
        --expiration-timeout=$expiration_timeout 
        --lifetime-limit=$lifetime_limit 
        --max-memory-size=$max_memory_size 
        --max-memory-time-limit=$max_memory_time_limit 
        --security-level=$security_level 
        --session-fault-tolerance-level=$session_fault_tolerance_level 
        --load-balancing-mode=$load_balancing_mode 
        --errors-count-threshold=$errors_count_threshold 
        --kill-problem-processes=$kill_problem_processes 
        $auth_agent $host"
        Run::server $tree $host ""
        destroy .add
    }
    return $frm
}

ΠŸΡ€ΠΈ сравнСнии ΠΊΠΎΠ΄Π° этих ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€, Ρ€Π°Π·Π½ΠΈΡ†Π° Π²ΠΈΠ΄Π½Π° Π½Π΅ Π²ΠΎΠΎΡ€ΡƒΠΆΠ΅Π½Π½Ρ‹ΠΌ Π³Π»Π°Π·ΠΎΠΌ, Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π·Π°ΠΎΡΡ‚Ρ€ΡŽ Π½Π° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ΅ ΠΊΠ½ΠΎΠΏΠΊΠΈ «Ок». Π’ Tk свойства графичСских элСмСнтов ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡ‚ΡŒ воврСмя выполнСния ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ ΠΎΠΏΡ†ΠΈΠΈ configure. К ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρƒ, ΠΏΠ΅Ρ€Π²ΠΎΠ½Π°Ρ‡Π°Π»ΡŒΠ½Π°Ρ ΠΊΠΎΠΌΠ°Π½Π΄Π° Π²Ρ‹Π²ΠΎΠ΄Π° ΠΊΠ½ΠΎΠΏΠΊΠΈ:

ttk::button $frm_btn.btn_ok -image ok_grey_24 -command { }

Но Π° Π² Π½Π°ΡˆΠΈΡ… Ρ„ΠΎΡ€ΠΌΠ°Ρ… ΠΊΠΎΠΌΠ°Π½Π΄Π° зависит ΠΎΡ‚ Ρ‚Ρ€Π΅Π±ΡƒΠ΅ΠΌΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ:

  .add.frm_btn.btn_ok configure -command {
        RunCommand "" "cluster insert 
        --host=[.add.frm.ent_host get] 
        --port=[.add.frm.ent_port get] 
        --name=[.add.frm.ent_name get] 
        --expiration-timeout=$expiration_timeout 
        --lifetime-limit=$lifetime_limit 
        --max-memory-size=$max_memory_size 
        --max-memory-time-limit=$max_memory_time_limit 
        --security-level=$security_level 
        --session-fault-tolerance-level=$session_fault_tolerance_level 
        --load-balancing-mode=$load_balancing_mode 
        --errors-count-threshold=$errors_count_threshold 
        --kill-problem-processes=$kill_problem_processes 
        $auth_agent $host"
        Run::server $tree $host ""
        destroy .add
    }

Π’ ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½ΠΎΠΌ Π²Ρ‹ΡˆΠ΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ Π½Π° ΠΊΠ½ΠΎΠΏΠΊΡƒ Β«Π·Π°Π±ΠΈΡ‚Β» запуск ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρ‹ добавлСния кластСра.

Π’ΡƒΡ‚ стоит ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ отступлСниС Π² сторону Ρ€Π°Π±ΠΎΡ‚Ρ‹ с графичСскими элСмСнтами Π² Tk β€” для Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… элСмСнтов Π²Π²ΠΎΠ΄Π° Π΄Π°Π½Π½Ρ‹Ρ… (entry, combobox, checkbutton ΠΈ Ρ‚.Π΄.) Π²Π²Π΅Π΄Ρ‘Π½ Ρ‚Π°ΠΊΠΎΠΉ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ ΠΊΠ°ΠΊ тСкстовая пСрСмСнная (textvariable):

entry  $frm.ent_lifetime_limit -textvariable lifetime_limit

ΠŸΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Π°Ρ эта ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π° Π² глобальном пространствС ΠΈΠΌΡ‘Π½ ΠΈ содСрТит Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ Π²Π²Π΅Π΄Ρ‘Π½Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅. Π’.Π΅. Π΄Π°Π±Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Π²Π²Π΅Π΄Ρ‘Π½Π½Ρ‹ΠΉ тСкст ΠΈΠ· поля Π½Π°Π΄ΠΎ просто ΡΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅ΠΉ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ (ΠΊΠΎΠ½Π΅Ρ‡Π½ΠΎ ΠΏΡ€ΠΈ условии, Ρ‡Ρ‚ΠΎ ΠΎΠ½Π° ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π° ΠΏΡ€ΠΈ создании элСмСнта).

Π’Ρ‚ΠΎΡ€ΠΎΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ получСния Π²Π²Π΅Π΄Ρ‘Π½Π½ΠΎΠ³ΠΎ тСкста (для элСмСнтов Ρ‚ΠΈΠΏΠ° entry) это использованиС ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ get:

.add.frm.ent_name get

Оба эти ΠΌΠ΅Ρ‚ΠΎΠ΄Π° ΠΌΠΎΠΆΠ½ΠΎ ΡƒΠ²ΠΈΠ΄Π΅Ρ‚ΡŒ Π² Π²Ρ‹ΡˆΠ΅ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½ΠΎΠΌ ΠΊΠΎΠ΄Π΅.

НаТатиС этой ΠΊΠ½ΠΎΠΏΠΊΠΈ, Π² Π΄Π°Π½Π½ΠΎΠΌ случаС, запускаСт ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρƒ RunCommand с сформированной строкой ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ добавлСния кластСра Π² Ρ‚Π΅Ρ€ΠΌΠΈΠ½Π°Ρ… rac:

/opt/1C/v8.3/x86_64/rac cluster insert  --host=localhost  --port=1540  --name=dsdsds  --expiration-timeout=0  --lifetime-limit=0  --max-memory-size=0  --max-memory-time-limit=0  --security-level=0  --session-fault-tolerance-level=0  --load-balancing-mode=performance  --errors-count-threshold=0  --kill-problem-processes=no   localhost:1545

Π’ΠΎΡ‚ ΠΈ подошли ΠΊ основной ΠΊΠΎΠΌΠ°Π½Π΄Π΅, которая ΠΈ управляСт запуском rac с Π½ΡƒΠΆΠ½Ρ‹ΠΌΠΈ Π½Π°ΠΌ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π°ΠΌΠΈ, Ρ‚Π°ΠΊΠΆΠ΅ Ρ€Π°Π·Π±ΠΈΡ€Π°Π΅Ρ‚ Π²Ρ‹Π²ΠΎΠ΄ ΠΊΠΎΠΌΠ°Π½Π΄ Π½Π° списки ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚, Ссли это трСбуСтся:

RunCommand

proc RunCommand {root par} {
    global dir rac_cmd cluster work_list_row_count agent_user agent_pwd cluster_user cluster_pwd
    puts "$rac_cmd $par"
    set work_list_row_count 0
    # ΠΎΡ‚ΠΊΡ€Ρ‹Π²Π°Π΅ΠΌ ΠΊΠ°Π½Π°Π» Π² Π½Π΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΡŽΡ‰Π΅ΠΌ Ρ€Π΅ΠΆΠΈΠΌΠ΅
    # $rac - ΠΊΠΎΠΌΠ°Π½Π΄Π° с ΠΏΠΎΠ»Π½Ρ‹ΠΌ ΠΏΡƒΡ‚Ρ‘ΠΌ
    # $par - сформированныС ΠΊΠ»ΡŽΡ‡ΠΈ запуска ΠΈ ΠΎΠΏΡ†ΠΈΠΈ    
    set pipe [open "|$rac_cmd $par" "r"]
    try {
        set lst ""
        set l ""
        # Π²Ρ‹Π²ΠΎΠ΄ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ добавляСм Π² список списков
        while {[gets $pipe line]>=0} {
            #puts $line
            if {$line eq ""} {
                lappend l $lst
                set lst ""
            } else {
                lappend lst [string trim $line]
            }
        }
        close $pipe
        return $l
    } on error {result options} {
        # Запуск ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ° ошибок
        ErrorParcing $result $options
        return ""
    }
}

ПослС Π²Π²ΠΎΠ΄Π° Π΄Π°Π½Π½Ρ‹Ρ… основного сСрвСра ΠΎΠ½ Π±ΡƒΠ΄Π΅Ρ‚ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ Π² Π΄Π΅Ρ€Π΅Π²ΠΎ, Π·Π° это, Π² Π²Ρ‹ΡˆΠ΅ ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½ΠΎΠΉ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π΅ Add:server, ΠΎΡ‚Π²Π΅Ρ‡Π°Π΅Ρ‚ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ ΠΊΠΎΠ΄:

.frm_tree.tree insert {} end -id "server::$host" -text "$host" -values "$host"

Π’Π΅ΠΏΠ΅Ρ€ΡŒ Ρ‰Π΅Π»ΠΊΠ½ΡƒΠ² ΠΏΠΎ ΠΈΠΌΠ΅Π½ΠΈ сСрвСра Π² Π΄Π΅Ρ€Π΅Π²Π΅, ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ список кластСров управляСмых ΠΎΠ½Ρ‹ΠΌ сСрвСром, Π° Ρ‰Π΅Π»ΠΊΠ½ΡƒΠ² Π½Π° кластСрС, ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ список элСмСнтов кластСра (сСрвСров, ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΎΠ½Π½Ρ‹Ρ… Π±Π°Π· ΠΈ Ρ‚.Π΄.). Π Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½ΠΎ это Π² ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π΅ TreePress (Ρ„Π°ΠΉΠ» lib/function.tcl):

proc TreePress {tree} {
   global host server active_cluster infobase
   # опрСдСляСм Π²Ρ‹Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΉ элСмСнт
    set id  [$tree selection]
   # устанавливаСм Π½ΡƒΠΆΠ½Ρ‹Π΅ Π³Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹Π΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅
    SetGlobalVarFromTreeItems $tree $id
   # ΠžΠΏΡ€Π΅Π΄Π΅Π»ΡΠ΅ΠΌ ΠΊΠ»ΡŽΡ‡ ΠΈ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, Ρ‚.Π΅. ΠΈΠΌΠ΅Π½Π½ΠΎ Ρ‚ΠΈΠΏ Π²Ρ‹Π±Ρ€Π°Π½Π½ΠΎΠ³ΠΎ элСмСнта
    set values [$tree item $id -values]
    set key [lindex [split $id "::"] 0]
   # ΠΈ Π² зависимости ΠΎΡ‚ Ρ‚ΠΎΠ³ΠΎ Ρ‡Ρ‚ΠΎ Π²Ρ‹Π±Ρ€Π°Π»ΠΈ Π±ΡƒΠ΄Π΅Ρ‚ Π·Π°ΠΏΡƒΡ‰Π΅Π½Π° ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π°Ρ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π° 
   # Π² пространствС ΠΈΠΌΡ‘Π½ Run
    Run::$key $tree $host $values
}

БоотвСтствСнно, для основного сСрвСра запустится Run::server (для кластСра β€” Run::cluster, для Ρ€Π°Π±ΠΎΡ‡Π΅Π³ΠΎ сСрвСра β€” Run::work_server ΠΈ Ρ‚.Π΄.). Π’.Π΅. Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ $key это Ρ‡Π°ΡΡ‚ΡŒ ΠΈΠΌΠ΅Π½ΠΈ элСмСнта Π΄Π΅Ρ€Π΅Π²Π°, Π·Π°Π΄Π°Π²Π°Π΅ΠΌΠΎΠ³ΠΎ ΠΎΠΏΡ†ΠΈΠ΅ΠΉ -id.

ΠžΠ±Ρ€Π°Ρ‚ΠΈΠΌ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρƒ

Run::server

proc Run::server {tree host values} {
    # ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ список кластСров Ρ‚Ρ€Π΅Π±ΡƒΠ΅ΠΌΠΎΠ³ΠΎ сСрвСра
    set lst [RunCommand server::$host "cluster list $host"]
    if {$lst eq ""} {return}
    set l [lindex $lst 0]
    #puts $lst
    # удаляСм лишнСС ΠΈΠ· списка
    .frm_work.tree_work delete  [ .frm_work.tree_work children {}]
    # Ρ‡ΠΈΡ‚Π°Π΅ΠΌ список
    foreach cluster_list $lst {
        # ЗаполняСм список ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½Ρ‹ΠΌΠΈ значСниями
        InsertItemsWorkList $cluster_list
        # ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅ΠΌ Π²Ρ‹Π²ΠΎΠ΄ (список) для добавлСния Π΄Π°Π½Π½Ρ‹Ρ… Π² Π΄Π΅Ρ€Π΅Π²ΠΎ
        foreach i $cluster_list {
            #puts $i
            set cluster_list [split $i ":"]
            if  {[string trim [lindex $cluster_list 0]] eq "cluster"} {
                set cluster_id [string trim [lindex $cluster_list 1]]
                lappend cluster($cluster_id) $cluster_id
            }
            if  {[string trim [lindex $cluster_list 0]] eq "name"} {
                lappend  cluster($cluster_id) [string trim [lindex $cluster_list 1]]
            }
        }
    }
    # добавляСм кластСры Π² Π΄Π΅Ρ€Π΅Π²ΠΎ
    foreach x [array names cluster] {
        set id [lindex $cluster($x) 0]
        if { [$tree exists "cluster::$id"] == 0 } {
            $tree insert "server::$host" end -id "cluster::$id" -text "[lindex $cluster($x) 1]" -values "$id"
            # добавляСм элСмСнты Π² кластСр
            InsertClusterItems $tree $id
        }
    }
    if { [$tree exists "agent_admins::$id"] == 0 } {
        $tree insert "server::$host" end -id "agent_admins::$id" -text "Администраторы" -values "$id"
        #InsertClusterItems $tree $id
    }
}

Данная ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π° ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ Π±Ρ‹Π»ΠΎ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΎ ΠΎΡ‚ сСрвСра Ρ‡Π΅Ρ€Π΅Π· ΠΊΠΎΠΌΠ°Π½Π΄Ρƒ RunCommand, ΠΈ добавляСт всякоС-Ρ€Π°Π·Π½ΠΎΠ΅ Π² Π΄Π΅Ρ€Π΅Π²ΠΎ β€” кластСры, Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Π΅ ΠΊΠΎΡ€Π½Π΅Π²Ρ‹Π΅ элСмСнты (Π±Π°Π·Ρ‹, Ρ€Π°Π±ΠΎΡ‡ΠΈΠ΅ сСрвСры, сСансы ΠΈ Ρ‚Π°ΠΊ Π΄Π°Π»Π΅Π΅). Если ΠΏΡ€ΠΈΠ³Π»ΡΠ΄Π΅Ρ‚ΡŒΡΡ, Ρ‚ΠΎ Π²Π½ΡƒΡ‚Ρ€ΠΈ ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ Π²Ρ‹Π·ΠΎΠ² ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρ‹ InsertItemsWorkList. Она ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для добавлСния элСмСнтов Π² графичСский список, обрабатывая Π²Ρ‹Π²ΠΎΠ΄ консольной ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Ρ‹ rac, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Ρ€Π°Π½Π΅Π΅ Π±Ρ‹Π» Π² Π²ΠΈΠ΄Π΅ списка Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π΅Π½ Π² ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ $lst. Π­Ρ‚ΠΎ список списков, содСрТащий ΠΏΠ°Ρ€Ρ‹ элСмСнтов Ρ€Π°Π·Π΄Π΅Π»Ρ‘Π½Π½Ρ‹Π΅ Π΄Π²ΠΎΠ΅Ρ‚ΠΎΡ‡ΠΈΠ΅ΠΌ.

НапримСр, список соСдинСний кластСра:

svk@svk ~]$ /opt/1C/v8.3/x86_64/rac connection list --cluster=783d2170-56c3-11e8-c586-fc75165efbb2 localhost:1545
connection     : dcf5991c-7d24-11e8-1690-fc75165efbb2
conn-id        : 0
host           : svk.home
process        : 79de2e16-56c3-11e8-c586-fc75165efbb2
infobase       : 00000000-0000-0000-0000-000000000000
application    : "JobScheduler"
connected-at   : 2018-07-01T14:49:51
session-number : 0
blocked-by-ls  : 0

connection     : b993293a-7d24-11e8-1690-fc75165efbb2
conn-id        : 0
host           : svk.home
process        : 79de2e16-56c3-11e8-c586-fc75165efbb2
infobase       : 00000000-0000-0000-0000-000000000000
application    : "JobScheduler"
connected-at   : 2018-07-01T14:48:52
session-number : 0
blocked-by-ls  : 0

Π’ графичСском Π²ΠΈΠ΄Π΅ это Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π³Π»ΡΠ΄Π΅Ρ‚ΡŒ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π½ΠΎ Ρ‚Π°ΠΊ:

ПишСм GUI к 1Б RAC, или снова о Tcl/Tk

Π’Ρ‹ΡˆΠ΅ΠΎΠ·Π½Π°Ρ‡Π΅Π½Π½Π°Ρ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π° выдСляСт наимСнования элСмСнтов для Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° ΠΈ Π΄Π°Π½Π½Ρ‹Π΅ для заполнСния Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹:

InsertItemsWorkList

proc InsertItemsWorkList {lst} {
    global work_list_row_count
    # установка чСрСдования Ρ†Π²Π΅Ρ‚Π° для строки
    if [expr $work_list_row_count % 2] {
        set tag dark
    } else {
        set tag light
    }
    # Ρ€Π°Π·Π±ΠΎΡ€ строк Π½Π° ΠΏΠ°Ρ€Ρ‹ ΠΊΠ»ΡŽΡ‡ - Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅
    foreach i $lst {
        if [regexp -nocase -all -- {(D+)(s*?|)(:)(s*?|)(.*)} $i match param v2 v3 v4 value] {
            lappend column_list [string trim $param]
            lappend value_list [string trim $value]
        }
    }
     # Π·Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹
    .frm_work.tree_work configure -columns $column_list -displaycolumns $column_list
    .frm_work.tree_work insert {} end  -values $value_list -tags $tag
    .frm_work.tree_work column #0 -stretch
    # установка Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΎΠ²
    foreach j $column_list {
        .frm_work.tree_work heading $j -text $j
    }
    incr work_list_row_count
}

Π’ΡƒΡ‚ вмСсто простой ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ [split $str «:»], которая Ρ€Π°Π·Π±ΠΈΠ²Π°Π΅Ρ‚ строку Π½Π° элСмСнты Ρ€Π°Π·Π΄Π΅Π»Π΅Π½Π½Ρ‹Π΅ «:» ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ список, ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΎ рСгулярноС Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ элСмСнты Ρ‚Π°ΠΊΠΆΠ΅ содСрТат Π΄Π²ΠΎΠ΅Ρ‚ΠΎΡ‡ΠΈΠ΅.

ΠŸΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π° InsertClusterItems (ΠΎΠ΄Π½Π° ΠΈΠ· Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… ΠΏΠΎΠ΄ΠΎΠ±Π½Ρ‹Ρ…) просто добавляСт Π² Π΄Π΅Ρ€Π΅Π²ΠΎ ΠΊ Ρ‚Ρ€Π΅Π±ΡƒΠ΅ΠΌΠΎΠΌΡƒ элСмСнту cluster список Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΡ… элСмСнтов с ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΌΠΈ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€Π°ΠΌΠΈ
InsertClusterItems

proc InsertClusterItems {tree id} {
    set parent "cluster::$id"
    $tree insert $parent end -id "infobases::$id" -text "Π˜Π½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΎΠ½Π½Ρ‹Π΅ Π±Π°Π·Ρ‹" -values "$id"
    $tree insert $parent end -id "servers::$id" -text "Π Π°Π±ΠΎΡ‡ΠΈΠ΅ сСрвСры" -values "$id"
    $tree insert $parent end -id "admins::$id" -text "Администраторы" -values "$id"
    $tree insert $parent end -id "managers::$id" -text "ΠœΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Ρ‹ кластСра" -values $id
    $tree insert $parent end -id "processes::$id" -text "Π Π°Π±ΠΎΡ‡ΠΈΠ΅ процСссы" -values "workprocess-all"
    $tree insert $parent end -id "sessions::$id" -text "БСансы" -values "sessions-all"
    $tree insert $parent end -id "locks::$id" -text "Π‘Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ" -values "blocks-all"
    $tree insert $parent end -id "connections::$id" -text "БоСдинСния" -values "connections-all"
    $tree insert $parent end -id "profiles::$id" -text "ΠŸΡ€ΠΎΡ„ΠΈΠ»ΠΈ бСзопасности" -values $id
}

МоТно Ρ€Π°ΡΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Π΅Ρ‰Ρ‘ Π΄Π²Π° Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π° Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΎΠΉ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρ‹, Π³Π΄Π΅ Π±ΡƒΠ΄Π΅Ρ‚ наглядно Π²ΠΈΠ΄Π½ΠΎ ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈ ΠΈΠ·Π±Π°Π²ΠΈΡ‚ΡŒΡΡ ΠΎΡ‚ ΠΏΠΎΠ²Ρ‚ΠΎΡ€ΡΡŽΡ‰ΠΈΡ…ΡΡ ΠΊΠΎΠΌΠ°Π½Π΄:

Π’ Π΄Π°Π½Π½ΠΎΠΉ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π΅ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Ρ€Π΅ΡˆΠ΅Π½Ρ‹ Π² Π»ΠΎΠ±:

InsertBaseItems

proc InsertBaseItems {tree id} {
    set parent "infobase::$id"
    if { [$tree exists "sessions::$id"] == 0 } {
        $tree insert $parent end -id "sessions::$id" -text "БСансы" -values "$id"
    }
    if { [$tree exists "locks::$id"] == 0 } {
        $tree insert $parent end -id "locks::$id" -text "Π‘Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ" -values "$id"
    }
    if { [$tree exists "connections::$id"] == 0 } {
        $tree insert $parent end -id "connections::$id" -text "БоСдинСния" -values "$id"
    }
}

А Ρ‚ΡƒΡ‚ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ Π±ΠΎΠ»Π΅Π΅ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Ρ‹ΠΉ:

InsertProfileItems

proc InsertProfileItems {tree id} {
    set parent "profile::$id"
    set lst {
        {dir "Π’ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹Π΅ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ΠΈ"}
        {com "Π Π°Π·Ρ€Π΅ΡˆΡ‘Π½Π½Ρ‹Π΅ COM-классы"}
        {addin "Π’Π½Π΅ΡˆΠ½ΠΈΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹"}
        {module "Π’Π½Π΅ΡˆΠ½ΠΈΠ΅ ΠΎΡ‚Ρ‡Ρ‘Ρ‚Ρ‹ ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ"}
        {app "Π Π°Π·Ρ€Π΅ΡˆΡ‘Π½Π½Ρ‹Π΅ прилоТСния"}
        {inet "РСсурсы ΠΈΠ½Ρ‚Π΅Ρ€Π½Π΅Ρ‚"}
    }
    foreach i $lst {
        append item [lindex $i 0] "::$id"
        if { [$tree exists $item] == 0 } {
            $tree insert $parent end -id $item -text [lindex $i 1] -values "$id"
        }
        unset item 
    }
}

Π Π°Π·Π½ΠΈΡ†Π° ΠΌΠ΅ΠΆΠ΄Ρƒ Π½ΠΈΠΌΠΈ Π² ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠΈ Ρ†ΠΈΠΊΠ»Π°, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ ΠΈ выполняСтся ΠΏΠΎΠ²Ρ‚ΠΎΡ€ΡΡŽΡ‰Π°ΡΡΡ ΠΊΠΎΠΌΠ°Π½Π΄Π° (ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹). Какой ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡ‚ΡŒ β€” это ΡƒΠΆΠ΅ Π½Π° усмотрСниС Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ°.

Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ элСмСнтов ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ Π΄Π°Π½Π½Ρ‹Ρ… ΠΌΡ‹ рассмотрСли, самоС врСмя ΠΎΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒΡΡ Π½Π° Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠΈ. Π’Π°ΠΊ ΠΊΠ°ΠΊ, Π² основном, для рСдактирования ΠΈ добавлСния ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ ΠΎΠ΄Π½ΠΈ ΠΈ Ρ‚Π΅ ΠΆΠ΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ (ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ составляСт информационная Π±Π°Π·Π°) Ρ‚ΠΎ ΠΈ Π΄ΠΈΠ°Π»ΠΎΠ³ΠΎΠ²Ρ‹Π΅ Ρ„ΠΎΡ€ΠΌΡ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹Π΅. Алгоритм Π²Ρ‹Π·ΠΎΠ²Π° ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€ для добавлСния выглядит Ρ‚Π°ΠΊ:

Add::$key->AddToplevel

А для рСдактирования Ρ‚Π°ΠΊ:

Edit::$key->Add::$key->AddTopLevel

Для ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° Π²ΠΎΠ·ΡŒΠΌΡ‘ΠΌ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ кластСра, Ρ‚.Π΅. Ρ‰Π΅Π»ΠΊΠ½ΡƒΠ² Π² Π΄Π΅Ρ€Π΅Π²Π΅ Π½Π° Π½Π°Π·Π²Π°Π½ΠΈΠΈ кластСра, Π½Π°ΠΆΠΈΠΌΠ°Π΅ΠΌ ΠΊΠ½ΠΎΠΏΠΊΡƒ рСдактирования Π² ΠΏΠ°Π½Π΅Π»ΠΈ инструмСнтов (ΠΊΠ°Ρ€Π°Π½Π΄Π°ΡˆΠΈΠΊ) ΠΈ Π½Π° экран Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π²Π΅Π΄Π΅Π½Π° ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π°Ρ Ρ„ΠΎΡ€ΠΌΠ°:

ПишСм GUI к 1Б RAC, или снова о Tcl/Tk
Edit::cluster

proc Edit::cluster {tree host values} {
    global default lifetime_limit expiration_timeout session_fault_tolerance_level
    global max_memory_size max_memory_time_limit errors_count_threshold security_level
    global load_balancing_mode kill_problem_processes active_cluster 
    agent_user agent_pwd cluster_user cluster_pwd auth
    if {$cluster_user ne "" && $cluster_pwd ne ""} {
        set auth "--cluster-user=$cluster_user --cluster-pwd=$cluster_pwd"
    } else {
        set auth ""
    }
    # рисуСм Ρ„ΠΎΡ€ΠΌΡƒ для кластСра
    set frm [Add::cluster $tree $host $values]
    # мСняСм тСкст Π½Π° ΠΌΠ΅Ρ‚ΠΊΠ΅
    $frm configure -text "Π Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ кластСра"
    
    set active_cluster $values
    # ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ Π΄Π°Π½Π½Ρ‹Π΅ ΠΏΠΎ Π²Ρ‹Π΄Π΅Π»Π΅Π½Π½ΠΎΠΌΡƒ кластСру
    set lst [RunCommand cluster::$values "cluster info --cluster=$active_cluster $host"]
    # заполняСм поля
    FormFieldsDataInsert $frm $lst
    # Π²Ρ‹ΠΊΠ»ΡŽΡ‡Π°Π΅ΠΌ поля, Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Π·Π°ΠΏΡ€Π΅Ρ‰Π΅Π½ΠΎ
    $frm.ent_host configure -state disable
    $frm.ent_port configure -state disable
    # ΠΏΠ΅Ρ€Π΅Π½Π°Π·Π½Π°Ρ‡Π°Π΅ΠΌ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ
    .add.frm_btn.btn_ok configure -command {
        RunCommand "" "cluster update 
        --cluster=$active_cluster $auth 
        --name=[.add.frm.ent_name get] 
        --expiration-timeout=$expiration_timeout 
        --lifetime-limit=$lifetime_limit 
        --max-memory-size=$max_memory_size 
        --max-memory-time-limit=$max_memory_time_limit 
        --security-level=$security_level 
        --session-fault-tolerance-level=$session_fault_tolerance_level 
        --load-balancing-mode=$load_balancing_mode 
        --errors-count-threshold=$errors_count_threshold 
        --kill-problem-processes=$kill_problem_processes 
        $auth $host"
        $tree delete "cluster::$active_cluster"
        Run::server $tree $host ""
        destroy .add
    }
}

По коммСнтариям Π² ΠΊΠΎΠ΄Π΅, Π² ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠ΅, всё понятно, ΠΊΡ€ΠΎΠΌΠ΅ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ ΠΊΠΎΠ΄ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ° ΠΊΠ½ΠΎΠΏΠΊΠΈ ΠΏΠ΅Ρ€Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»Ρ‘Π½ ΠΈ присутствуСт ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π° FormFieldsDataInsert, которая заполняСт поля Π΄Π°Π½Π½Ρ‹ΠΌΠΈ ΠΈ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅:

FormFieldsDataInsert

proc FormFieldsDataInsert {frm lst} {
    foreach i [lindex $lst 0] {
        # ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ список ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² ΠΈ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ
        if [regexp -nocase -all -- {(D+)(s*?|)(:)(s*?|)(.*)} $i match param v2 v3 v4 value] {
            # мСняСм символы
            regsub -all -- "-" [string trim $param] "_" entry_name
            # заполняСм Π΄Π°Π½Π½Ρ‹ΠΌΠΈ
            if [winfo exists $frm.ent_$entry_name] {
                $frm.ent_$entry_name delete 0 end
                $frm.ent_$entry_name insert end [string trim $value """]
            }
            if [winfo exists $frm.cb_$entry_name] {
                global $entry_name
                set $entry_name [string trim $value """]
            }
            # для чСкбоксов мСняСм значСния
            if [winfo exists $frm.check_$entry_name] {
                global $entry_name
                if {$value eq "0"} {
                    set $entry_name no
                } elseif {$value eq "1"} {
                    set $entry_name yes
                } else {
                    set $entry_name $value
                }
            }
        }
    }
}

Π’ Π΄Π°Π½Π½ΠΎΠΉ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π΅ всплыл Π΅Ρ‰Π΅ ΠΎΠ΄ΠΈΠ½ плюс tcl β€” Π² качСствС ΠΈΠΌΡ‘Π½ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… ΠΏΠΎΠ΄ΡΡ‚Π°Π²Π»ΡΡŽΡ‚ΡΡ значСния Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ…. Π’.Π΅. для Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΠ·Π°Ρ†ΠΈΠΈ заполнСния Ρ„ΠΎΡ€ΠΌ ΠΈ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… наимСнования ΠΏΠΎΠ»Π΅ΠΉ ΠΈ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ…, ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‚ ΠΊΠ»ΡŽΡ‡Π°ΠΌ ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ строки ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Ρ‹ rac ΠΈ наимСнованиям ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² Π²Ρ‹Π²ΠΎΠ΄Π° ΠΊΠΎΠΌΠ°Π½Π΄ с Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ΠΌ β€” Ρ‚ΠΈΡ€Π΅ Π·Π°ΠΌΠ΅Π½Π΅Π½ΠΎ Π½Π° ΠΏΠΎΠ΄Ρ‡Π΅Ρ€ΠΊ. К ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρƒ scheduled-jobs-deny соотвСтствуСт полю ent_scheduled_jobs_deny ΠΈ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ scheduled_jobs_deny.

Π€ΠΎΡ€ΠΌΡ‹ добавлСния ΠΈ рСдактирования ΠΌΠΎΠ³ΡƒΡ‚ ΠΎΡ‚Π»ΠΈΡ‡Π°Ρ‚ΡŒΡΡ составом ΠΏΠΎΠ»Π΅ΠΉ, ΠΊ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρƒ, Ρ€Π°Π±ΠΎΡ‚Π° с ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΎΠ½Π½ΠΎΠΉ Π±Π°Π·ΠΎΠΉ:

Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π˜Π‘

ПишСм GUI к 1Б RAC, или снова о Tcl/Tk

Π Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π˜Π‘

ПишСм GUI к 1Б RAC, или снова о Tcl/Tk

Π’ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π΅ рСдактирования Edit::infobase Π½Π° Ρ„ΠΎΡ€ΠΌΡƒ Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‚ΡΡ Ρ‚Ρ€Π΅Π±ΡƒΠ΅ΠΌΡ‹Π΅ поля, ΠΊΠΎΠ΄ ΠΎΠ±ΡŠΡ‘ΠΌΠ½Ρ‹ΠΉ посСму Ρ‚ΡƒΡ‚ Π½Π΅ ΠΏΡ€ΠΈΠ²ΠΎΠΆΡƒ.

По Π°Π½Π°Π»ΠΎΠ³ΠΈΠΈ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Ρ‹ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρ‹ добавлСния, рСдактирования, удалСния ΠΈ для ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Ρ… элСмСнтов.

Π’Π°ΠΊ ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚Π° ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Ρ‹ ΠΏΠΎΠ΄Ρ€Π°Π·ΡƒΠΌΠ΅Π²Π°Π΅Ρ‚ Π½Π΅ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½Π½ΠΎΠ΅ количСство сСрвСров, кластСров, ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΎΠ½Π½Ρ‹Ρ… Π±Π°Π· ΠΈ Ρ‚.ΠΏ., Ρ‚ΠΎ для опрСдСлСния ΠΊ ΠΊΠ°ΠΊΠΎΠΌΡƒ кластСру относится ΠΊΠ°ΠΊΠΎΠΉ сСрвСр ΠΈΠ»ΠΈ Π˜Π‘, Π²Π²Π΅Π΄Π΅Π½Ρ‹ нСсколько Π³Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹Ρ… ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ…, значСния ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ΡƒΡΡ‚Π°Π½Π°Π²Π»ΠΈΠ²Π°ΡŽΡ‚ΡΡ ΠΏΡ€ΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΌ Ρ‰Π΅Π»Ρ‡ΠΊΠ΅ ΠΏΠΎ элСмСнтам Π΄Π΅Ρ€Π΅Π²Π°. Π’.Π΅. ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π° рСкурсивно ΠΏΡ€ΠΎΠ±Π΅Π³Π°Π΅Ρ‚ ΠΏΠΎ всСм Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΈΠΌ элСмСнтам ΠΈ выставляСт ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅:

SetGlobalVarFromTreeItems

proc SetGlobalVarFromTreeItems {tree id} {
    global host server active_cluster infobase
    set parent [$tree parent $id]
    set values [$tree item $id -values]
    set key [lindex [split $id "::"] 0]
    switch -- $key {
        server {set host $values}
        work_server {set server $values}
        cluster {set active_cluster $values}
        infobase {set infobase $values}
    }
    if {$parent eq ""} {
        return
    } else {
        SetGlobalVarFromTreeItems $tree $parent
    }
}

ΠšΠ»Π°ΡΡ‚Π΅Ρ€ 1Π‘ позволяСт Ρ€Π°Π±ΠΎΡ‚Ρƒ ΠΊΠ°ΠΊ с Π°Π²Ρ‚ΠΎΡ€ΠΈΠ·Π°Ρ†ΠΈΠ΅ΠΉ Ρ‚Π°ΠΊ ΠΈ Π±Π΅Π·. БущСствуСт Π΄Π²Π° Π²ΠΈΠ΄Π° администраторов β€” администратор Π°Π³Π΅Π½Ρ‚Π° кластСра ΠΈ администратор кластСра. БоотвСтствСнно для ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΠΉ Ρ€Π°Π±ΠΎΡ‚Ρ‹ Π²Π²Π΅Π΄Π΅Π½Ρ‹ Π΅Ρ‰Ρ‘ 4 Π³Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹Ρ… ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ…, содСрТащих Π»ΠΎΠ³ΠΈΠ½ ΠΈ ΠΏΠ°Ρ€ΠΎΠ»ΡŒ администратора. Π’.Π΅. Ссли Π² кластСрС присутствуСт учётная запись администратора, Ρ‚ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π²Π΅Π΄Π΅Π½ Π΄ΠΈΠ°Π»ΠΎΠ³ для Π²Π²ΠΎΠ΄Π° Π»ΠΎΠ³ΠΈΠ½Π° ΠΈ пароля, Π΄Π°Π½Π½Ρ‹Π΅ Π±ΡƒΠ΄ΡƒΡ‚ сохранСны Π² памяти ΠΈ подставятся Π² ΠΊΠ°ΠΆΠ΄ΡƒΡŽ ΠΊΠΎΠΌΠ°Π½Π΄Ρƒ для ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π³ΠΎ кластСра.

Π—Π° это ΠΎΡ‚Π²Π΅Ρ‡Π°Π΅Ρ‚ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ошибок

ErrorParcing

proc ErrorParcing {err opt} {
    global cluster_user cluster_pwd agent_user agent_pwd
        switch -regexp -- $err {
        "Cluster administrator is not authenticated" {
            AuthorisationDialog "Администратор кластСра"
            .auth_win.frm_btn.btn_ok configure -command {
                set cluster_user [.auth_win.frm.ent_name get]
                set cluster_pwd [.auth_win.frm.ent_pwd get]
                destroy .auth_win
            }
            #RunCommand $root $par
        }
        "Central server administrator is not authenticated" {
            AuthorisationDialog "Администратор Π°Π³Π΅Π½Ρ‚Π° кластСра"
            .auth_win.frm_btn.btn_ok configure -command {
                set agent_user [.auth_win.frm.ent_name get]
                set agent_pwd [.auth_win.frm.ent_pwd get]
                destroy .auth_win
            }
        }
        "Администратор кластСра Π½Π΅ Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½" {
            AuthorisationDialog "Администратор кластСра"
            .auth_win.frm_btn.btn_ok configure -command {
                set cluster_user [.auth_win.frm.ent_name get]
                set cluster_pwd [.auth_win.frm.ent_pwd get]
                destroy .auth_win
            }
            #RunCommand $root $par
        }
        "Администратор Ρ†Π΅Π½Ρ‚Ρ€Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ сСрвСра Π½Π΅ Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½" {
            AuthorisationDialog "Администратор Π°Π³Π΅Π½Ρ‚Π° кластСра"
            .auth_win.frm_btn.btn_ok configure -command {
                set agent_user [.auth_win.frm.ent_name get]
                set agent_pwd [.auth_win.frm.ent_pwd get]
                destroy .auth_win
            }
        }
        (.+) {
            tk_messageBox -type ok -icon error -message "$err"
        }
    }
}

Π’.Π΅. Π² зависимости ΠΎΡ‚ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΠΊΠΎΠΌΠ°Π½Π΄Π°, Π±ΡƒΠ΄Π΅Ρ‚ соотвСтствСнно ΠΈ рСакция.

На Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π° ΠΏΡ€ΠΎΡ†Π΅Π½Ρ‚ΠΎΠ² эдак Π½Π° 95, ΠΎΡΡ‚Π°Π»ΠΎΡΡŒ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π°Π±ΠΎΡ‚Ρƒ с профилями бСзопасности Π½Ρƒ ΠΈ ΠΎΡ‚Ρ‚Π΅ΡΡ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ =). На этом всё. ΠŸΡ€ΠΎΡˆΡƒ прощСния Π·Π° скомканноС повСствованиС.

Код, ΠΏΠΎ Ρ‚Ρ€Π°Π΄ΠΈΡ†ΠΈΠΈ доступСн Ρ‚ΡƒΡ‚.

ОбновлСниС: Π”ΠΎΠ΄Π΅Π»Π°Π» Ρ€Π°Π±ΠΎΡ‚Ρƒ с профилями бСзопасности. Π’Π΅ΠΏΠ΅Ρ€ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π° Π½Π° 100%.

ОбновлСниС 2: Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Π° локализация Π½Π° английский ΠΈ русский, ΠΏΡ€ΠΎΠ²Π΅Ρ€Π΅Π½Π° Ρ€Π°Π±ΠΎΡ‚Π° Π² win7
ПишСм GUI к 1Б RAC, или снова о Tcl/Tk

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com