Remove IPAM driver and implement `CreateNetwork` / `DeleteNetwork`

pull/8/head
Jack O'Sullivan 5 years ago
parent 92dfd90ea0
commit 272eea0d55

@ -3,8 +3,7 @@
"interface": { "interface": {
"socket": "net-dhcp.sock", "socket": "net-dhcp.sock",
"types": [ "types": [
"docker.networkdriver/1.0", "docker.networkdriver/1.0"
"docker.ipamdriver/1.0"
] ]
}, },
"entrypoint": [ "/opt/plugin/launch.sh" ], "entrypoint": [ "/opt/plugin/launch.sh" ],
@ -16,7 +15,10 @@
{ {
"source": "/var/run/docker.sock", "source": "/var/run/docker.sock",
"destination": "/run/docker.sock", "destination": "/run/docker.sock",
"type": "bind" "type": "bind",
"options": [
"bind"
]
} }
], ],
"linux": { "linux": {

@ -2,7 +2,7 @@ from flask import Flask, jsonify
app = Flask(__name__) app = Flask(__name__)
from . import network, ipam from . import network
@app.errorhandler(404) @app.errorhandler(404)
def err_not_found(e): def err_not_found(e):

@ -1,58 +0,0 @@
import itertools
import ipaddress
from os import path
import atexit
import pyroute2
import docker
from flask import jsonify
from . import app
ipdb = pyroute2.IPDB()
@atexit.register
def close_ipdb():
ipdb.release()
client = docker.from_env()
@atexit.register
def close_docker():
client.close()
def iface_addrs(iface):
return list(map(ipaddress.ip_interface, iface.ipaddr.ipv4))
def iface_nets(iface):
return list(map(lambda n: n.network, map(ipaddress.ip_interface, iface.ipaddr.ipv4)))
def get_bridges():
reserved_nets = set(map(ipaddress.ip_network, map(lambda c: c['Subnet'], \
itertools.chain.from_iterable(map(lambda i: i['Config'], filter(lambda i: i['Driver'] != 'net-dhcp', \
map(lambda n: n.attrs['IPAM'], client.networks.list())))))))
return list(filter(lambda i: i.kind == 'bridge' and not set(iface_nets(i)).intersection(reserved_nets), \
map(lambda i: ipdb.interfaces[i], filter(lambda k: isinstance(k, str), ipdb.interfaces.keys()))))
@app.route('/IpamDriver.GetCapabilities')
def ipam_get_capabilities():
return jsonify({
'RequiresMACAddress': True,
'RequiresRequestReplay': False
})
@app.route('/IpamDriver.GetDefaultAddressSpace')
def get_default_addr_space():
bridges = get_bridges()
if not bridges:
return jsonify({'Err': 'No bridges available'}), 404
first = None
for b in bridges:
if b.ipaddr.ipv4:
first = b
if not first:
return jsonify({'Err': 'No bridges with addresses available'}), 404
return jsonify({
'LocalDefaultAddressSpace': f'{first.ifname}-{iface_addrs(first)[0].network}',
'GlobalDefaultAddressSpace': None
})

@ -1,10 +1,65 @@
from flask import jsonify import itertools
import ipaddress
from os import path
import logging
import atexit
import pyroute2
import docker
from flask import request, jsonify
from . import app from . import app
@app.route('/NetworkDriver.GetCapabilities') BRIDGE_OPT = 'devplayer0.net-dhcp.bridge'
logger = logging.getLogger('gunicorn.error')
ipdb = pyroute2.IPDB()
@atexit.register
def close_ipdb():
ipdb.release()
client = docker.from_env()
@atexit.register
def close_docker():
client.close()
def iface_addrs(iface):
return list(map(ipaddress.ip_interface, iface.ipaddr.ipv4))
def iface_nets(iface):
return list(map(lambda n: n.network, map(ipaddress.ip_interface, iface.ipaddr.ipv4)))
def get_bridges():
reserved_nets = set(map(ipaddress.ip_network, map(lambda c: c['Subnet'], \
itertools.chain.from_iterable(map(lambda i: i['Config'], filter(lambda i: i['Driver'] != 'net-dhcp', \
map(lambda n: n.attrs['IPAM'], client.networks.list())))))))
return dict(map(lambda i: (i.ifname, i), filter(lambda i: i.kind == 'bridge' and not \
set(iface_nets(i)).intersection(reserved_nets), map(lambda i: ipdb.interfaces[i], \
filter(lambda k: isinstance(k, str), ipdb.interfaces.keys())))))
@app.route('/NetworkDriver.GetCapabilities', methods=['POST'])
def net_get_capabilities(): def net_get_capabilities():
return jsonify({ return jsonify({
'Scope': 'local', 'Scope': 'local',
'ConnectivityScope': 'global' 'ConnectivityScope': 'global'
}) })
@app.route('/NetworkDriver.CreateNetwork', methods=['POST'])
def create_net():
if BRIDGE_OPT not in request.json['Options']:
return jsonify({'Err': 'No bridge provided'}), 400
desired = request.json[BRIDGE_OPT]
bridges = get_bridges()
if desired not in bridges:
return jsonify({'Err': f'Bridge "{desired}" not found (or the specified bridge is already used by Docker)'}), 400
if request.json['IPv6Data']:
return jsonify({'Err': 'IPv6 is currently unsupported'}), 400
return jsonify({})
@app.route('/NetworkDriver.DeleteNetwork', methods=['POST'])
def delete_net():
return jsonify({})
Loading…
Cancel
Save