4

I'm using a program built in python 3 that figures out which VIP (Virtual IP) subnet I should use and which load balancer the VIP should match with. The program will ask you what the IP address is of one of the pool members. Based on that, it will tell you which subnet you will need an IP address for from the VIP and which load balancer to build the VIP on. An edited example of a simple working script is ran on a linux box shown below:

from netaddr import IPNetwork, IPAddress, IPSet

global subnet
global loadbalancer

member = IPAddress(input("What is the IP address of one of the nodes? "))

# Lists for each LB pair containing the node subnets.
loadbalancer1_node_IPs = IPSet([IPNetwork('1.1.1.0/22'), IPNetwork('2.2.2.0/22'), IPNetwork('3.3.3.0/22')])
loadbalancer2_node_IPs = IPSet([IPNetwork('4.4.4.0/23'), IPNetwork('2.2.2.0/23'), IPNetwork('3.3.3.0/23')])


# Provides the LB the VIP is to be built on based on node IP address.
if IPAddress(member) in loadbalancer1_node_IPs:
    loadbalancer = "The LB pair you need to build this VIP on is loadbalancer1_node_IPs"
    subnet = "You need a VIP ip from subnet 1.1.1.0/22, 2.2.2.0/22, or 3.3.3.0/22"
elif IPAddress(member) in loadbalancer2_node_IPs:
    loadbalancer = "The LB pair you need to build this VIP on is loadbalancer2_node_IPs"
    subnet = "You need a VIP ip from subnet 4.4.4.0/23, 2.2.2.0/23, or 3.3.3.0/23"


print(loadbalancer)
print(subnet)
exit(input("Press Enter to exit."))

This scripts work fine using the cli on linux. My goal now is to use the python package PySimpleGUI to build a GUI that outputs the results. I am trying to combine the code above with the below code for PySimpleGUI:

import PySimpleGUI as sg

form = sg.FlexForm('F5 Load Balancer VIP IP and LB selector')

layout = [ [sg.Text('What is the IP address of one of the nodes'), sg.InputText()],
           [sg.OK()] ]

button, (name,) = form.Layout(layout).Read()

I am having trouble getting a basic output of the results. I tried using

window = sg.Window('Test').Layout(layout) 

and updating it with

window.FindElement('loadbalancer').Update(loadbalancer) 

but the window displays the error

"Error creating layout. The layout specified has already been used.". 

Any assistance is appreciated. Thank you.

furas
  • 134,197
  • 12
  • 106
  • 148
user30558
  • 43
  • 6
  • all variables create outside functions are global so using `global subnet` and `global loadbalancer` is useless. Word `global` is used inside function to inform function that it has to uses external/global variable instead of creating local one. – furas Jan 03 '20 at 02:19
  • always put full error message (starting at word "Traceback") in question (not comment) as text (not screenshot). There are other useful information. – furas Jan 03 '20 at 02:20
  • what is `loadbalancer` in `.Update(loadbalancer)` ? This variable exists only in other script which you don't import so you can't access in GUI. – furas Jan 03 '20 at 02:21
  • it would be better to put code in function in first script, import this function to second script and execute it in second script. This way you could get result directy in variable. And you could skip `exit(input())` – furas Jan 03 '20 at 02:27
  • @furas Thank you for your response. My apologies, I should have clarified. I tried to "Frankenstein" the code together and wasn't going anywhere. The script and PySimpleGUI code I posted work just fine separately which is I posted it that way to show it's basic function. I am just lost on how to combine the script into a GUI. Looking back at the code for this I see I can just remove that part. – user30558 Jan 03 '20 at 02:31
  • @furas that does make sense. Could you point me in the right direction on how that would be structured? I am not clear on how I would call the results from the first script to the output of PySimpleGUI. – user30558 Jan 03 '20 at 02:37
  • I would look at newer PySimpleGUI programs. The coding conventions have changed significantly since the early releases where things like FlexForm were used and chained calls. The documentation and demo programs have all been updated to use better coding conventions. – Mike from PSG Jan 03 '20 at 20:47

2 Answers2

3

It could be easier if you put code in function so you could import it to other script

vip.py

from netaddr import IPNetwork, IPAddress, IPSet

def run(ip):
    member = IPAddress(ip)

    # Lists for each LB pair containing the node subnets.
    loadbalancer1_node_IPs = IPSet([IPNetwork('1.1.1.0/22'), IPNetwork('2.2.2.0/22'), IPNetwork('3.3.3.0/22')])
    loadbalancer2_node_IPs = IPSet([IPNetwork('4.4.4.0/23'), IPNetwork('2.2.2.0/23'), IPNetwork('3.3.3.0/23')])

    # Provides the LB the VIP is to be built on based on node IP address.
    if IPAddress(member) in loadbalancer1_node_IPs:
        loadbalancer = "The LB pair you need to build this VIP on is loadbalancer1_node_IPs"
        subnet = "You need a VIP ip from subnet 1.1.1.0/22, 2.2.2.0/22, or 3.3.3.0/22"
    elif IPAddress(member) in loadbalancer2_node_IPs:
        loadbalancer = "The LB pair you need to build this VIP on is loadbalancer2_node_IPs"
        subnet = "You need a VIP ip from subnet 4.4.4.0/23, 2.2.2.0/23, or 3.3.3.0/23"
    else:
        loadbalancer = "?"
        subnet = "?"

    return loadbalancer, subnet

if __name__ == "__main__":
    # this part is not executed when script is imported to other script
    ip = input("What is the IP address of one of the nodes? ")
    loadbalancer, subnet = run(ip)
    print(loadbalancer)
    print(subnet)
    exit(input("Press Enter to exit."))

And now in GUI you can uses

import vip

loadbalancer, subnet = vip.run(ip)

like

gui.py

import vip
import PySimpleGUI as sg

form = sg.FlexForm('F5 Load Balancer VIP IP and LB selector')

layout = [ 
    [sg.Text('What is the IP address of one of the nodes'), sg.InputText(key='IP')],
    [sg.OK()] 
]

button, values = form.Layout(layout).Read()

ip = values['IP']
loadbalancer, subnet = vip.run(ip)

form = sg.FlexForm('F5 Load Balancer VIP IP and LB selector')

layout = [ 
    [sg.Text(ip)],
    [sg.Text(loadbalancer)],
    [sg.Text(subnet)],
    [sg.OK()] 
]

button, values = form.Layout(layout).Read()
furas
  • 134,197
  • 12
  • 106
  • 148
3

Working from the layouts furas posted, these are the coding conventions that are currently used with PySimpleGUI. You need to add calls to close your windows too.

Here's an updated version of the GUI based on the latest naming and coding conventions:

import vip
import PySimpleGUI as sg

layout = [ 
    [sg.Text('What is the IP address of one of the nodes'), sg.InputText(key='IP')],
    [sg.OK()] 
]

window = sg.Window('F5 Load Balancer VIP IP and LB selector', layout)

event, values = window.read()
window.close()
ip = values['IP']
loadbalancer, subnet = vip.run(ip)


layout = [ 
    [sg.Text(ip)],
    [sg.Text(loadbalancer)],
    [sg.Text(subnet)],
    [sg.OK()] 
]

window = sg.Window('F5 Load Balancer VIP IP and LB selector', layout)
event, values = window.read()
window.close()

Mike from PSG
  • 5,312
  • 21
  • 39