mirror of
https://github.com/xcat2/confluent.git
synced 2024-11-22 09:32:21 +00:00
Add multi-address registration
This enables scanning a range or subnet
This commit is contained in:
parent
2c1e88d927
commit
9837ad7932
@ -51,16 +51,27 @@ columnmapping = {
|
||||
#TODO: add chassis uuid
|
||||
|
||||
def register_endpoint(options, session, addr):
|
||||
neednewline = False
|
||||
current = 0
|
||||
for rsp in session.update('/discovery/register', {'addresses': addr}):
|
||||
if 'count' in rsp:
|
||||
total = rsp['count']
|
||||
elif total > 1:
|
||||
current += 1
|
||||
sys.stdout.write('\x1b[2K\r{0:.1f}% Scanned'.format(100 * current / total))
|
||||
sys.stdout.flush()
|
||||
neednewline = True
|
||||
if 'created' in rsp:
|
||||
if neednewline:
|
||||
print('')
|
||||
neednewline = False
|
||||
print('Registered: {0}'.format(rsp['created']))
|
||||
else:
|
||||
sys.stderr.write(repr(rsp))
|
||||
sys.stderr.write('\n')
|
||||
if neednewline:
|
||||
print('')
|
||||
|
||||
def subscribe_discovery(options, session, subscribe):
|
||||
def subscribe_discovery(options, session, subscribe, targ):
|
||||
keyn = 'subscribe' if subscribe else 'unsubscribe'
|
||||
payload = {keyn: options.node}
|
||||
payload = {keyn: targ}
|
||||
if subscribe:
|
||||
for rsp in session.update('/discovery/subscriptions/{0}'.format(options.node), payload):
|
||||
if 'status' in rsp:
|
||||
@ -383,6 +394,12 @@ def main():
|
||||
if len(args) == 0 or args[0] not in ('list', 'assign', 'reassign', 'rescan', 'clear', 'subscribe', 'unsubscribe', 'register'):
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
if args[0] == 'register' and len(args) != 2:
|
||||
sys.stderr.write('Register requires target address or range (e.g. 192.168.2.30, 192.168.2.0/24, or 192.168.2.1-192.168.2.30)')
|
||||
sys.exit(1)
|
||||
if 'subscribe' in args[0] and len(args) != 2:
|
||||
sys.stderr.write('subscribe/unsubscribe subcommands require switch name as argument')
|
||||
sys.exit(1)
|
||||
session = client.Command()
|
||||
if args[0] == 'list':
|
||||
list_discovery(options, session)
|
||||
@ -395,9 +412,9 @@ def main():
|
||||
if args[0] == 'register':
|
||||
register_endpoint(options, session, args[1])
|
||||
if args[0] == 'subscribe':
|
||||
subscribe_discovery(options, session, True)
|
||||
subscribe_discovery(options, session, True, args[1])
|
||||
if args[0] == 'unsubscribe':
|
||||
subscribe_discovery(options, session, False)
|
||||
subscribe_discovery(options, session, False, args[1])
|
||||
if args[0] == 'rescan':
|
||||
blocking_scan(session)
|
||||
print("Rescan complete")
|
||||
|
@ -83,6 +83,7 @@ import json
|
||||
import eventlet
|
||||
import traceback
|
||||
import shlex
|
||||
import struct
|
||||
import eventlet.green.socket as socket
|
||||
import socket as nsocket
|
||||
import eventlet.green.subprocess as subprocess
|
||||
@ -385,6 +386,59 @@ single_selectors = set([
|
||||
])
|
||||
|
||||
|
||||
def addr_to_number(addr):
|
||||
addr = socket.inet_pton(socket.AF_INET, addr)
|
||||
num = struct.unpack('!I', addr)[0]
|
||||
return num
|
||||
|
||||
def number_to_addr(number):
|
||||
addr = struct.pack('!I', number)
|
||||
addr = socket.inet_ntop(socket.AF_INET, addr)
|
||||
return addr
|
||||
|
||||
def iterate_addrs(addrs, countonly=False):
|
||||
if '.' not in addrs:
|
||||
raise exc.InvalidArgumentException('IPv4 only supported')
|
||||
if '-' in addrs:
|
||||
first, last = addrs.split('-', 1)
|
||||
currn = addr_to_number(first)
|
||||
last = addr_to_number(last)
|
||||
if last < currn:
|
||||
tm = currn
|
||||
currn = last
|
||||
currn = tm
|
||||
if (last - currn) > 65538:
|
||||
raise exc.InvalidArgumentException("Too many ip addresses")
|
||||
if countonly:
|
||||
yield last - currn + 1
|
||||
return
|
||||
while currn <= last:
|
||||
yield number_to_addr(currn)
|
||||
currn += 1
|
||||
elif '/' in addrs:
|
||||
first, plen = addrs.split('/', 1)
|
||||
plen = int(plen)
|
||||
if plen > 32:
|
||||
raise exc.InvalidArgumentException("Invalid prefix length")
|
||||
mask = (2**32 - 1) ^ (2**(32 - plen) - 1)
|
||||
currn = addr_to_number(first)
|
||||
currn = currn & mask
|
||||
numips = 2**(32 - plen)
|
||||
if numips > 65538:
|
||||
raise exc.InvalidArgumentException("Too many ip addresses")
|
||||
if countonly:
|
||||
yield numips
|
||||
return
|
||||
while numips > 0:
|
||||
yield number_to_addr(currn)
|
||||
currn += 1
|
||||
numips -= 1
|
||||
else:
|
||||
if countonly:
|
||||
yield 1
|
||||
return
|
||||
yield addrs
|
||||
|
||||
def _parameterize_path(pathcomponents):
|
||||
listrequested = False
|
||||
childcoll = True
|
||||
@ -442,6 +496,30 @@ def save_subscriptions(subs):
|
||||
with open('/etc/confluent/discovery_subscriptions.json', 'w') as dso:
|
||||
dso.write(json.dumps(subs))
|
||||
|
||||
|
||||
def register_remote_addrs(addresses, configmanager):
|
||||
def register_remote_addr(addr):
|
||||
nd = {
|
||||
'addresses': [(addr, 443)]
|
||||
}
|
||||
sd = ssdp.check_fish(('/DeviceDescription.json', nd))
|
||||
if not sd:
|
||||
return addr, False
|
||||
sd['hwaddr'] = sd['attributes']['mac-address']
|
||||
nh = xcc.NodeHandler(sd, configmanager)
|
||||
nh.scan()
|
||||
detected(nh.info)
|
||||
return addr, True
|
||||
rpool = eventlet.greenpool.GreenPool(512)
|
||||
for count in iterate_addrs(addresses, True):
|
||||
yield msg.ConfluentResourceCount(count)
|
||||
for result in rpool.imap(register_remote_addr, iterate_addrs(addresses)):
|
||||
if result[1]:
|
||||
yield msg.CreatedResource(result[0])
|
||||
else:
|
||||
yield msg.ConfluentResourceNotFound(result[0])
|
||||
|
||||
|
||||
def handle_api_request(configmanager, inputdata, operation, pathcomponents):
|
||||
if pathcomponents == ['discovery', 'autosense']:
|
||||
return handle_autosense_config(operation, inputdata)
|
||||
@ -477,17 +555,7 @@ def handle_api_request(configmanager, inputdata, operation, pathcomponents):
|
||||
if pathcomponents == ['discovery', 'register']:
|
||||
if 'addresses' not in inputdata:
|
||||
raise exc.InvalidArgumentException('Missing address in input')
|
||||
nd = {
|
||||
'addresses': [(inputdata['addresses'], 443)]
|
||||
}
|
||||
sd = ssdp.check_fish(('/DeviceDescription.json', nd))
|
||||
if not sd:
|
||||
raise exc.InvalidArgumentException('Target address is not detected or is not a supported device for remote discovery registration')
|
||||
sd['hwaddr'] = sd['attributes']['mac-address']
|
||||
nh = xcc.NodeHandler(sd, configmanager)
|
||||
nh.scan()
|
||||
detected(nh.info)
|
||||
return [msg.CreatedResource(inputdata['address'])]
|
||||
return register_remote_addrs(inputdata['addresses'], configmanager)
|
||||
if 'node' not in inputdata:
|
||||
raise exc.InvalidArgumentException('Missing node name in input')
|
||||
mac = _get_mac_from_query(pathcomponents)
|
||||
|
@ -309,6 +309,29 @@ class DeletedResource(ConfluentMessage):
|
||||
pass
|
||||
|
||||
|
||||
class ConfluentResourceNotFound(ConfluentMessage):
|
||||
notnode = True
|
||||
apicode = 404
|
||||
|
||||
def __init__(self, resource):
|
||||
self.myargs = [resource]
|
||||
self.desc = 'Not Found'
|
||||
self.kvpairs = {'missing': resource}
|
||||
|
||||
def strip_node(self, node):
|
||||
pass
|
||||
|
||||
class ConfluentResourceCount(ConfluentMessage):
|
||||
notnode = True
|
||||
|
||||
def __init__(self, count):
|
||||
self.myargs = [count]
|
||||
self.desc = 'Resource Count'
|
||||
self.kvpairs = {'count': count}
|
||||
|
||||
def strip_node(self, node):
|
||||
pass
|
||||
|
||||
class CreatedResource(ConfluentMessage):
|
||||
notnode = True
|
||||
readonly = True
|
||||
|
Loading…
Reference in New Issue
Block a user