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