blob: 14044af93865bf0eb809058219af85811c0cf7ba [file] [log] [blame]
Matteo Scandoloaf3c9942018-06-27 14:03:12 -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
Scott Bakere9855012019-04-01 15:01:34 -070016from __future__ import absolute_import
17
Matteo Scandoloaf3c9942018-06-27 14:03:12 -070018import ipaddress
19import random
Scott Baker382366d2019-02-04 10:58:43 -080020from xossynchronizer.modelaccessor import NodeToSwitchPort, PortInterface, model_accessor
21from xossynchronizer.model_policies.policy import Policy
Matteo Scandoloaf3c9942018-06-27 14:03:12 -070022
23from xosconfig import Config
24from multistructlog import create_logger
25
Matteo Scandoloaf3c9942018-06-27 14:03:12 -070026log = create_logger(Config().get('logging'))
27
Scott Bakere9855012019-04-01 15:01:34 -070028
Matteo Scandoloaf3c9942018-06-27 14:03:12 -070029class ComputeNodePolicy(Policy):
30 model_name = "NodeToSwitchPort"
31
32 @staticmethod
33 def getLastAddress(network):
34 return str(network.network_address + network.num_addresses - 2) + "/" + str(network.prefixlen)
35 # return ipaddress.ip_interface(network.network_address + network.num_addresses - 2)
36
37 @staticmethod
38 def getPortCidrByIp(ip):
39 interface = ipaddress.ip_interface(ip)
40 network = ipaddress.ip_network(interface.network)
41 cidr = ComputeNodePolicy.getLastAddress(network)
42 return cidr
43
44 @staticmethod
45 def generateVlan(used_vlans):
Scott Bakere9855012019-04-01 15:01:34 -070046 availabel_tags = list(range(16, 4093))
Matteo Scandoloaf3c9942018-06-27 14:03:12 -070047 valid_tags = list(set(availabel_tags) - set(used_vlans))
48 if len(valid_tags) == 0:
49 raise Exception("No VLANs left")
50 return random.choice(valid_tags)
51
52 @staticmethod
53 def getVlanByCidr(subnet):
54 # vlanUntagged is unique per subnet
55 same_subnet_ifaces = PortInterface.objects.filter(ips=str(subnet))
56
57 if len(same_subnet_ifaces) > 0:
58 return same_subnet_ifaces[0].vlanUntagged
59 else:
60 PortInterface.objects.all()
61 used_vlans = list(set([i.vlanUntagged for i in same_subnet_ifaces]))
62 log.info("MODEL_POLICY: used vlans", vlans=used_vlans, subnet=subnet)
63 return ComputeNodePolicy.generateVlan(used_vlans)
64
65 def handle_create(self, node_to_port):
66 return self.handle_update(node_to_port)
67
68 def handle_update(self, node_to_port):
Scott Bakere9855012019-04-01 15:01:34 -070069 log.info(
70 "MODEL_POLICY: NodeToSwitchPort %s handle update" %
71 node_to_port.id,
72 node=node_to_port.node,
73 port=node_to_port.port,
74 switch=node_to_port.port.switch)
Matteo Scandoloaf3c9942018-06-27 14:03:12 -070075
76 compute_node = node_to_port.node
77
78 cidr = ComputeNodePolicy.getPortCidrByIp(compute_node.dataPlaneIp)
79
80 # check if an interface already exists
81 try:
82 PortInterface.objects.get(
83 port_id=node_to_port.port.id,
84 name=compute_node.dataPlaneIntf,
85 ips=str(cidr)
86 )
87 except IndexError:
88
89 vlan = self.getVlanByCidr(cidr)
90
91 log.info("MODEL_POLICY: choosen vlan", vlan=vlan, cidr=cidr)
92
93 interface = PortInterface(
94 port_id=node_to_port.port.id,
95 name=compute_node.dataPlaneIntf,
96 ips=str(cidr),
97 vlanUntagged=vlan
98 )
99
100 interface.save()
Matteo Scandoloaf3c9942018-06-27 14:03:12 -0700101
Scott Bakere9855012019-04-01 15:01:34 -0700102 # TODO if the model is updated I need to remove the old interface, how?
Matteo Scandoloaf3c9942018-06-27 14:03:12 -0700103
104 def handle_delete(self, node_to_port):
105 pass