commit | author | age
|
f973b9
|
1 |
import ipaddress |
JK |
2 |
import random |
|
3 |
|
|
4 |
import flask |
|
5 |
import pyroute2 |
|
6 |
from docker_plugin_api.NetworkDriverEntities import * |
|
7 |
from docker_plugin_api.Plugin import Blueprint, InputValidationException |
|
8 |
|
|
9 |
from .NetworkDriverData import * |
|
10 |
|
|
11 |
app = Blueprint('NetworkDriver', __name__) |
|
12 |
|
|
13 |
|
|
14 |
def genid(size=8, chars='0123456789abcdef'): |
|
15 |
return ''.join([random.choice(chars) for _ in range(size)]) |
|
16 |
|
|
17 |
|
|
18 |
@app.route('/NetworkDriver.GetCapabilities', methods=['POST']) |
|
19 |
def GetCapabilities(): |
|
20 |
return { |
|
21 |
'Scope': 'local', |
|
22 |
'ConnectivityScope': 'global', |
|
23 |
} |
|
24 |
|
|
25 |
|
|
26 |
@app.route('/NetworkDriver.CreateNetwork', methods=['POST']) |
|
27 |
def CreateNetwork(): |
|
28 |
network = NetworkCreateEntity(**flask.request.get_json(force=True)) |
|
29 |
try: |
|
30 |
for option, value in network.Options['com.docker.network.generic'].items(): |
|
31 |
if option not in network.Options: |
|
32 |
network.Options[option] = value |
|
33 |
except KeyError: |
|
34 |
pass |
|
35 |
networks[network.NetworkID] = network |
|
36 |
return {} |
|
37 |
|
|
38 |
|
|
39 |
@app.route('/NetworkDriver.DeleteNetwork', methods=['POST']) |
|
40 |
def DeleteNetwork(): |
|
41 |
network = NetworkDeleteEntity(**flask.request.get_json(force=True)) |
|
42 |
del networks[network.NetworkID] |
|
43 |
return {} |
|
44 |
|
|
45 |
|
|
46 |
@app.route('/NetworkDriver.CreateEndpoint', methods=['POST']) |
|
47 |
def CreateEndpoint(): |
|
48 |
endpoint = EndpointCreateEntity(**flask.request.get_json(force=True)) |
|
49 |
|
|
50 |
endpoints['{}-{}'.format(endpoint.NetworkID, endpoint.EndpointID)] = endpoint |
|
51 |
return { |
|
52 |
'Interface': { |
|
53 |
} |
|
54 |
} |
|
55 |
|
|
56 |
|
|
57 |
@app.route('/NetworkDriver.EndpointOperInfo', methods=['POST']) |
|
58 |
def EndpointOperInfo(): |
|
59 |
endpoint = EndpointOperInfoEntity(**flask.request.get_json(force=True)) |
|
60 |
return { |
|
61 |
'Value': { |
|
62 |
} |
|
63 |
} |
|
64 |
|
|
65 |
|
|
66 |
@app.route('/NetworkDriver.DeleteEndpoint', methods=['POST']) |
|
67 |
def DeleteEndpoint(): |
|
68 |
entity = EndpointDeleteEntity(**flask.request.get_json(force=True)) |
|
69 |
endpoint = endpoints['{}-{}'.format(entity.NetworkID, entity.EndpointID)] |
|
70 |
|
|
71 |
try: |
|
72 |
with pyroute2.IPRoute() as ip: |
|
73 |
iface = ip.link_lookup(ifname=endpoint.Interface.Peer)[0] |
|
74 |
if iface: |
|
75 |
ip.link('del', index=iface) |
|
76 |
del endpoint.Interface.Name |
|
77 |
del endpoint.Interface.Peer |
|
78 |
except AttributeError: |
|
79 |
pass |
|
80 |
|
|
81 |
del endpoints['{}-{}'.format(endpoint.NetworkID, endpoint.EndpointID)] |
|
82 |
return {} |
|
83 |
|
|
84 |
|
|
85 |
@app.route('/NetworkDriver.Join', methods=['POST']) |
|
86 |
def Join(): |
|
87 |
join = JoinEntity(**flask.request.get_json(force=True)) |
|
88 |
network = networks[join.NetworkID] |
|
89 |
endpoint = endpoints['{}-{}'.format(join.NetworkID, join.EndpointID)] |
|
90 |
|
|
91 |
ifname0 = 'veth{}'.format(genid()) |
|
92 |
ifname1 = 'veth{}'.format(genid()) |
|
93 |
with pyroute2.IPRoute() as ip: |
|
94 |
ip.link('add', ifname=ifname0, peer=ifname1, kind='veth') |
|
95 |
idx = ip.link_lookup(ifname=ifname0)[0] |
|
96 |
if endpoint.Interface.MacAddress: |
|
97 |
ip.link('set', index=idx, address=endpoint.Interface.MacAddress) |
|
98 |
ip.link('set', index=idx, state='up') |
|
99 |
if endpoint.Interface.Address: |
|
100 |
addr = ipaddress.ip_interface(endpoint.Interface.Address) |
|
101 |
ip.addr('add', index=idx, address=addr.ip.compressed, mask=addr.network.prefixlen) |
|
102 |
if endpoint.Interface.AddressIPv6: |
|
103 |
addr = ipaddress.ip_interface(endpoint.Interface.AddressIPv6) |
|
104 |
ip.addr('add', index=idx, address=addr.ip.compressed, mask=addr.network.prefixlen) |
|
105 |
endpoint.Interface.Name = ifname0 |
|
106 |
|
|
107 |
idx = ip.link_lookup(ifname=ifname1)[0] |
|
108 |
ip.link('set', index=idx, state='up') |
|
109 |
if 'parent' in network.Options: |
|
110 |
id_parent = ip.link_lookup(ifname=network.Options['parent'])[0] |
|
111 |
print(ip.link("set", index=idx, master=id_parent)) |
|
112 |
endpoint.Interface.Peer = ifname1 |
|
113 |
|
|
114 |
gw4 = None |
|
115 |
for net4 in network.IPv4: |
|
116 |
try: |
|
117 |
gw4 = ipaddress.ip_interface(net4.Gateway) |
|
118 |
break |
|
119 |
except: |
|
120 |
pass |
|
121 |
gw6 = None |
|
122 |
for net6 in network.IPv6: |
|
123 |
try: |
|
124 |
gw6 = ipaddress.ip_interface(net6.Gateway) |
|
125 |
break |
|
126 |
except: |
|
127 |
pass |
|
128 |
|
|
129 |
result = { |
|
130 |
'InterfaceName': { |
|
131 |
'SrcName': ifname0, |
|
132 |
'DstPrefix': 'eth', |
|
133 |
}, |
|
134 |
} |
|
135 |
if gw4 is not None: |
|
136 |
result['Gateway'] = gw4.ip.compressed |
|
137 |
if gw6 is not None: |
|
138 |
result['GatewayIPv6'] = gw6.ip.compressed |
|
139 |
return result |
|
140 |
|
|
141 |
|
|
142 |
@app.route('/NetworkDriver.Leave', methods=['POST']) |
|
143 |
def Leave(): |
|
144 |
leave = LeaveEntity(**flask.request.get_json(force=True)) |
|
145 |
endpoint = endpoints['{}-{}'.format(leave.NetworkID, leave.EndpointID)] |
|
146 |
|
|
147 |
try: |
|
148 |
with pyroute2.IPRoute() as ip: |
|
149 |
iface = ip.link_lookup(ifname=endpoint.Interface.Peer)[0] |
|
150 |
if iface: |
|
151 |
ip.link('del', index=iface) |
|
152 |
del endpoint.Interface.Name |
|
153 |
del endpoint.Interface.Peer |
|
154 |
except AttributeError: |
|
155 |
pass |
|
156 |
|
|
157 |
return {} |
|
158 |
|
|
159 |
|
|
160 |
@app.route('/NetworkDriver.DiscoverNew', methods=['POST']) |
|
161 |
def DiscoverNew(): |
|
162 |
entity = DiscoverNewEntity(**flask.request.get_json(force=True)) |
|
163 |
return {} |
|
164 |
|
|
165 |
|
|
166 |
@app.route('/NetworkDriver.DiscoverDelete', methods=['POST']) |
|
167 |
def DiscoverDelete(): |
|
168 |
entity = DiscoverDeleteEntity(**flask.request.get_json(force=True)) |
|
169 |
return {} |
|
170 |
|
|
171 |
|
|
172 |
@app.route('/NetworkDriver.ProgramExternalConnectivity', methods=['POST']) |
|
173 |
def ProgramExternalConnectivity(): |
|
174 |
entity = ProgramExternalConnectivityEntity(**flask.request.get_json(force=True)) |
|
175 |
return {} |
|
176 |
|
|
177 |
|
|
178 |
@app.route('/NetworkDriver.RevokeExternalConnectivity', methods=['POST']) |
|
179 |
def RevokeExternalConnectivity(): |
|
180 |
entity = RevokeExternalConnectivityEntity(**flask.request.get_json(force=True)) |
|
181 |
return {} |