blob: e3e0265aed13b1028cff6a5d78abe915b2310772 [file] [log] [blame]
Luca Preteb601c382018-04-30 16:10:43 -07001# Copyright 2017-present Open Networking Foundation
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
Scott Bakere9855012019-04-01 15:01:34 -070015#from __future__ import absolute_import
16
Luca Preteb601c382018-04-30 16:10:43 -070017import requests
Matteo Scandolodb7adc32018-06-15 16:05:19 -070018import urllib
Luca Preteb601c382018-04-30 16:10:43 -070019from requests.auth import HTTPBasicAuth
Scott Baker91bf91b2019-03-15 16:13:51 -070020from xossynchronizer.steps.syncstep import SyncStep
21from xossynchronizer.modelaccessor import SwitchPort, PortInterface, FabricIpAddress, model_accessor
Luca Preteb601c382018-04-30 16:10:43 -070022
23from xosconfig import Config
24from multistructlog import create_logger
25
Matteo Scandolo04e5e122018-05-04 16:21:53 -070026from helpers import Helpers
27
Luca Preteb601c382018-04-30 16:10:43 -070028log = create_logger(Config().get('logging'))
29
30class SyncFabricPort(SyncStep):
31 provides = [SwitchPort]
Luca Prete15377872018-09-11 17:32:55 -070032 observes = [SwitchPort, PortInterface, FabricIpAddress]
Luca Preteb601c382018-04-30 16:10:43 -070033
Luca Preteb601c382018-04-30 16:10:43 -070034 def sync_record(self, model):
Matteo Scandolodb7adc32018-06-15 16:05:19 -070035
36 if model.leaf_model_name == "PortInterface":
Scott Baker91bf91b2019-03-15 16:13:51 -070037 log.info("Received update for PortInterface", port=model.port.portId, interface=model)
Matteo Scandolodb7adc32018-06-15 16:05:19 -070038 return self.sync_record(model.port)
39
Luca Prete15377872018-09-11 17:32:55 -070040 if model.leaf_model_name == "FabricIpAddress":
Scott Baker91bf91b2019-03-15 16:13:51 -070041 log.info("Received update for FabricIpAddress",
42 port=model.interface.port.portId,
43 interface=model.interface.name,
44 ip=model.ip)
Luca Prete15377872018-09-11 17:32:55 -070045 return self.sync_record(model.interface.port)
46
Matteo Scandolo6739b512018-05-30 18:55:29 -070047 log.info("Adding port %s/%s to onos-fabric" % (model.switch.ofId, model.portId))
Luca Preteb601c382018-04-30 16:10:43 -070048 interfaces = []
49 for intf in model.interfaces.all():
50 i = {
Scott Baker91bf91b2019-03-15 16:13:51 -070051 "name": intf.name,
52 "ips": [i.ip for i in intf.ips.all()]
Luca Preteb601c382018-04-30 16:10:43 -070053 }
54 if intf.vlanUntagged:
55 i["vlan-untagged"] = intf.vlanUntagged
56 interfaces.append(i)
57
58 # Send port config to onos-fabric netcfg
59 data = {
Matteo Scandolodfe75ff2018-06-15 10:52:09 -070060 "ports": {
Scott Baker91bf91b2019-03-15 16:13:51 -070061 "%s/%s" % (model.switch.ofId, model.portId): {
Matteo Scandolodfe75ff2018-06-15 10:52:09 -070062 "interfaces": interfaces,
63 "hostLearning": {
64 "enabled": model.host_learning
65 }
66 }
Luca Preteb601c382018-04-30 16:10:43 -070067 }
Luca Preteb601c382018-04-30 16:10:43 -070068 }
69
Matteo Scandolodfe75ff2018-06-15 10:52:09 -070070 log.debug("Port %s/%s data" % (model.switch.ofId, model.portId), data=data)
71
Himanshu Bhandari3d2d3412020-04-29 12:08:09 +053072 onos = Helpers.get_onos(model.switch, self.model_accessor)
Luca Preteb601c382018-04-30 16:10:43 -070073 url = 'http://%s:%s/onos/v1/network/configuration/' % (onos.rest_hostname, onos.rest_port)
74 r = requests.post(url, json=data, auth=HTTPBasicAuth(onos.rest_username, onos.rest_password))
Luca Preteb601c382018-04-30 16:10:43 -070075 if r.status_code != 200:
76 log.error(r.text)
Matteo Scandolodb7adc32018-06-15 16:05:19 -070077 raise Exception("Failed to add port %s/%s into ONOS" % (model.switch.ofId, model.portId))
Luca Preteb601c382018-04-30 16:10:43 -070078 else:
79 try:
Matteo Scandolodfe75ff2018-06-15 10:52:09 -070080 log.info("Port %s/%s response" % (model.switch.ofId, model.portId), json=r.json())
Luca Preteb601c382018-04-30 16:10:43 -070081 except Exception:
Matteo Scandolodfe75ff2018-06-15 10:52:09 -070082 log.info("Port %s/%s response" % (model.switch.ofId, model.portId), text=r.text)
Scott Baker91bf91b2019-03-15 16:13:51 -070083 # Now set the port's administrative state.
Himanshu Bhandari3d2d3412020-04-29 12:08:09 +053084 # TODO(smbaker): See if netcfg allows us to specify the portstate instead of using a separate REST call.
85 url = 'http://%s:%s/onos/v1/devices/%s/portstate/%s' % (onos.rest_hostname, onos.rest_port, model.switch.ofId, model.portId)
Scott Baker91bf91b2019-03-15 16:13:51 -070086 data = {"enabled": True if model.admin_state == "enabled" else False}
87 log.debug("Sending portstate %s to %s/%s" % (data, model.switch.ofId, model.portId))
88 r = requests.post(url, json=data, auth=HTTPBasicAuth(onos.rest_username, onos.rest_password))
Scott Baker91bf91b2019-03-15 16:13:51 -070089 if r.status_code != 200:
90 log.error(r.text)
91 raise Exception("Failed to set portstate %s/%s into ONOS" % (model.switch.ofId, model.portId))
92 else:
93 try:
94 log.info("Portstate %s/%s response" % (model.switch.ofId, model.portId), json=r.json())
95 except Exception:
96 log.info("Portstate %s/%s response" % (model.switch.ofId, model.portId), text=r.text)
97
Himanshu Bhandari3d2d3412020-04-29 12:08:09 +053098 def delete_netcfg_item(self, partial_url, switch, model_accessor):
99 onos = Helpers.get_onos(switch, model_accessor)
Matteo Scandolodb7adc32018-06-15 16:05:19 -0700100 url = 'http://%s:%s/onos/v1/network/configuration/ports/%s' % (onos.rest_hostname, onos.rest_port, partial_url)
Matteo Scandolo6739b512018-05-30 18:55:29 -0700101 r = requests.delete(url, auth=HTTPBasicAuth(onos.rest_username, onos.rest_password))
Matteo Scandolo6739b512018-05-30 18:55:29 -0700102 if r.status_code != 204:
103 log.error(r.text)
Matteo Scandolodb7adc32018-06-15 16:05:19 -0700104 raise Exception("Failed to %s port %s from ONOS" % url)
105
106 def delete_record(self, model):
Matteo Scandolodb7adc32018-06-15 16:05:19 -0700107 if model.leaf_model_name == "PortInterface":
Luca Prete15377872018-09-11 17:32:55 -0700108 log.info("Received update for PortInterface", port=model.port.portId, interface=model.name)
Scott Bakere9855012019-04-01 15:01:34 -0700109 log.info("Removing port interface %s from port %s/%s in onos-fabric" %
110 (model.name, model.port.switch.ofId, model.port.portId))
Matteo Scandolodb7adc32018-06-15 16:05:19 -0700111
Matteo Scandolodb7adc32018-06-15 16:05:19 -0700112 # resync the existing interfaces
113 return self.sync_record(model.port)
114
Luca Prete15377872018-09-11 17:32:55 -0700115 if model.leaf_model_name == "FabricIpAddress":
116 # TODO add unit tests
Scott Bakere9855012019-04-01 15:01:34 -0700117 log.info(
118 "Received update for FabricIpAddress",
119 port=model.interface.port.portId,
120 interface=model.interface.name,
121 ip=model.ip)
122 log.info("Removing IP %s from interface %s, on port %s/%s in onos-fabric" %
123 (model.ip, model.interface.name, model.interface.port.switch.ofId, model.interface.port.portId))
Luca Prete15377872018-09-11 17:32:55 -0700124
125 # resync the existing interfaces
126 return self.sync_record(model.interface.port)
127
Matteo Scandolodb7adc32018-06-15 16:05:19 -0700128 log.info("Removing port %s/%s from onos-fabric" % (model.switch.ofId, model.portId))
129
130 key = "%s/%s" % (model.switch.ofId, model.portId)
131 key = urllib.quote(key, safe='')
132
133 # deleting the port
Himanshu Bhandari3d2d3412020-04-29 12:08:09 +0530134 self.delete_netcfg_item(key, model.switch, self.model_accessor)