| |
| # Copyright 2017-present Open Networking Foundation |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| |
| import os |
| import base64 |
| import struct |
| import socket |
| from netaddr import IPAddress, IPNetwork |
| from synchronizers.swarm.swarmsyncstep import SwarmSyncStep |
| from synchronizers.new_base.syncstep import * |
| from xos.logger import observer_logger as logger |
| from synchronizers.new_base.ansible_helper import * |
| from synchronizers.new_base.modelaccessor import * |
| |
| import synchronizers.swarm.swarmlog as slog |
| |
| |
| class SyncControllerNetworks(SwarmSyncStep): |
| requested_interval = 0 |
| provides=[Network] |
| observes=ControllerNetwork |
| playbook='sync_controller_networks.yaml' |
| |
| def alloc_subnet(self, uuid): |
| slog.debug("uuid: %s" % str(uuid)) |
| # use 16 bits only |
| uuid_masked = uuid & 0xffff |
| a = 10 |
| b = uuid_masked >> 8 |
| c = uuid_masked & 0xff |
| d = 0 |
| |
| cidr = '%d.%d.%d.%d/24'%(a,b,c,d) |
| slog.debug("subnet cidr: %s" % str(cidr)) |
| |
| return cidr |
| |
| def alloc_gateway(self, subnet): |
| # given a CIDR, allocate a default gateway using the .1 address within the subnet. |
| # 10.123.0.0/24 --> 10.123.0.1 |
| # 207.141.192.128/28 --> 207.141.192.129 |
| (network, bits) = subnet.split("/") |
| network=network.strip() |
| bits=int(bits.strip()) |
| netmask = (~(pow(2,32-bits)-1) & 0xFFFFFFFF) |
| ip = struct.unpack("!L", socket.inet_aton(network))[0] |
| ip = ip & netmask | 1 |
| slog.debug("subnet: %s gateway: %s" % (subnet,ip)) |
| return socket.inet_ntoa(struct.pack("!L", ip)) |
| |
| def chk_net_exist(self, controller_network, swarm_manager_address): |
| duplicated_flag = False |
| try: |
| slog.debug("network_name to check: %s" % controller_network.network.name) |
| |
| import docker |
| docker_api_base_url = "tcp://%s:4243" % swarm_manager_address |
| slog.info("Docker API Base URL: %s" % docker_api_base_url) |
| my_client = docker.DockerClient(base_url=docker_api_base_url) |
| net = my_client.networks.get(controller_network.network.name) |
| slog.debug("network.id : %s" % net.id) |
| slog.debug("network.name : %s" % net.name) |
| slog.debug("network.attrs[IPAM][Config] : %s" % net.attrs['IPAM']['Config']) |
| slog.debug("network.attrs : %s" % net.attrs) |
| except Exception as ex: |
| slog.info("Exception: %s" % str(ex.args)) |
| slog.info("Exception: %s" % str(ex)) |
| duplicated_flag = False # There is no same network. |
| else: |
| duplicated_flag = True # There is same network. |
| slog.debug("network duplicated_flag: %s" % duplicated_flag) |
| return duplicated_flag |
| |
| def save_controller_network(self, controller_network): |
| network_name = controller_network.network.name |
| if controller_network.subnet and controller_network.subnet.strip(): |
| # If a subnet is already specified (pass in by the creator), then |
| # use that rather than auto-generating one. |
| cidr = controller_network.subnet.strip() |
| slog.info("subnet CIDR : %s" % cidr) |
| else: |
| cidr = self.alloc_subnet(controller_network.pk) |
| slog.info("subnet CIDR (Auto generated by XOS): %s" % cidr) |
| |
| if controller_network.network.start_ip and controller_network.network.start_ip.strip(): |
| start_ip = controller_network.network.start_ip.strip() |
| controller_network.gateway = start_ip |
| else: |
| start_ip = None |
| controller_network.gateway = self.alloc_gateway(cidr) |
| |
| if controller_network.network.end_ip and controller_network.network.end_ip.strip(): |
| end_ip = controller_network.network.end_ip.strip() |
| else: |
| end_ip = None |
| slog.info("Start IP Address: %s End IP Address: %s" % (start_ip, end_ip)) |
| |
| self.cidr=cidr |
| slice = controller_network.network.owner |
| |
| # "overlay" is default network driver for swarm |
| opt_driver = "--driver=overlay" |
| opt_ipam_driver = " " |
| opt_ipam_neutron_opt = " " |
| if controller_network.network.template.shared_network_name is not None: |
| if controller_network.network.template.shared_network_name.__contains__("kuryr"): |
| # update network driver for swarm |
| opt_driver = "--driver=%s" % controller_network.network.template.shared_network_name |
| opt_ipam_driver = "--ipam-driver=%s" % controller_network.network.template.shared_network_name |
| opt_ipam_neutron_opt = "--ipam-opt=neutron.pool.uuid=%s -o neutron.pool.uuid=%s -o neutron.net.name=%s" % ( |
| controller_network.network.labels, |
| controller_network.network.labels, |
| controller_network.network.name) |
| |
| swarm_manager_url = controller_network.controller.auth_url |
| (swarm_manager_address, docker_registry_port) = swarm_manager_url.split(':') |
| slog.info("swarm_manager_address: %s docker_registry_port: %s" |
| % (swarm_manager_address, docker_registry_port)) |
| |
| # check if this controller network is created already on swarm cluster. |
| duplicated_flag = self.chk_net_exist(controller_network, swarm_manager_address) |
| |
| network_fields = { |
| 'swarm_manager_address' : swarm_manager_address, |
| 'network_name' : network_name, |
| 'ansible_tag' : '%s-%s@%s' % ( |
| network_name, |
| slice.slicename, |
| controller_network.controller.name), |
| 'opt_driver' : opt_driver, |
| 'opt_ipam_driver' : opt_ipam_driver, |
| 'opt_ipam_neutron_opt' : opt_ipam_neutron_opt, |
| 'opt_subnet' : "--subnet=%s" % cidr, |
| 'opt_gateway' : "--gateway=%s" % controller_network.gateway, |
| 'start_ip' : start_ip, |
| 'end_ip' : end_ip, |
| 'duplicated' : duplicated_flag, |
| 'delete' : False |
| } |
| slog.info("network_fields: %s" % network_fields) |
| return network_fields |
| |
| def map_sync_inputs(self, controller_network): |
| slog.debug("controller_network.subnet: %s" % controller_network.subnet) |
| slog.debug("controller_network.network.name: %s" % controller_network.network.name) |
| if controller_network.network.owner and controller_network.network.owner.creator: |
| return self.save_controller_network(controller_network) |
| else: |
| slog.info("I could not create network controller information %s" % controller_network) |
| raise Exception('I could not create network controller %s'%controller_network) |
| |
| def map_sync_outputs(self, controller_network, res): |
| slog.debug("ansible playbook ressult: %s" % str(res)) |
| slog.debug("ansible playbook ressult[1][stdout]: %s" % str(res[1]['stdout'])) |
| |
| res_stdout = res[1]['stdout'] |
| json_content = json.loads(res_stdout) |
| slog.debug("json_content: %s" % str(json_content)) |
| network_id = json_content[0]['Id'] |
| slog.debug("network_id: %s" % str(network_id)) |
| subnet_id = "%s-subnet-%s" % (network_id, self.cidr) |
| slog.debug("subnet_id: %s" % str(subnet_id)) |
| |
| controller_network.net_id = network_id |
| controller_network.subnet = self.cidr |
| controller_network.subnet_id = subnet_id |
| controller_network.backend_status = '1 - OK' |
| controller_network.save() |
| |
| def map_delete_inputs(self, controller_network): |
| # make sure to not delete a shared network |
| swarm_manager_url = controller_network.controller.auth_url |
| (swarm_manager_address, docker_registry_port) = swarm_manager_url.split(':') |
| slog.info("swarm_manager_address: %s docker_registry_port: %s" |
| % (swarm_manager_address, docker_registry_port)) |
| |
| try: |
| slice = controller_network.network.owner |
| except: |
| raise Exception('Could not get slice for Network %s' % controller_network.network.name) |
| |
| network_name = controller_network.network.name |
| cidr = controller_network.subnet |
| network_fields = { |
| 'swarm_manager_address' : swarm_manager_address, |
| 'network_name' :network_name, |
| 'ansible_tag' :'%s-%s@%s'%( |
| network_name, |
| slice.slicename, |
| controller_network.controller.name), |
| 'delete':True |
| } |
| return network_fields |