blob: a253a1200f9eaece7120eca4d7418363259a83b9 [file] [log] [blame]
# 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 ipaddress
import random
from xossynchronizer.modelaccessor import NodeToSwitchPort, PortInterface, model_accessor
from xossynchronizer.model_policies.policy import Policy
from xosconfig import Config
from multistructlog import create_logger
from helpers import Helpers
log = create_logger(Config().get('logging'))
class ComputeNodePolicy(Policy):
model_name = "NodeToSwitchPort"
@staticmethod
def getLastAddress(network):
return str(network.network_address + network.num_addresses - 2) + "/" + str(network.prefixlen)
# return ipaddress.ip_interface(network.network_address + network.num_addresses - 2)
@staticmethod
def getPortCidrByIp(ip):
interface = ipaddress.ip_interface(ip)
network = ipaddress.ip_network(interface.network)
cidr = ComputeNodePolicy.getLastAddress(network)
return cidr
@staticmethod
def generateVlan(used_vlans):
availabel_tags = range(16, 4093)
valid_tags = list(set(availabel_tags) - set(used_vlans))
if len(valid_tags) == 0:
raise Exception("No VLANs left")
return random.choice(valid_tags)
@staticmethod
def getVlanByCidr(subnet):
# vlanUntagged is unique per subnet
same_subnet_ifaces = PortInterface.objects.filter(ips=str(subnet))
if len(same_subnet_ifaces) > 0:
return same_subnet_ifaces[0].vlanUntagged
else:
PortInterface.objects.all()
used_vlans = list(set([i.vlanUntagged for i in same_subnet_ifaces]))
log.info("MODEL_POLICY: used vlans", vlans=used_vlans, subnet=subnet)
return ComputeNodePolicy.generateVlan(used_vlans)
def handle_create(self, node_to_port):
return self.handle_update(node_to_port)
def handle_update(self, node_to_port):
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)
compute_node = node_to_port.node
cidr = ComputeNodePolicy.getPortCidrByIp(compute_node.dataPlaneIp)
# check if an interface already exists
try:
PortInterface.objects.get(
port_id=node_to_port.port.id,
name=compute_node.dataPlaneIntf,
ips=str(cidr)
)
except IndexError:
vlan = self.getVlanByCidr(cidr)
log.info("MODEL_POLICY: choosen vlan", vlan=vlan, cidr=cidr)
interface = PortInterface(
port_id=node_to_port.port.id,
name=compute_node.dataPlaneIntf,
ips=str(cidr),
vlanUntagged=vlan
)
interface.save()
# TODO if the model is updated I need to remove the old interface, how?
def handle_delete(self, node_to_port):
pass