blob: e5c080e28778d2b6ab4fb3458e2abdd25af0e313 [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 Bakerc808c672019-02-04 11:38:20 -080022from openstacksyncstep import OpenStackSyncStep
23from xossynchronizer.modelaccessor import *
24from xosconfig import Config
25from multistructlog import create_logger
26
27log = create_logger(Config().get('logging'))
Scott Bakerb63ea792016-08-11 10:24:48 -070028
29class SyncControllerNetworks(OpenStackSyncStep):
30 requested_interval = 0
31 provides=[Network]
Andy Bavier66f9f342018-04-12 16:16:03 -070032 observes=ControllerNetwork
Scott Bakerb63ea792016-08-11 10:24:48 -070033 playbook='sync_controller_networks.yaml'
34
35 def alloc_subnet(self, uuid):
36 # 16 bits only
37 uuid_masked = uuid & 0xffff
38 a = 10
39 b = uuid_masked >> 8
40 c = uuid_masked & 0xff
41 d = 0
42
43 cidr = '%d.%d.%d.%d/24'%(a,b,c,d)
44 return cidr
45
46 def alloc_gateway(self, subnet):
47 # given a CIDR, allocate a default gateway using the .1 address within
48 # the subnet.
49 # 10.123.0.0/24 --> 10.123.0.1
50 # 207.141.192.128/28 --> 207.141.192.129
51 (network, bits) = subnet.split("/")
52 network=network.strip()
53 bits=int(bits.strip())
54 netmask = (~(pow(2,32-bits)-1) & 0xFFFFFFFF)
55 ip = struct.unpack("!L", socket.inet_aton(network))[0]
56 ip = ip & netmask | 1
57 return socket.inet_ntoa(struct.pack("!L", ip))
58
Scott Baker11cb69f2016-08-25 16:17:52 -070059 def get_segmentation_id(self, controller_network):
Scott Baker7bd1cd42016-08-29 15:30:45 -070060 driver = self.driver.admin_driver(controller = controller_network.controller)
Scott Baker11cb69f2016-08-25 16:17:52 -070061 neutron_network = driver.shell.neutron.list_networks(controller_network.network_id)["networks"][0]
Sapan Bhatia259205e2017-01-24 19:32:59 +010062 if "provider:segmentation_id" in neutron_network:
Scott Baker11cb69f2016-08-25 16:17:52 -070063 return neutron_network["provider:segmentation_id"]
64 else:
65 return None
66
Scott Bakerb63ea792016-08-11 10:24:48 -070067 def save_controller_network(self, controller_network):
68 network_name = controller_network.network.name
69 subnet_name = '%s-%d'%(network_name,controller_network.pk)
70 if controller_network.subnet and controller_network.subnet.strip():
71 # If a subnet is already specified (pass in by the creator), then
72 # use that rather than auto-generating one.
73 cidr = controller_network.subnet.strip()
74 print "CIDR_MS", cidr
75 else:
76 cidr = self.alloc_subnet(controller_network.pk)
77 print "CIDR_AMS", cidr
78
79 if controller_network.network.start_ip and controller_network.network.start_ip.strip():
80 start_ip = controller_network.network.start_ip.strip()
81 else:
82 start_ip = None
83
84 if controller_network.network.end_ip and controller_network.network.end_ip.strip():
85 end_ip = controller_network.network.end_ip.strip()
86 else:
87 end_ip = None
88
Scott Bakerb63ea792016-08-11 10:24:48 -070089 slice = controller_network.network.owner
Scott Baker5defb352017-11-29 15:09:38 -080090 controller_network.subnet = cidr
Scott Bakerb63ea792016-08-11 10:24:48 -070091
Scott Baker11cb69f2016-08-25 16:17:52 -070092 controller_network.gateway = self.alloc_gateway(cidr)
93
Scott Bakere7fe17d2018-07-06 10:18:50 -070094 network_fields = {
Scott Bakerb63ea792016-08-11 10:24:48 -070095 'name':network_name,
96 'subnet_name':subnet_name,
97 'ansible_tag':'%s-%s@%s'%(network_name,slice.slicename,controller_network.controller.name),
98 'cidr':cidr,
Scott Baker11cb69f2016-08-25 16:17:52 -070099 'gateway': controller_network.gateway,
Scott Bakerb63ea792016-08-11 10:24:48 -0700100 'start_ip':start_ip,
101 'end_ip':end_ip,
Matteo Scandoloceccb1f2017-06-05 10:35:44 -0700102 'use_vtn':True,
Scott Bakerb63ea792016-08-11 10:24:48 -0700103 'delete':False
104 }
Scott Bakere7fe17d2018-07-06 10:18:50 -0700105
106 if slice.trust_domain is not None:
107 # New Openstack modeling
108 # TODO(smbaker): Should use slice credentials rather than admin credentials
109 os_service = slice.trust_domain.owner.leaf_model
110 network_fields["endpoint"] = os_service.auth_url
111 network_fields["admin_user"] = os_service.admin_user
112 network_fields["admin_password"] = os_service.admin_password
113 network_fields["admin_project"] = "admin"
114 network_fields["domain"] = "Default"
115 else:
116 # Old OpenStack modeling
117 network_fields['endpoint'] = controller_network.controller.auth_url
118 network_fields['admin_user'] = slice.creator.email
119 network_fields['admin_password'] = slice.creator.remote_password
120 network_fields['admin_project'] = slice.name
121 network_fields['domain'] = controller_network.controller.domain
122
Scott Bakerb63ea792016-08-11 10:24:48 -0700123 return network_fields
124
125 def map_sync_outputs(self, controller_network,res):
126 network_id = res[0]['network']['id']
127 subnet_id = res[1]['subnet']['id']
128 controller_network.net_id = network_id
Scott Bakerb63ea792016-08-11 10:24:48 -0700129 controller_network.subnet_id = subnet_id
Scott Bakere7fe17d2018-07-06 10:18:50 -0700130 controller_network.backend_status = 'OK'
131 controller_network.backend_code = 1
Scott Baker11cb69f2016-08-25 16:17:52 -0700132 if not controller_network.segmentation_id:
Scott Baker75bae452017-03-27 20:10:58 -0700133 controller_network.segmentation_id = str(self.get_segmentation_id(controller_network))
Scott Bakerb63ea792016-08-11 10:24:48 -0700134 controller_network.save()
135
136
137 def map_sync_inputs(self, controller_network):
Scott Baker3de3d582016-09-09 15:26:43 -0700138 # make sure to not sync a shared network
Scott Bakerb63ea792016-08-11 10:24:48 -0700139 if (controller_network.network.template.shared_network_name or controller_network.network.template.shared_network_id):
140 return SyncStep.SYNC_WITHOUT_RUNNING
Scott Baker3de3d582016-09-09 15:26:43 -0700141
Scott Bakerb63ea792016-08-11 10:24:48 -0700142 if not controller_network.controller.admin_user:
Scott Bakerc808c672019-02-04 11:38:20 -0800143 log.info("controller %r has no admin_user, skipping" % controller_network.controller)
Scott Bakerb63ea792016-08-11 10:24:48 -0700144 return
145
146 if controller_network.network.owner and controller_network.network.owner.creator:
Scott Bakere7fe17d2018-07-06 10:18:50 -0700147 return self.save_controller_network(controller_network)
Scott Bakerb63ea792016-08-11 10:24:48 -0700148 else:
149 raise Exception('Could not save network controller %s'%controller_network)
150
151 def map_delete_inputs(self, controller_network):
Scott Baker3de3d582016-09-09 15:26:43 -0700152 # make sure to not delete a shared network
153 if (controller_network.network.template.shared_network_name or controller_network.network.template.shared_network_id):
Scott Bakerb63ea792016-08-11 10:24:48 -0700154 return
Scott Baker3de3d582016-09-09 15:26:43 -0700155
Scott Bakere7fe17d2018-07-06 10:18:50 -0700156 try:
157 slice = controller_network.network.owner # XXX: FIXME!!
Scott Bakerb63ea792016-08-11 10:24:48 -0700158 except:
Scott Bakere7fe17d2018-07-06 10:18:50 -0700159 raise Exception('Could not get slice for Network %s'%controller_network.network.name)
Scott Bakerb63ea792016-08-11 10:24:48 -0700160
Scott Bakere7fe17d2018-07-06 10:18:50 -0700161 network_name = controller_network.network.name
Scott Bakerb63ea792016-08-11 10:24:48 -0700162 subnet_name = '%s-%d'%(network_name,controller_network.pk)
Scott Bakere7fe17d2018-07-06 10:18:50 -0700163 cidr = controller_network.subnet
164 network_fields = {
Scott Bakerb63ea792016-08-11 10:24:48 -0700165 'name':network_name,
166 'subnet_name':subnet_name,
167 'ansible_tag':'%s-%s@%s'%(network_name,slice.slicename,controller_network.controller.name),
168 'cidr':cidr,
Scott Bakere7fe17d2018-07-06 10:18:50 -0700169 'delete':True
Scott Bakerb63ea792016-08-11 10:24:48 -0700170 }
171
Scott Bakere7fe17d2018-07-06 10:18:50 -0700172 if slice.trust_domain is not None:
173 # New Openstack modeling
174 # TODO(smbaker): Should use slice credentials rather than admin credentials
175 os_service = slice.trust_domain.owner.leaf_model
176 network_fields["endpoint"] = os_service.auth_url
177 network_fields["admin_user"] = os_service.admin_user
178 network_fields["admin_password"] = os_service.admin_password
179 network_fields["admin_project"] = "admin"
180 network_fields["domain"] = "Default"
181 else:
182 # Old OpenStack modeling
183 network_fields['endpoint'] = controller_network.controller.auth_url
184 network_fields['admin_user'] = slice.creator.email
185 network_fields['admin_password'] = slice.creator.remote_password
186 network_fields['admin_project'] = slice.name
187 network_fields['domain'] = controller_network.controller.domain
188
Scott Bakerb63ea792016-08-11 10:24:48 -0700189 return network_fields
190