source: genesis/tools/node-editor@ 13899

Last change on this file since 13899 was 11515, checked in by rick, 12 years ago

Almost able to generate new nodes with the tips of a few clicks. Aliases how-ever are a big PITA.

  • Property svn:executable set to *
File size: 10.1 KB
RevLine 
[11506]1#!/usr/bin/env python
2'''
3 CLI interface which configures and makes new nodes with the most commonly
4 used commands.
5
6 Rick van der Zwet <info@rickvanderzwet.nl>
7'''
8
9import getrange
10import gformat
11import os
12import readline
13import sys
[11515]14import pyproj
[11506]15
16
[11515]17def latlon2rd(lon, lat):
18 p1 = pyproj.Proj(proj='latlon',datum='WGS84')
19 p2 = pyproj.Proj(init='EPSG:28992')
20 RDx, RDy = pyproj.transform(p1,p2, lon, lat)
21 return (int(RDx), int(RDy))
22
23
[11506]24print "WARNING I AM NOT PRODUCTION CODE YET!" + __doc__
25
26DEBUG = "-g" in sys.argv
27
[11515]28# Global variable, because this is dirty code.
29datadump = None
30
[11506]31def rlprompt(prompt, prefill=''):
32 ''' Get line with some boring default '''
[11513]33 prompt = "%s [%s]: " % (prompt, prefill)
[11506]34 if DEBUG:
[11513]35 print prompt
[11506]36 return prefill
[11513]37 return raw_input(prompt) or prefill
[11506]38
39def rlinput(prompt, prefill=''):
40 ''' Get line with some editable boring default '''
41 if DEBUG:
[11513]42 print "%s [%s]:" % (prompt, prefill)
[11506]43 return prefill
44 readline.set_startup_hook(lambda: readline.insert_text(prefill))
45 try:
46 return raw_input(prompt + ": ")
47 finally:
48 readline.set_startup_hook()
49
50def rlinput_float(prompt, prefill=0):
51 while True:
52 try:
[11515]53 prefill = rlinput(prompt, str(prefill))
[11506]54 return float(prefill)
55 except ValueError:
56 print "Invalid Number!"
57 pass
58
59def rlinput_choices(prompt, choices, prefill=''):
60 if DEBUG:
[11513]61 print '%s [%s]:' % (prompt, prefill)
[11506]62 return prefill
63 while True:
[11513]64 filtered_choices = sorted(list(set([x for x in choices if (str(prefill).lower() in str(x).lower())])))
[11506]65 if len(filtered_choices) == 1:
66 return filtered_choices[0]
67 elif len(filtered_choices) == 0:
68 filtered_choices = choices
69 prefill = rlinput(prompt + ' ' + str(filtered_choices), prefill)
70 if prefill in prompt:
71 return prefill
72
73
74
75
76
77
78def newNode():
79 datadump = {
80 'nodename' : "New",
81 'location' : "1234 AB, Leiden",
82 'nodetype' : "Hybrid",
83 'latitude' : "52.",
84 'longitude' : "4.",
85 }
86 datadump['nodename'] = rlprompt("Nodename", datadump['nodename'])
87 datadump['location'] = rlprompt("Location", datadump['location'])
88 datadump['nodetype'] = rlprompt("Nodetype", datadump['nodetype'])
89 datadump['latitude'] = rlinput_float("Latitude", datadump['latitude'])
90 datadump['longitude'] = rlinput_float("Longitude", datadump['longitude'])
[11515]91 (datadump['rdnap_x'], datadump['rdnap_y']) = latlon2rd(datadump['longitude'], datadump['latitude'])
[11506]92 datadump['autogen_item'] = datadump['nodetype'] + datadump['nodename']
93
94 print "Generating the Master IP range..."
95 master_network = getrange.get_ranges(False, 24, 1)[0]
96 master_ip = getrange.showaddr(master_network + 1)
[11515]97 datadump['masterip'] = master_ip
[11506]98
[11515]99 if os.path.exists(datadump['autogen_item']):
100 print "Warning Node does already exists, overwriting!"
[11506]101
[11515]102
103 # Secret global state variable
[11513]104 newNode.if_nr = 0
[11515]105 def next_ifnr():
106 if_nr = newNode.if_nr
107 newNode.if_nr = newNode.if_nr + 1
108 return if_nr
109
110 def new_access_point(link_type='wireless'):
111 if link_type == 'wireless':
112 ifname = rlinput("Interface name", "ath0")
113 datadump['iface_' + ifname] = {
114 'ip' : rlinput(" - IP", master_ip + "/26"),
115 'dhcp' : rlinput(" - DHCP range", "10-60"),
116 'ssid' : rlinput(" - SSID", "ap-WirelessLeiden-" + datadump['nodename']),
117 'mode' : 'ap',
118 'type' : '11b',
119 'comment' : rlinput(" - Comment", "Omni voor de Buurt"),
120 'sdesc': rlinput(" - Short Description", "2buurt"),
121 'channel' : rlprompt(" - Channel", "10"),
122 'status' : 'up',
123 }
124 elif link_type == 'wired':
125 if_nr = next_ifnr()
126 ifname = rlinput("Interface name", "vr%i" % if_nr)
127 netmask = int(rlinput_float("Netmask", 24))
128 print "Generating the Master IP range..."
129 link_network = getrange.get_ranges(False, netmask, 1, use_history=True)[0]
130 datadump['iface_' + ifname] = {
131 'ip' : rlinput(" - IP", gformat.showaddr(link_network + 1) + "/" + str(netmask)),
132 'dhcp' : rlinput(" - DHCP range", "10-60"),
133 'ssid' : rlinput(" - SSID", "ap-WirelessLeiden-" + datadump['nodename'] + '-' + ifname),
134 'comment' : rlinput(" - Comment", "Omni voor de Buurt"),
135 'type' : 'eth',
136 'sdesc': rlinput(" - Short Description", "2buurt"),
137 'channel' : rlprompt(" - Channel", "10"),
138 'status' : 'up',
139 'mode': "ap",
140 'bridge_type': rlinput(' - Bridge Type', 'NanoStation5M'),
141 'ns_ip': rlinput(" - NS IP", getrange.showaddr(link_network + 2) + "/" + str(netmask)),
142 'ns_mac': rlinput(" - NS MAC", "00:27:22:"),
143 }
144
[11513]145 def new_interlink(link_type='wireless', link_mode='station'):
[11515]146 if_nr = next_ifnr()
147 remote_datadump = None
148 ifname = rlinput("Interface name", "vr%i" % if_nr)
[11506]149 netmask = 28
[11513]150 if link_mode == 'station':
151 remote = rlinput_choices("Create interlink with (remote host)", gformat.get_hostlist(),'Hybrid')
152 remote_datadump = gformat.get_yaml(remote)
153 print "Available remote interfaces:"
154 if_choices = []
155 for ifkey in remote_datadump['autogen_iface_keys']:
156 ifdump = remote_datadump[ifkey]
157 # Could only do this if all meta information is correct
158 #if link_type == 'wireless' and link_mode == 'station':
159 # basedump = remote_datadump['iface_' + ifdump['autogen_ifbase']]
160 # if not basedump.has_key('mode') or basedump['mode'] != 'ap-wds':
161 # continue
162 if_choices.append(ifdump['autogen_ifbase'])
163 print " - %4s" % ifdump['autogen_ifbase'], '- %20s' % ifdump['ip'], '- %30s' % ifdump['comment'],
164 if ifdump.has_key('ssid'):
165 print '-', ifdump['ssid']
166 else:
167 print ''
[11515]168 remote_ifname = rlinput_choices("Remote interface", if_choices)
169 remote_ifdump = remote_datadump['iface_%s' % remote_ifname]
[11510]170
[11513]171 #make_alias = rlprompt("Create Alias", "no") == "yes"
[11515]172 link_network = gformat.network(remote_ifdump['ip'])
[11513]173 elif link_mode == 'master':
[11515]174 remote = rlinput("Interlink is planned for (remote host)", 'Unused%s' % if_nr)
[11513]175 print "Generating the Interlink IP range..."
[11515]176 link_network = getrange.get_ranges(True, netmask, 1, use_history=True)[0]
[11513]177
178 print "Using Network %s/%s" % (gformat.showaddr(link_network), netmask)
179
180 # XXX: Create remote linking
181 # XXX: This does not handle IP pools
182
183 # Common part
[11506]184 datadump['iface_%s' % ifname] = {
185 'comment': rlinput(" - Comment", "Link naar " + remote),
186 'sdesc': rlinput(" - Short Description", "2" + remote),
187 'type': "eth",
188 'status': 'up',
[11513]189 'dhcp': 'False',
[11506]190 }
[11513]191 if link_type == 'wireless':
192 compass = rlprompt("Compass direction", 'n')
193 datadump['iface_%s' % ifname].update({
194 'ns_mac': rlinput(" - NS MAC", "00:27:22:"),
195 'bridge_type': rlinput(' - Bridge Type', 'NanoStation5M'),
196 'compass': compass,
197 })
198 if link_mode == 'master':
199 datadump['iface_%s' % ifname].update({
200 'ssid': rlinput(" - SSID", 'il-%s.%s.wleiden.net' % (compass, datadump['nodename'])),
201 'ip': rlinput(" - IP", getrange.showaddr(link_network + 1) + "/" + str(netmask)),
202 'ns_ip': rlinput(" - NS IP", getrange.showaddr(link_network + 2) + "/" + str(netmask)),
203 'mode': "ap-wds",
204 })
205 elif link_mode == 'station':
206 datadump['iface_%s' % ifname].update({
[11515]207 'ssid': rlinput(" - SSID", remote_ifdump['ssid']),
[11513]208 'ip': rlinput(" - IP", getrange.showaddr(link_network + 3) + "/" + str(netmask)),
209 'ns_ip': rlinput(" - NS IP", getrange.showaddr(link_network + 4) + "/" + str(netmask)),
210 'mode': "station-wds",
211 })
[11515]212 remote_datadump['iface_' + remote_ifname]['comment'] = 'Link naar %s' % datadump['nodename']
213 remote_datadump['iface_' + remote_ifname]['sdesc'] = '2%s' % datadump['nodename']
214
[11513]215 elif link_type == 'wired':
216 if link_mode == 'master':
217 datadump['iface_%s' % ifname].update({
218 'ip': rlinput(" - IP", getrange.showaddr(link_network + 1) + "/" + str(netmask)),
219 })
220 elif link_mode == 'station':
221 datadump['iface_%s' % ifname].update({
222 'ip': rlinput(" - IP", getrange.showaddr(link_network + 2) + "/" + str(netmask)),
223 })
[11515]224 remote_datadump['iface_' + remote_ifname]['comment'] = 'Link naar %s' % datadump['nodename']
225 remote_datadump['iface_' + remote_ifname]['sdesc'] = '2%s' % datadump['nodename']
[11506]226
[11515]227 if remote_datadump:
228 # Alter remote side of interfaces
229 gformat.store_yaml(remote_datadump)
230
231
[11513]232 def printMenu():
233 print '''\
234==========================================
[11515]235Create new Interface:
236 === Public Access Points ===
237 1) Accesspoint (ath0)
238 2) Accesspoint with Bridge/Switch (vr0)
239
240 === Wireless Interlinks ===
241 3) Wireless Bridge (master)
242 4) Wireless Bridge (station)
243
244 === Multiple Nodes at location ===
245 5) Ethernet Cross-connect (master)
246 6) Ethernet Cross-connect (station)
247
248 === When finished adding links ===
[11513]249 9) Finish and Save
250==========================================
251 '''
252
[11515]253 choice = ''
254 while True:
[11513]255 printMenu()
256 choice = int(rlprompt("Choice", choice))
257 if choice == 1:
[11515]258 new_access_point('wireless')
[11513]259 elif choice == 2:
[11515]260 new_access_point('wired')
[11513]261 elif choice == 3:
262 new_interlink('wired', 'master')
263 elif choice == 4:
[11515]264 new_interlink('wired', 'station')
[11513]265 elif choice == 5:
266 new_interlink('wireless', 'master')
[11515]267 elif choice == 6:
268 new_interlink('wireless', 'station')
269 elif choice == 9:
270 break
[11513]271 else:
272 print "Invalid choice!"
273
274 # Output final result
[11506]275 print datadump
[11515]276 if not os.path.exists(datadump['autogen_item']):
277 os.mkdir(datadump['autogen_item'])
278 gformat.store_yaml(datadump)
[11513]279
[11515]280 print "Please check changes and commit result"
[11506]281
282
283
284if __name__ == '__main__':
285 def printMenu():
[11513]286 print '''\
287==========================================
288Node File Editor by Rick van der Zwet
[11506]289
290 1) New Node
291 9) Quit
[11513]292==========================================
[11506]293 '''
294
295 printMenu()
296 choice = 1
297 while choice != 9:
298 choice = int(rlprompt("Choice", choice))
299 if choice == 9:
300 break
301 elif choice == 1:
302 newNode()
303 printMenu()
304 sys.exit(1)
305 else:
306 print "Invalid choice!"
Note: See TracBrowser for help on using the repository browser.