blob: 4f0c9140d4a19bf10271e7d6943f481a1e535f7d [file] [log] [blame]
Luca Preteb601c382018-04-30 16:10:43 -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 -070016#from __future__ import absolute_import
17
Luca Preteb601c382018-04-30 16:10:43 -070018import requests
Matteo Scandolodb7adc32018-06-15 16:05:19 -070019import urllib
Luca Preteb601c382018-04-30 16:10:43 -070020from requests.auth import HTTPBasicAuth
Scott Baker91bf91b2019-03-15 16:13:51 -070021from xossynchronizer.steps.syncstep import SyncStep
22from xossynchronizer.modelaccessor import SwitchPort, PortInterface, FabricIpAddress, model_accessor
Luca Preteb601c382018-04-30 16:10:43 -070023
24from xosconfig import Config
25from multistructlog import create_logger
26
Matteo Scandolo04e5e122018-05-04 16:21:53 -070027from helpers import Helpers
28
Luca Preteb601c382018-04-30 16:10:43 -070029log = create_logger(Config().get('logging'))
30
Scott Baker91bf91b2019-03-15 16:13:51 -070031
Luca Preteb601c382018-04-30 16:10:43 -070032class SyncFabricPort(SyncStep):
33 provides = [SwitchPort]
Luca Prete15377872018-09-11 17:32:55 -070034 observes = [SwitchPort, PortInterface, FabricIpAddress]
Luca Preteb601c382018-04-30 16:10:43 -070035
Luca Preteb601c382018-04-30 16:10:43 -070036 def sync_record(self, model):
Matteo Scandolodb7adc32018-06-15 16:05:19 -070037
38 if model.leaf_model_name == "PortInterface":
Scott Baker91bf91b2019-03-15 16:13:51 -070039 log.info("Received update for PortInterface", port=model.port.portId, interface=model)
Matteo Scandolodb7adc32018-06-15 16:05:19 -070040 return self.sync_record(model.port)
41
Luca Prete15377872018-09-11 17:32:55 -070042 if model.leaf_model_name == "FabricIpAddress":
Scott Baker91bf91b2019-03-15 16:13:51 -070043 log.info("Received update for FabricIpAddress",
44 port=model.interface.port.portId,
45 interface=model.interface.name,
46 ip=model.ip)
Luca Prete15377872018-09-11 17:32:55 -070047 return self.sync_record(model.interface.port)
48
Matteo Scandolo6739b512018-05-30 18:55:29 -070049 log.info("Adding port %s/%s to onos-fabric" % (model.switch.ofId, model.portId))
Luca Preteb601c382018-04-30 16:10:43 -070050 interfaces = []
51 for intf in model.interfaces.all():
52 i = {
Scott Baker91bf91b2019-03-15 16:13:51 -070053 "name": intf.name,
54 "ips": [i.ip for i in intf.ips.all()]
Luca Preteb601c382018-04-30 16:10:43 -070055 }
56 if intf.vlanUntagged:
57 i["vlan-untagged"] = intf.vlanUntagged
58 interfaces.append(i)
59
60 # Send port config to onos-fabric netcfg
61 data = {
Matteo Scandolodfe75ff2018-06-15 10:52:09 -070062 "ports": {
Scott Baker91bf91b2019-03-15 16:13:51 -070063 "%s/%s" % (model.switch.ofId, model.portId): {
Matteo Scandolodfe75ff2018-06-15 10:52:09 -070064 "interfaces": interfaces,
65 "hostLearning": {
66 "enabled": model.host_learning
67 }
68 }
Luca Preteb601c382018-04-30 16:10:43 -070069 }
Luca Preteb601c382018-04-30 16:10:43 -070070 }
71
Matteo Scandolodfe75ff2018-06-15 10:52:09 -070072 log.debug("Port %s/%s data" % (model.switch.ofId, model.portId), data=data)
73
Scott Baker382366d2019-02-04 10:58:43 -080074 onos = Helpers.get_onos_fabric_service(self.model_accessor)
Luca Preteb601c382018-04-30 16:10:43 -070075
76 url = 'http://%s:%s/onos/v1/network/configuration/' % (onos.rest_hostname, onos.rest_port)
Matteo Scandolo6739b512018-05-30 18:55:29 -070077
Luca Preteb601c382018-04-30 16:10:43 -070078 r = requests.post(url, json=data, auth=HTTPBasicAuth(onos.rest_username, onos.rest_password))
79
80 if r.status_code != 200:
81 log.error(r.text)
Matteo Scandolodb7adc32018-06-15 16:05:19 -070082 raise Exception("Failed to add port %s/%s into ONOS" % (model.switch.ofId, model.portId))
Luca Preteb601c382018-04-30 16:10:43 -070083 else:
84 try:
Matteo Scandolodfe75ff2018-06-15 10:52:09 -070085 log.info("Port %s/%s response" % (model.switch.ofId, model.portId), json=r.json())
Luca Preteb601c382018-04-30 16:10:43 -070086 except Exception:
Matteo Scandolodfe75ff2018-06-15 10:52:09 -070087 log.info("Port %s/%s response" % (model.switch.ofId, model.portId), text=r.text)
Luca Preteb601c382018-04-30 16:10:43 -070088
Scott Baker91bf91b2019-03-15 16:13:51 -070089 # Now set the port's administrative state.
90 # TODO(smbaker): See if netcfg allows us to specify the portstate instead of using a separate REST call
91
92 url = 'http://%s:%s/onos/v1/devices/%s/portstate/%s' % (onos.rest_hostname,
93 onos.rest_port,
94 model.switch.ofId,
95 model.portId)
96 data = {"enabled": True if model.admin_state == "enabled" else False}
97 log.debug("Sending portstate %s to %s/%s" % (data, model.switch.ofId, model.portId))
98 r = requests.post(url, json=data, auth=HTTPBasicAuth(onos.rest_username, onos.rest_password))
99
100 if r.status_code != 200:
101 log.error(r.text)
102 raise Exception("Failed to set portstate %s/%s into ONOS" % (model.switch.ofId, model.portId))
103 else:
104 try:
105 log.info("Portstate %s/%s response" % (model.switch.ofId, model.portId), json=r.json())
106 except Exception:
107 log.info("Portstate %s/%s response" % (model.switch.ofId, model.portId), text=r.text)
108
Matteo Scandolodb7adc32018-06-15 16:05:19 -0700109 def delete_netcfg_item(self, partial_url):
Scott Baker382366d2019-02-04 10:58:43 -0800110 onos = Helpers.get_onos_fabric_service(self.model_accessor)
Matteo Scandolodb7adc32018-06-15 16:05:19 -0700111 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 -0700112
113 r = requests.delete(url, auth=HTTPBasicAuth(onos.rest_username, onos.rest_password))
114
115 if r.status_code != 204:
116 log.error(r.text)
Matteo Scandolodb7adc32018-06-15 16:05:19 -0700117 raise Exception("Failed to %s port %s from ONOS" % url)
118
119 def delete_record(self, model):
Matteo Scandolodb7adc32018-06-15 16:05:19 -0700120 if model.leaf_model_name == "PortInterface":
Luca Prete15377872018-09-11 17:32:55 -0700121 log.info("Received update for PortInterface", port=model.port.portId, interface=model.name)
Scott Bakere9855012019-04-01 15:01:34 -0700122 log.info("Removing port interface %s from port %s/%s in onos-fabric" %
123 (model.name, model.port.switch.ofId, model.port.portId))
Matteo Scandolodb7adc32018-06-15 16:05:19 -0700124
Matteo Scandolodb7adc32018-06-15 16:05:19 -0700125 # resync the existing interfaces
126 return self.sync_record(model.port)
127
Luca Prete15377872018-09-11 17:32:55 -0700128 if model.leaf_model_name == "FabricIpAddress":
129 # TODO add unit tests
Scott Bakere9855012019-04-01 15:01:34 -0700130 log.info(
131 "Received update for FabricIpAddress",
132 port=model.interface.port.portId,
133 interface=model.interface.name,
134 ip=model.ip)
135 log.info("Removing IP %s from interface %s, on port %s/%s in onos-fabric" %
136 (model.ip, model.interface.name, model.interface.port.switch.ofId, model.interface.port.portId))
Luca Prete15377872018-09-11 17:32:55 -0700137
138 # resync the existing interfaces
139 return self.sync_record(model.interface.port)
140
Matteo Scandolodb7adc32018-06-15 16:05:19 -0700141 log.info("Removing port %s/%s from onos-fabric" % (model.switch.ofId, model.portId))
142
143 key = "%s/%s" % (model.switch.ofId, model.portId)
144 key = urllib.quote(key, safe='')
145
146 # deleting the port
147 self.delete_netcfg_item(key)