blob: 87bbe45975227108fca19b8e05db0f161c281726 [file] [log] [blame]
boyoungf42f2bf2017-10-16 19:06:30 +09001
2# Copyright 2017-present Open Networking Foundation
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16
17import os
18import base64
19import struct
20import socket
21from netaddr import IPAddress, IPNetwork
22from synchronizers.swarm.swarmsyncstep import SwarmSyncStep
23from synchronizers.new_base.syncstep import *
24from xos.logger import observer_logger as logger
25from synchronizers.new_base.ansible_helper import *
26from synchronizers.new_base.modelaccessor import *
27
28import synchronizers.swarm.swarmlog as slog
29
30
31class SyncControllerNetworks(SwarmSyncStep):
32 requested_interval = 0
33 provides=[Network]
34 observes=ControllerNetwork
35 playbook='sync_controller_networks.yaml'
36
37 def alloc_subnet(self, uuid):
38 slog.debug("uuid: %s" % str(uuid))
39 # use 16 bits only
40 uuid_masked = uuid & 0xffff
41 a = 10
42 b = uuid_masked >> 8
43 c = uuid_masked & 0xff
44 d = 0
45
46 cidr = '%d.%d.%d.%d/24'%(a,b,c,d)
47 slog.debug("subnet cidr: %s" % str(cidr))
48
49 return cidr
50
51 def alloc_gateway(self, subnet):
52 # given a CIDR, allocate a default gateway using the .1 address within the subnet.
53 # 10.123.0.0/24 --> 10.123.0.1
54 # 207.141.192.128/28 --> 207.141.192.129
55 (network, bits) = subnet.split("/")
56 network=network.strip()
57 bits=int(bits.strip())
58 netmask = (~(pow(2,32-bits)-1) & 0xFFFFFFFF)
59 ip = struct.unpack("!L", socket.inet_aton(network))[0]
60 ip = ip & netmask | 1
61 slog.debug("subnet: %s gateway: %s" % (subnet,ip))
62 return socket.inet_ntoa(struct.pack("!L", ip))
63
64 def chk_net_exist(self, controller_network, swarm_manager_address):
65 duplicated_flag = False
66 try:
67 slog.debug("network_name to check: %s" % controller_network.network.name)
68
69 import docker
70 docker_api_base_url = "tcp://%s:4243" % swarm_manager_address
71 slog.info("Docker API Base URL: %s" % docker_api_base_url)
72 my_client = docker.DockerClient(base_url=docker_api_base_url)
73 net = my_client.networks.get(controller_network.network.name)
74 slog.debug("network.id : %s" % net.id)
75 slog.debug("network.name : %s" % net.name)
76 slog.debug("network.attrs[IPAM][Config] : %s" % net.attrs['IPAM']['Config'])
77 slog.debug("network.attrs : %s" % net.attrs)
78 except Exception as ex:
79 slog.info("Exception: %s" % str(ex.args))
80 slog.info("Exception: %s" % str(ex))
81 duplicated_flag = False # There is no same network.
82 else:
83 duplicated_flag = True # There is same network.
84 slog.debug("network duplicated_flag: %s" % duplicated_flag)
85 return duplicated_flag
86
87 def save_controller_network(self, controller_network):
88 network_name = controller_network.network.name
89 if controller_network.subnet and controller_network.subnet.strip():
90 # If a subnet is already specified (pass in by the creator), then
91 # use that rather than auto-generating one.
92 cidr = controller_network.subnet.strip()
93 slog.info("subnet CIDR : %s" % cidr)
94 else:
95 cidr = self.alloc_subnet(controller_network.pk)
96 slog.info("subnet CIDR (Auto generated by XOS): %s" % cidr)
97
98 if controller_network.network.start_ip and controller_network.network.start_ip.strip():
99 start_ip = controller_network.network.start_ip.strip()
100 controller_network.gateway = start_ip
101 else:
102 start_ip = None
103 controller_network.gateway = self.alloc_gateway(cidr)
104
105 if controller_network.network.end_ip and controller_network.network.end_ip.strip():
106 end_ip = controller_network.network.end_ip.strip()
107 else:
108 end_ip = None
109 slog.info("Start IP Address: %s End IP Address: %s" % (start_ip, end_ip))
110
111 self.cidr=cidr
112 slice = controller_network.network.owner
113
114 # "overlay" is default network driver for swarm
115 opt_driver = "--driver=overlay"
116 opt_ipam_driver = " "
117 opt_ipam_neutron_opt = " "
118 if controller_network.network.template.shared_network_name is not None:
119 if controller_network.network.template.shared_network_name.__contains__("kuryr"):
120 # update network driver for swarm
121 opt_driver = "--driver=%s" % controller_network.network.template.shared_network_name
122 opt_ipam_driver = "--ipam-driver=%s" % controller_network.network.template.shared_network_name
123 opt_ipam_neutron_opt = "--ipam-opt=neutron.pool.uuid=%s -o neutron.pool.uuid=%s -o neutron.net.name=%s" % (
124 controller_network.network.labels,
125 controller_network.network.labels,
126 controller_network.network.name)
127
128 swarm_manager_url = controller_network.controller.auth_url
129 (swarm_manager_address, docker_registry_port) = swarm_manager_url.split(':')
130 slog.info("swarm_manager_address: %s docker_registry_port: %s"
131 % (swarm_manager_address, docker_registry_port))
132
133 # check if this controller network is created already on swarm cluster.
134 duplicated_flag = self.chk_net_exist(controller_network, swarm_manager_address)
135
136 network_fields = {
137 'swarm_manager_address' : swarm_manager_address,
138 'network_name' : network_name,
139 'ansible_tag' : '%s-%s@%s' % (
140 network_name,
141 slice.slicename,
142 controller_network.controller.name),
143 'opt_driver' : opt_driver,
144 'opt_ipam_driver' : opt_ipam_driver,
145 'opt_ipam_neutron_opt' : opt_ipam_neutron_opt,
146 'opt_subnet' : "--subnet=%s" % cidr,
147 'opt_gateway' : "--gateway=%s" % controller_network.gateway,
148 'start_ip' : start_ip,
149 'end_ip' : end_ip,
150 'duplicated' : duplicated_flag,
151 'delete' : False
152 }
153 slog.info("network_fields: %s" % network_fields)
154 return network_fields
155
156 def map_sync_inputs(self, controller_network):
157 slog.debug("controller_network.subnet: %s" % controller_network.subnet)
158 slog.debug("controller_network.network.name: %s" % controller_network.network.name)
159 if controller_network.network.owner and controller_network.network.owner.creator:
160 return self.save_controller_network(controller_network)
161 else:
162 slog.info("I could not create network controller information %s" % controller_network)
163 raise Exception('I could not create network controller %s'%controller_network)
164
165 def map_sync_outputs(self, controller_network, res):
166 slog.debug("ansible playbook ressult: %s" % str(res))
167 slog.debug("ansible playbook ressult[1][stdout]: %s" % str(res[1]['stdout']))
168
169 res_stdout = res[1]['stdout']
170 json_content = json.loads(res_stdout)
171 slog.debug("json_content: %s" % str(json_content))
172 network_id = json_content[0]['Id']
173 slog.debug("network_id: %s" % str(network_id))
174 subnet_id = "%s-subnet-%s" % (network_id, self.cidr)
175 slog.debug("subnet_id: %s" % str(subnet_id))
176
177 controller_network.net_id = network_id
178 controller_network.subnet = self.cidr
179 controller_network.subnet_id = subnet_id
180 controller_network.backend_status = '1 - OK'
181 controller_network.save()
182
183 def map_delete_inputs(self, controller_network):
184 # make sure to not delete a shared network
185 swarm_manager_url = controller_network.controller.auth_url
186 (swarm_manager_address, docker_registry_port) = swarm_manager_url.split(':')
187 slog.info("swarm_manager_address: %s docker_registry_port: %s"
188 % (swarm_manager_address, docker_registry_port))
189
190 try:
191 slice = controller_network.network.owner
192 except:
193 raise Exception('Could not get slice for Network %s' % controller_network.network.name)
194
195 network_name = controller_network.network.name
196 cidr = controller_network.subnet
197 network_fields = {
198 'swarm_manager_address' : swarm_manager_address,
199 'network_name' :network_name,
200 'ansible_tag' :'%s-%s@%s'%(
201 network_name,
202 slice.slicename,
203 controller_network.controller.name),
204 'delete':True
205 }
206 return network_fields