Skip to content

Commit 39cce67

Browse files
committed
gui CHANGE prove of concept use of socket.io
Use socket.io interface to do hostcheck while connecting to a NETCONF device.
1 parent 80a2347 commit 39cce67

File tree

4 files changed

+79
-9
lines changed

4 files changed

+79
-9
lines changed

backend/connections.py

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@
77
import json
88
import os
99

10-
from liberouterapi import auth
10+
from liberouterapi import socketio, auth
1111
from flask import request
12+
from flask_socketio import emit
13+
from eventlet import event
14+
from eventlet.timeout import Timeout
1215
import yang
1316
import netconf2 as nc
1417

@@ -18,10 +21,39 @@
1821
from .data import *
1922

2023
sessions = {}
24+
hostcheck = {}
25+
26+
27+
def hostkey_check_send(data):
28+
print(json.dumps(data))
29+
try:
30+
e = hostcheck[data['id']]
31+
e.send(data['result'])
32+
except KeyError:
33+
pass
34+
35+
36+
@socketio.on('hostcheck_result')
37+
def hostkey_check_answer(data):
38+
hostkey_check_send(data)
39+
2140

2241
def hostkey_check(hostname, state, keytype, hexa, priv):
23-
# TODO real check
24-
return True
42+
params = {'id': priv, 'hostname' : hostname, 'state' : state, 'keytype' : keytype, 'hexa' : hexa}
43+
socketio.emit('hostcheck', params, callback = hostkey_check_send)
44+
45+
timeout = Timeout(30)
46+
try:
47+
e = hostcheck[priv] = event.Event()
48+
result = e.wait()
49+
except Timeout:
50+
return False;
51+
finally:
52+
hostcheck.pop(priv, None)
53+
timeout.cancel()
54+
55+
return result
56+
2557

2658
@auth.required()
2759
def connect():
@@ -45,19 +77,19 @@ def connect():
4577
nc.setSearchpath(path)
4678

4779
ssh = nc.SSH(device['username'], password=device['password'])
48-
ssh.setAuthHostkeyCheckClb(hostkey_check)
80+
ssh.setAuthHostkeyCheckClb(hostkey_check, session['session_id'])
4981
try:
50-
session = nc.Session(device['hostname'], device['port'], ssh)
82+
ncs = nc.Session(device['hostname'], device['port'], ssh)
5183
except Exception as e:
5284
return(json.dumps({'success': False, 'error-msg': str(e)}))
5385

5486
if not user.username in sessions:
5587
sessions[user.username] = {}
5688

5789
# use key (as hostname:port:session-id) to store the created NETCONF session
58-
key = session.host + ":" + str(session.port) + ":" + session.id
90+
key = ncs.host + ":" + str(ncs.port) + ":" + ncs.id
5991
sessions[user.username][key] = {}
60-
sessions[user.username][key]['session'] = session
92+
sessions[user.username][key]['session'] = ncs
6193

6294
return(json.dumps({'success': True, 'session-key': key}))
6395

frontend/inventory/devices.component.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,16 @@
6060
<hr/>
6161
</div>
6262

63+
<div *ngIf="hostcheck" class="user-dialogue">
64+
<div *ngIf="hostcheck.msg">{{hostcheck.msg}}</div>
65+
<div>The authenticity of the host <span class="keyword">{{hostcheck.hostname}}</span> cannot be established.<br/>
66+
<span class="keyword">{{hostcheck.keytype}}</span> key fingerprint is <span class="keyword">{{hostcheck.hexa}}</span>.</div>
67+
<div>Are you sure you want to continue connecting?
68+
<button (click)="hostcheckAnswer(true)">yes</button> /
69+
<button (click)="hostcheckAnswer(false)">no</button>
70+
</div>
71+
</div>
72+
6373
<p class="msg-failure msg-rounded" *ngIf="err_msg"><span class="msg-close" (click)="err_msg=''">x</span>{{err_msg}}</p>
6474
<table class="items">
6575
<tr class="item_header">

frontend/inventory/devices.component.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@ import {Device} from './device';
88
import {DevicesService} from './devices.service'
99
import {SessionsService} from '../config/sessions.service'
1010

11+
import {SocketService} from 'app/services/socket.service';
12+
13+
enum ssh_hostcheck_status {
14+
SSH_SERVER_KNOWN_CHANGED = 2,
15+
SSH_SERVER_FOUND_OTHER = 3,
16+
SSH_SERVER_FILE_NOT_FOUND = 4,
17+
SSH_SERVER_NOT_KNOWN = 0
18+
}
19+
1120
@Component({
1221
selector: 'inventoryDevices',
1322
templateUrl: './devices.component.html',
@@ -24,10 +33,12 @@ export class InventoryDevicesComponent implements OnInit {
2433
namePlaceholder: string = "";
2534
id: number;
2635
err_msg = "";
36+
hostcheck = null;
2737

2838
constructor(
2939
private devicesService: DevicesService,
3040
private sessionsService: SessionsService,
41+
public socketService: SocketService,
3142
private router: Router) {}
3243

3344
getDevices(): void {
@@ -109,15 +120,32 @@ export class InventoryDevicesComponent implements OnInit {
109120
}
110121
}
111122

123+
hostcheckAnswer(result: boolean) {
124+
this.socketService.send('hostcheck_result', {'id': this.hostcheck.id, 'result': result});
125+
delete this.hostcheck;
126+
}
127+
112128
connect(device: Device) {
113129
/* for backward compatibility */
114130
if (!device.name) {
115131
device.name = device.hostname + ":" + device.port;
116132
}
133+
this.socketService.listen('hostcheck').subscribe((message: any) => {
134+
this.hostcheck = message;
135+
switch(message['state']) {
136+
case ssh_hostcheck_status.SSH_SERVER_KNOWN_CHANGED:
137+
this.hostcheck['msg'] = "Server has changed.";
138+
break;
139+
case ssh_hostcheck_status.SSH_SERVER_NOT_KNOWN:
140+
this.hostcheck['msg'] = "Server not known.";
141+
break;
142+
}
143+
});
117144
this.sessionsService.connect(device).subscribe(result => {
118145
if (result['success']) {
119146
this.router.navigateByUrl('/netopeer/config');
120147
} else {
148+
delete this.hostcheck;
121149
this.err_msg = result['error-msg']
122150
}
123151
});

frontend/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
},
1515
"homepage": "https://github.com/CESNET/Netopeer2GUI",
1616
"dependencies" : {
17-
"@angular/material": "^5.0.0",
18-
"@angular/cdk": "^5.0.0"
17+
"@angular/material": "^6.0.0",
18+
"@angular/cdk": "^6.0.0"
1919
}
2020
}

0 commit comments

Comments
 (0)