blob: d33962a306c951932059bf28ca36ffa9c14a6190 [file] [log] [blame]
Matteo Scandolof0441032017-08-08 13:05:26 -07001
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
Scott Bakerb63ea792016-08-11 10:24:48 -070017import os
18import base64
19import struct
20import socket
Scott Bakerb63ea792016-08-11 10:24:48 -070021from netaddr import IPAddress, IPNetwork
Scott Baker8b75e852016-08-16 15:04:59 -070022from synchronizers.openstack.openstacksyncstep import OpenStackSyncStep
Scott Bakeraf599eb2017-03-21 12:43:26 -070023from synchronizers.new_base.syncstep import *
Scott Bakerb63ea792016-08-11 10:24:48 -070024from xos.logger import observer_logger as logger
Scott Bakeraf599eb2017-03-21 12:43:26 -070025from synchronizers.new_base.ansible_helper import *
Scott Bakeraf599eb2017-03-21 12:43:26 -070026from synchronizers.new_base.modelaccessor import *
Scott Bakerb63ea792016-08-11 10:24:48 -070027
28class SyncControllerNetworks(OpenStackSyncStep):
29 requested_interval = 0
30 provides=[Network]
Andy Bavier66f9f342018-04-12 16:16:03 -070031 observes=ControllerNetwork
Scott Bakerb63ea792016-08-11 10:24:48 -070032 playbook='sync_controller_networks.yaml'
33
34 def alloc_subnet(self, uuid):
35 # 16 bits only
36 uuid_masked = uuid & 0xffff
37 a = 10
38 b = uuid_masked >> 8
39 c = uuid_masked & 0xff
40 d = 0
41
42 cidr = '%d.%d.%d.%d/24'%(a,b,c,d)
43 return cidr
44
45 def alloc_gateway(self, subnet):
46 # given a CIDR, allocate a default gateway using the .1 address within
47 # the subnet.
48 # 10.123.0.0/24 --> 10.123.0.1
49 # 207.141.192.128/28 --> 207.141.192.129
50 (network, bits) = subnet.split("/")
51 network=network.strip()
52 bits=int(bits.strip())
53 netmask = (~(pow(2,32-bits)-1) & 0xFFFFFFFF)
54 ip = struct.unpack("!L", socket.inet_aton(network))[0]
55 ip = ip & netmask | 1
56 return socket.inet_ntoa(struct.pack("!L", ip))
57
Scott Baker11cb69f2016-08-25 16:17:52 -070058 def get_segmentation_id(self, controller_network):
Scott Baker7bd1cd42016-08-29 15:30:45 -070059 driver = self.driver.admin_driver(controller = controller_network.controller)
Scott Baker11cb69f2016-08-25 16:17:52 -070060 neutron_network = driver.shell.neutron.list_networks(controller_network.network_id)["networks"][0]
Sapan Bhatia259205e2017-01-24 19:32:59 +010061 if "provider:segmentation_id" in neutron_network:
Scott Baker11cb69f2016-08-25 16:17:52 -070062 return neutron_network["provider:segmentation_id"]
63 else:
64 return None
65
Scott Bakerb63ea792016-08-11 10:24:48 -070066 def save_controller_network(self, controller_network):
67 network_name = controller_network.network.name
68 subnet_name = '%s-%d'%(network_name,controller_network.pk)
69 if controller_network.subnet and controller_network.subnet.strip():
70 # If a subnet is already specified (pass in by the creator), then
71 # use that rather than auto-generating one.
72 cidr = controller_network.subnet.strip()
73 print "CIDR_MS", cidr
74 else:
75 cidr = self.alloc_subnet(controller_network.pk)
76 print "CIDR_AMS", cidr
77
78 if controller_network.network.start_ip and controller_network.network.start_ip.strip():
79 start_ip = controller_network.network.start_ip.strip()
80 else:
81 start_ip = None
82
83 if controller_network.network.end_ip and controller_network.network.end_ip.strip():
84 end_ip = controller_network.network.end_ip.strip()
85 else:
86 end_ip = None
87
Scott Bakerb63ea792016-08-11 10:24:48 -070088 slice = controller_network.network.owner
Scott Baker5defb352017-11-29 15:09:38 -080089 controller_network.subnet = cidr
Scott Bakerb63ea792016-08-11 10:24:48 -070090
Scott Baker11cb69f2016-08-25 16:17:52 -070091 controller_network.gateway = self.alloc_gateway(cidr)
92
Scott Bakere7fe17d2018-07-06 10:18:50 -070093 network_fields = {
Scott Bakerb63ea792016-08-11 10:24:48 -070094 'name':network_name,
95 'subnet_name':subnet_name,
96 'ansible_tag':'%s-%s@%s'%(network_name,slice.slicename,controller_network.controller.name),
97 'cidr':cidr,
Scott Baker11cb69f2016-08-25 16:17:52 -070098 'gateway': controller_network.gateway,
Scott Bakerb63ea792016-08-11 10:24:48 -070099 'start_ip':start_ip,
100 'end_ip':end_ip,
Matteo Scandoloceccb1f2017-06-05 10:35:44 -0700101 'use_vtn':True,
Scott Bakerb63ea792016-08-11 10:24:48 -0700102 'delete':False
103 }
Scott Bakere7fe17d2018-07-06 10:18:50 -0700104
105 if slice.trust_domain is not None:
106 # New Openstack modeling
107 # TODO(smbaker): Should use slice credentials rather than admin credentials
108 os_service = slice.trust_domain.owner.leaf_model
109 network_fields["endpoint"] = os_service.auth_url
110 network_fields["admin_user"] = os_service.admin_user
111 network_fields["admin_password"] = os_service.admin_password
112 network_fields["admin_project"] = "admin"
113 network_fields["domain"] = "Default"
114 else:
115 # Old OpenStack modeling
116 network_fields['endpoint'] = controller_network.controller.auth_url
117 network_fields['admin_user'] = slice.creator.email
118 network_fields['admin_password'] = slice.creator.remote_password
119 network_fields['admin_project'] = slice.name
120 network_fields['domain'] = controller_network.controller.domain
121
Scott Bakerb63ea792016-08-11 10:24:48 -0700122 return network_fields
123
124 def map_sync_outputs(self, controller_network,res):
125 network_id = res[0]['network']['id']
126 subnet_id = res[1]['subnet']['id']
127 controller_network.net_id = network_id
Scott Bakerb63ea792016-08-11 10:24:48 -0700128 controller_network.subnet_id = subnet_id
Scott Bakere7fe17d2018-07-06 10:18:50 -0700129 controller_network.backend_status = 'OK'
130 controller_network.backend_code = 1
Scott Baker11cb69f2016-08-25 16:17:52 -0700131 if not controller_network.segmentation_id:
Scott Baker75bae452017-03-27 20:10:58 -0700132 controller_network.segmentation_id = str(self.get_segmentation_id(controller_network))
Scott Bakerb63ea792016-08-11 10:24:48 -0700133 controller_network.save()
134
135
136 def map_sync_inputs(self, controller_network):
Scott Baker3de3d582016-09-09 15:26:43 -0700137 # make sure to not sync a shared network
Scott Bakerb63ea792016-08-11 10:24:48 -0700138 if (controller_network.network.template.shared_network_name or controller_network.network.template.shared_network_id):
139 return SyncStep.SYNC_WITHOUT_RUNNING
Scott Baker3de3d582016-09-09 15:26:43 -0700140
Scott Bakerb63ea792016-08-11 10:24:48 -0700141 if not controller_network.controller.admin_user:
142 logger.info("controller %r has no admin_user, skipping" % controller_network.controller)
143 return
144
145 if controller_network.network.owner and controller_network.network.owner.creator:
Scott Bakere7fe17d2018-07-06 10:18:50 -0700146 return self.save_controller_network(controller_network)
Scott Bakerb63ea792016-08-11 10:24:48 -0700147 else:
148 raise Exception('Could not save network controller %s'%controller_network)
149
150 def map_delete_inputs(self, controller_network):
Scott Baker3de3d582016-09-09 15:26:43 -0700151 # make sure to not delete a shared network
152 if (controller_network.network.template.shared_network_name or controller_network.network.template.shared_network_id):
Scott Bakerb63ea792016-08-11 10:24:48 -0700153 return
Scott Baker3de3d582016-09-09 15:26:43 -0700154
Scott Bakere7fe17d2018-07-06 10:18:50 -0700155 try:
156 slice = controller_network.network.owner # XXX: FIXME!!
Scott Bakerb63ea792016-08-11 10:24:48 -0700157 except:
Scott Bakere7fe17d2018-07-06 10:18:50 -0700158 raise Exception('Could not get slice for Network %s'%controller_network.network.name)
Scott Bakerb63ea792016-08-11 10:24:48 -0700159
Scott Bakere7fe17d2018-07-06 10:18:50 -0700160 network_name = controller_network.network.name
Scott Bakerb63ea792016-08-11 10:24:48 -0700161 subnet_name = '%s-%d'%(network_name,controller_network.pk)
Scott Bakere7fe17d2018-07-06 10:18:50 -0700162 cidr = controller_network.subnet
163 network_fields = {
Scott Bakerb63ea792016-08-11 10:24:48 -0700164 'name':network_name,
165 'subnet_name':subnet_name,
166 'ansible_tag':'%s-%s@%s'%(network_name,slice.slicename,controller_network.controller.name),
167 'cidr':cidr,
Scott Bakere7fe17d2018-07-06 10:18:50 -0700168 'delete':True
Scott Bakerb63ea792016-08-11 10:24:48 -0700169 }
170
Scott Bakere7fe17d2018-07-06 10:18:50 -0700171 if slice.trust_domain is not None:
172 # New Openstack modeling
173 # TODO(smbaker): Should use slice credentials rather than admin credentials
174 os_service = slice.trust_domain.owner.leaf_model
175 network_fields["endpoint"] = os_service.auth_url
176 network_fields["admin_user"] = os_service.admin_user
177 network_fields["admin_password"] = os_service.admin_password
178 network_fields["admin_project"] = "admin"
179 network_fields["domain"] = "Default"
180 else:
181 # Old OpenStack modeling
182 network_fields['endpoint'] = controller_network.controller.auth_url
183 network_fields['admin_user'] = slice.creator.email
184 network_fields['admin_password'] = slice.creator.remote_password
185 network_fields['admin_project'] = slice.name
186 network_fields['domain'] = controller_network.controller.domain
187
Scott Bakerb63ea792016-08-11 10:24:48 -0700188 return network_fields
189