xpra icon
Bug tracker and wiki

This bug tracker and wiki are being discontinued
please use https://github.com/Xpra-org/xpra instead.


Ticket #1486: xpra_bal.py

File xpra_bal.py, 6.1 KB (added by Denis01, 5 years ago)
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4import os
5import sqlite3
6import paramiko # yum -y install epel-release # yum repolist # yum -y install python-pip #pip install --upgrade pip #sudo yum install gcc libffi-devel python-devel openssl-devel #pip install paramiko
7import re
8import sys
9
10
11from xpra.log import Logger
12log = Logger("proxy")
13authlog = Logger("proxy", "auth")
14
15def create_session(user_id):
16        # check db exists
17        db_name='/root/xpra.sdb'
18       
19        if os.path.exists(db_name): 
20                log("LB. No database: '%s'", db_name)
21        else: 
22                log.error("LB. No database: '%s'", db_name)
23                return 
24        # check user exists in DB
25        conn = sqlite3.connect(db_name)
26        cursor = conn.cursor()
27
28        try:
29                log.error("User ID: '%s'", [user_id])
30                cursor.execute("select * from users where user_ipn=(?)", ([user_id]))
31                usr_created=cursor.fetchone()
32        except sqlite3.DatabaseError as err:       
33                log.error("LB. DB problem:'%s'", err)
34                return
35        else:
36                conn.commit()
37
38        if not usr_created:
39                log.error("LB. No user known:'%s'", [user_id])
40                return 
41        # busy_ports - table with sessions opened on host servers
42        try:
43                cursor.execute("delete from busy_ports") 
44        except sqlite3.DatabaseError as err: 
45                log.error("Loadbalancing. Prb with table-busy_ports:'%s'", err)
46                return
47        else:
48                conn.commit()
49        # ping for port check from admin server
50        try:
51                cursor.execute("select * from hosts where adminserv='y'")
52                host_admin_data=cursor.fetchone()
53        except sqlite3.DatabaseError as err: 
54                log.error("Loadbalancing. Prb with table-hosts:'%s'", err)
55                return
56        else:
57                conn.commit()
58
59        #From admin_host ping available ports on nods
60        host_adm = host_admin_data[0]
61        host_user = host_admin_data[3]
62        host_secret = host_admin_data[4]
63        host_port = int(host_admin_data[6])
64
65        client = paramiko.SSHClient()
66        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
67        client.connect(hostname=host_adm, username=host_user, password=host_secret, port=host_port)
68
69        # get available nods to check
70        try:
71                cursor.execute("select * from hosts where nodserver='y'")
72                hosts=cursor.fetchall()
73        except sqlite3.DatabaseError as err: 
74
75                log.error("LB. Prb with table-hosts:'%s'", err)
76                return
77        else:
78                conn.commit()
79       
80        if not hosts:
81                log.error("LB. No server as target host defined")
82                return
83               
84        hosts_load=[]
85               
86        #check of busy ports=session available on each nods(hosts)
87        for row in hosts:
88                ip_serv=row[0]
89                port_start = row[1]
90                port_stop=row[2]
91
92                # Busy port check (= session available on this port)
93                comm_string='nmap '+ip_serv+' -p '+str(port_start)+'-'+str(port_stop)
94                stdin, stdout, stderr = client.exec_command(comm_string)
95                data = stdout.read() + stderr.read()
96               
97                # results text parsing - xxxx/tcp ports
98                a=[]
99                res=re.finditer('(\d+)/tcp',data)
100                for match in res :
101                        b=re.findall('(\d+)/tcp',match.group())
102                        a.append(str(b[0]))
103
104                if a: #write out of sessions opened
105                        sql = "INSERT INTO busy_ports (ip_host, port) VALUES (?,?)"
106                        cursor.executemany(sql, ((ip_serv, i) for i in a))
107                        conn.commit()
108
109                # drop all closed sessions on host (in session table still user connected but physically port on nod is close=> no session)
110                try:
111                        cursor.execute("delete from open_sessions where user in (select user from open_sessions left join busy_ports on open_sessions.ip_host=busy_ports.ip_host and open_sessions.port=busy_ports.port where busy_ports.port is NULL)")
112                except sqlite3.DatabaseError as err: 
113                        log.error("LB. Prb with tables:'%s'", err)
114                        return
115                else:
116                        conn.commit()
117                # check is user is trying to connect. And physically port is open/buzy and session record with the same user ID
118                try:
119                        cursor.execute("select * from open_sessions where user=(?)", ([user_id]))
120                        conn_alive=cursor.fetchone()
121                except sqlite3.DatabaseError as err: 
122                        log.error("LB. Prb with tables:'%s'", err)
123                        return
124                else:
125                        conn.commit()
126                       
127                if conn_alive:
128                        log.error("LB. User already connected")
129                        return
130                       
131        client.close()
132
133        # server choice by choosing the servers/nods with lowest number of open/busy ports
134        cursor.execute("select ip_host from busy_ports group by ip_host order by count(*) ASC")
135        data1=cursor.fetchone()
136        conn.commit()
137
138        if data1: # server with min number of closed ports
139                ip_serv_1=data1[0]
140
141        if not data1: # all servers are free and we will take the first one
142                cursor.execute("select host_ip from hosts where nodserver='y' order by host_ip ASC")
143                data1=cursor.fetchone()
144                conn.commit()
145                ip_serv_1=data1[0]
146
147        log.error("LB. Host chosen:'%s'", ip_serv_1)
148
149        # port choice on th choisen server
150        ####if no ports -> exit with error message!!!!
151
152        cursor.execute("select * from hosts where host_ip=(?)", ([ip_serv_1]))
153        ports_check=cursor.fetchone()
154        conn.commit()
155        port_start = ports_check[1]
156        port_stop=ports_check[2]
157
158        p_l=int(port_stop)+1-int(port_start)
159        a_p = [str(int(port_start)+i) for i in range(0,p_l)]
160
161        # temp table
162        cursor.executescript("""
163                create table avail_ports(
164                        port
165                );
166                """)
167               
168        sql = "INSERT INTO avail_ports (port) VALUES (?)"
169        cursor.executemany(sql, (([i]) for i in a_p))
170        conn.commit()
171
172        sql="select min(port) from avail_ports where port not in (select port from busy_ports where ip_host=(?))"
173        cursor.execute(sql, ([ip_serv_1]))
174        port_to_connect=cursor.fetchone()
175        conn.commit()
176        log.error("LB. Port chosen:'%s'", ip_serv_1)
177       
178        cursor.execute("drop table avail_ports")
179        conn.commit()
180
181        # get login and pass to server to connect user under user's rights
182        cursor.execute("select * from users where user_ipn=(?)", [user_id])
183        host_admin_data=cursor.fetchone()
184        conn.commit()
185
186        host_secret = host_admin_data[2]
187        user_conn_str=''.join(host_admin_data[1])
188
189        comm_string="xpra start --bind-tcp=0.0.0.0:"+port_to_connect[0]+" "+str(user_conn_str)
190
191        client = paramiko.SSHClient()
192        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
193        client.connect(hostname=ip_serv_1, username=USER_ID, password=host_secret, port=22)
194        stdin, stdout, stderr = client.exec_command(comm_string)
195        data = stdout.read() + stderr.read()
196        client.close()
197
198        log("Remote start resulsts:'%s'", data)
199
200        #write open session info
201        sql = "INSERT INTO open_sessions (ip_host, port,user) VALUES (?,?,?)"
202        cursor.execute(sql, (ip_serv_1, port_to_connect[0], user_id))
203        conn.commit()
204        cursor.close()
205        conn.close
206
207        log("Session for '%s' is created", USER_ID)
208                       
209        return
210
211                               
212
213