From af7c8ef6748f470d3ef3dbef6a1019a1024bf350 Mon Sep 17 00:00:00 2001 From: mgaliar <53537622+mgaliar@users.noreply.github.com> Date: Thu, 15 Feb 2024 05:58:29 -1000 Subject: [PATCH] Adding flexibility for sceptre app (#23) --- .../phenix_apps/apps/sceptre/sceptre.py | 65 ++++++++++++++++--- .../apps/sceptre/templates/auto_winscp.mako | 32 +++++++++ .../apps/sceptre/templates/hmi.mako | 2 - .../apps/sceptre/templates/putty.mako | 12 ++-- .../apps/sceptre/templates/sceptre_start.mako | 2 +- 5 files changed, 95 insertions(+), 18 deletions(-) create mode 100644 src/python/phenix_apps/apps/sceptre/templates/auto_winscp.mako diff --git a/src/python/phenix_apps/apps/sceptre/sceptre.py b/src/python/phenix_apps/apps/sceptre/sceptre.py index 0b5febf..833676e 100644 --- a/src/python/phenix_apps/apps/sceptre/sceptre.py +++ b/src/python/phenix_apps/apps/sceptre/sceptre.py @@ -226,6 +226,17 @@ def configure(self): }) self.add_inject(hostname=engineer_workstation.hostname, inject=kwargs) + # Create auto putty connection startup script injection + if "connect_interval" in engineer_workstation.metadata: + kwargs = self.find_override(f"{engineer_workstation.hostname}_auto_winscp.ps1") + if kwargs is None: + kwargs = {"src": f"{engineer_directory}/auto_winscp.ps1"} + kwargs.update({ + "dst": "/sceptre/startup/40-auto_winscp.ps1", + "description": "engineer_workstation auto putty connections", + }) + self.add_inject(hostname=engineer_workstation.hostname, inject=kwargs) + # Create sceptre startup scheduler injections # Mirrors the phenix startup scheduler but is needed in order to run things as local user for UI automation kwargs = { @@ -1306,9 +1317,25 @@ def pre_start(self): ######################## HMI pre-start ################################### # Create hmi files hmis = self.extract_nodes_type("hmi") + scada_servers = self.extract_nodes_type("scada-server") for hmi in hmis: hmi_ip = hmi.topology.network.interfaces[0].address + #add scada connection based on metadata or based on subnet if not metadata + hmi_scada_ips = [] + if "connected_scadas" in hmi.metadata: + for hmi_scada_server in hmi.metadata.connected_scadas: + for scada_server in scada_servers: + if hmi_scada_server == scada_server.hostname: + hmi_scada_ips.append(scada_server.topology.network.interfaces[0].address) + else: + if len(scada_ips) == 1: + hmi_scada_ips = scada_ips + else: + for scada_ip in scada_ips: + if scada_ip.split('.')[:-1] == hmi_ip.split('.')[:-1]: + hmi_scada_ips.append(scada_ip) + hmi_directory = f"{self.sceptre_dir}/{hmi.hostname}" os.makedirs(hmi_directory, exist_ok=True) @@ -1320,33 +1347,39 @@ def pre_start(self): hmi_mako, self.mako_templates_path, file_, - scada_ips=scada_ips, + scada_ips=hmi_scada_ips, hmi_ip=hmi_ip, ) ######################## Engineer Workstation pre-start ################################### # Create engineer workstation files - rtus = self.extract_nodes_type("rtu") + rtus = self.extract_nodes_type("fd-server") eng_fd = [] - for rtu in rtus: - eng_fd.append(rtu) - engineer_workstations = self.extract_nodes_type( - "engineering-workstation" + "engineer-workstation" ) + #get rtus that engineer workstation can connect to. Connect to all if none given. for engineer_workstation in engineer_workstations: + if "connected_rtus" in engineer_workstation.metadata: + for engineer_rtu in engineer_workstation.metadata.connected_rtus: + for rtu in rtus: + if engineer_rtu == rtu.hostname: + eng_fd.append(rtu) + else: + for rtu in rtus: + eng_fd.append(rtu) + engineer_directory = ( f"{self.sceptre_dir}/{engineer_workstation.hostname}" ) - os.makedirs(engineer_directory, exist_ok=True) # Wrtie engineer workstation putty injection - auto_engineer = f"{engineer_directory}/putty.ps1" + putty = f"{engineer_directory}/putty.ps1" engineer_mako = "putty.mako" - with open(auto_engineer, "w") as file_: + with open(putty, "w") as file_: utils.mako_serve_template( engineer_mako, self.mako_templates_path, @@ -1355,6 +1388,20 @@ def pre_start(self): eng_fd=eng_fd, ) + #automation script to actively create putty connection + if "connect_interval" in engineer_workstation.metadata: + auto_winscp = f"{engineer_directory}/auto_winscp.ps1" + auto_winscp_mako = "auto_winscp.mako" + with open(auto_winscp, "w") as file_: + utils.mako_serve_template( + auto_winscp_mako, + self.mako_templates_path, + file_, + eng_fd=eng_fd, + connect_interval=engineer_workstation.metadata.connect_interval + ) + + ######################## Historian pre-start ################################### # Determine primary/secondary historian secondary_historian_ips = {"historian": []} diff --git a/src/python/phenix_apps/apps/sceptre/templates/auto_winscp.mako b/src/python/phenix_apps/apps/sceptre/templates/auto_winscp.mako new file mode 100644 index 0000000..11ed70e --- /dev/null +++ b/src/python/phenix_apps/apps/sceptre/templates/auto_winscp.mako @@ -0,0 +1,32 @@ +function Phenix-StartupComplete { + $key = Get-Item -LiteralPath 'HKLM:\Software\phenix' -ErrorAction SilentlyContinue + + if ($key) { + $val = $key.GetValue('startup') + + if ($val) { + return $val -eq 'done' + } + + return $false + } + + return $false +} +while (-Not (Phenix-StartupComplete)) { + Start-Sleep -s 30 +} + +while ($true) +{ + Start-Sleep -s ${connect_interval} + % for fd in eng_fd: + % for iface in fd.topology.network.interfaces: + % if not iface.type == 'serial' and iface.vlan.lower() != 'mgmt': +$winscp = Start-Process -FilePath "C:\Program Files (x86)\WinSCP\WinSCP.exe" -ArgumentList "/console /open -hostkey=* scp://root:SiaSd3te@${iface.address}" -passthru +Start-Sleep -s 5 +Stop-Process $winscp.Id + % endif + % endfor + % endfor +} diff --git a/src/python/phenix_apps/apps/sceptre/templates/hmi.mako b/src/python/phenix_apps/apps/sceptre/templates/hmi.mako index 4d44eba..151847d 100644 --- a/src/python/phenix_apps/apps/sceptre/templates/hmi.mako +++ b/src/python/phenix_apps/apps/sceptre/templates/hmi.mako @@ -38,9 +38,7 @@ Show-Sleep(200) Echo '' Echo 'Opening MySCADA Interface...' % for scada_addr in scada_ips: -% if scada_addr.split('.')[:-1] == hmi_ip.split('.')[:-1] or len(scada_ips) == 1: Start-Process -FilePath "C:\Program Files (x86)\Mozilla Firefox\firefox.exe" -ArgumentList ${scada_addr} -WindowStyle Maximized -% endif % endfor Echo 'Done.' diff --git a/src/python/phenix_apps/apps/sceptre/templates/putty.mako b/src/python/phenix_apps/apps/sceptre/templates/putty.mako index c5cd002..3184fb4 100644 --- a/src/python/phenix_apps/apps/sceptre/templates/putty.mako +++ b/src/python/phenix_apps/apps/sceptre/templates/putty.mako @@ -21,12 +21,12 @@ while (-Not (Phenix-StartupComplete)) { new-item -path "HKCU:\Software\SimonTatham\" new-item -path "HKCU:\Software\SimonTatham\PuTTY\" new-item -path "HKCU:\Software\SimonTatham\PuTTY\Sessions" -new-item -path "HKCU:\Software\SimonTatham\PuTTY\Sessions\${fd.name}" - % for iface in fd.interfaces: - % if not iface.type_ == 'serial' and iface.vlan_alias.lower() != 'mgmt': -new-itemproperty -path "HKCU:\Software\SimonTatham\PuTTY\Sessions\${fd.name}" -name Hostname -value ${iface.ipv4_address} -new-itemproperty -path "HKCU:\Software\SimonTatham\PuTTY\Sessions\${fd.name}" -name Protocol -value telnet -new-itemproperty -path "HKCU:\Software\SimonTatham\PuTTY\Sessions\${fd.name}" -name PortNumber -value 1337 -type DWord +new-item -path "HKCU:\Software\SimonTatham\PuTTY\Sessions\${fd.hostname}" + % for iface in fd.topology.network.interfaces: + % if not iface.type == 'serial' and iface.vlan.lower() != 'mgmt': +new-itemproperty -path "HKCU:\Software\SimonTatham\PuTTY\Sessions\${fd.hostname}" -name Hostname -value ${iface.address} +new-itemproperty -path "HKCU:\Software\SimonTatham\PuTTY\Sessions\${fd.hostname}" -name Protocol -value telnet +new-itemproperty -path "HKCU:\Software\SimonTatham\PuTTY\Sessions\${fd.hostname}" -name PortNumber -value 1337 -type DWord <% break %> % endif % endfor diff --git a/src/python/phenix_apps/apps/sceptre/templates/sceptre_start.mako b/src/python/phenix_apps/apps/sceptre/templates/sceptre_start.mako index fd49a01..389ef56 100644 --- a/src/python/phenix_apps/apps/sceptre/templates/sceptre_start.mako +++ b/src/python/phenix_apps/apps/sceptre/templates/sceptre_start.mako @@ -1,6 +1,6 @@ % if os == 'linux': % for interface in ips: - % if interface['vlan'] and interface['vlan'].lower() == 'mgmt': + % if interface['vlan']: echo 'ListenAddress ${interface['address']}' >> /etc/ssh/sshd_config % endif % endfor