blob: 1ab0f52e5649661b42c39b18364dcade1068b964 [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
16import requests
Matteo Scandolodb7adc32018-06-15 16:05:19 -070017import urllib
Luca Preteb601c382018-04-30 16:10:43 -070018from requests.auth import HTTPBasicAuth
Scott Baker91bf91b2019-03-15 16:13:51 -070019from xossynchronizer.steps.syncstep import SyncStep
20from xossynchronizer.modelaccessor import SwitchPort, PortInterface, FabricIpAddress, model_accessor
Luca Preteb601c382018-04-30 16:10:43 -070021
22from xosconfig import Config
23from multistructlog import create_logger
24
Matteo Scandolo04e5e122018-05-04 16:21:53 -070025from helpers import Helpers
26
Luca Preteb601c382018-04-30 16:10:43 -070027log = create_logger(Config().get('logging'))
28
Scott Baker91bf91b2019-03-15 16:13:51 -070029
Luca Preteb601c382018-04-30 16:10:43 -070030class 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
Scott Baker382366d2019-02-04 10:58:43 -080072 onos = Helpers.get_onos_fabric_service(self.model_accessor)
Luca Preteb601c382018-04-30 16:10:43 -070073
74 url = 'http://%s:%s/onos/v1/network/configuration/' % (onos.rest_hostname, onos.rest_port)
Matteo Scandolo6739b512018-05-30 18:55:29 -070075
Luca Preteb601c382018-04-30 16:10:43 -070076 r = requests.post(url, json=data, auth=HTTPBasicAuth(onos.rest_username, onos.rest_password))
77
78 if r.status_code != 200:
79 log.error(r.text)
Matteo Scandolodb7adc32018-06-15 16:05:19 -070080 raise Exception("Failed to add port %s/%s into ONOS" % (model.switch.ofId, model.portId))
Luca Preteb601c382018-04-30 16:10:43 -070081 else:
82 try:
Matteo Scandolodfe75ff2018-06-15 10:52:09 -070083 log.info("Port %s/%s response" % (model.switch.ofId, model.portId), json=r.json())
Luca Preteb601c382018-04-30 16:10:43 -070084 except Exception:
Matteo Scandolodfe75ff2018-06-15 10:52:09 -070085 log.info("Port %s/%s response" % (model.switch.ofId, model.portId), text=r.text)
Luca Preteb601c382018-04-30 16:10:43 -070086
Scott Baker91bf91b2019-03-15 16:13:51 -070087 # Now set the port's administrative state.
88 # TODO(smbaker): See if netcfg allows us to specify the portstate instead of using a separate REST call
89
90 url = 'http://%s:%s/onos/v1/devices/%s/portstate/%s' % (onos.rest_hostname,
91 onos.rest_port,
92 model.switch.ofId,
93 model.portId)
94 data = {"enabled": True if model.admin_state == "enabled" else False}
95 log.debug("Sending portstate %s to %s/%s" % (data, model.switch.ofId, model.portId))
96 r = requests.post(url, json=data, auth=HTTPBasicAuth(onos.rest_username, onos.rest_password))
97
98 if r.status_code != 200:
99 log.error(r.text)
100 raise Exception("Failed to set portstate %s/%s into ONOS" % (model.switch.ofId, model.portId))
101 else:
102 try:
103 log.info("Portstate %s/%s response" % (model.switch.ofId, model.portId), json=r.json())
104 except Exception:
105 log.info("Portstate %s/%s response" % (model.switch.ofId, model.portId), text=r.text)
106
Matteo Scandolodb7adc32018-06-15 16:05:19 -0700107 def delete_netcfg_item(self, partial_url):
Scott Baker382366d2019-02-04 10:58:43 -0800108 onos = Helpers.get_onos_fabric_service(self.model_accessor)
Matteo Scandolodb7adc32018-06-15 16:05:19 -0700109 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 -0700110
111 r = requests.delete(url, auth=HTTPBasicAuth(onos.rest_username, onos.rest_password))
112
113 if r.status_code != 204:
114 log.error(r.text)
Matteo Scandolodb7adc32018-06-15 16:05:19 -0700115 raise Exception("Failed to %s port %s from ONOS" % url)
116
117 def delete_record(self, model):
Matteo Scandolodb7adc32018-06-15 16:05:19 -0700118 if model.leaf_model_name == "PortInterface":
Luca Prete15377872018-09-11 17:32:55 -0700119 log.info("Received update for PortInterface", port=model.port.portId, interface=model.name)
Matteo Scandolodb7adc32018-06-15 16:05:19 -0700120 log.info("Removing port interface %s from port %s/%s in onos-fabric" % (model.name, model.port.switch.ofId, model.port.portId))
121
Matteo Scandolodb7adc32018-06-15 16:05:19 -0700122 # resync the existing interfaces
123 return self.sync_record(model.port)
124
Luca Prete15377872018-09-11 17:32:55 -0700125 if model.leaf_model_name == "FabricIpAddress":
126 # TODO add unit tests
127 log.info("Received update for FabricIpAddress", port=model.interface.port.portId, interface=model.interface.name, ip=model.ip)
128 log.info("Removing IP %s from interface %s, on port %s/%s in onos-fabric" % (model.ip, model.interface.name, model.interface.port.switch.ofId, model.interface.port.portId))
129
130 # resync the existing interfaces
131 return self.sync_record(model.interface.port)
132
Matteo Scandolodb7adc32018-06-15 16:05:19 -0700133 log.info("Removing port %s/%s from onos-fabric" % (model.switch.ofId, model.portId))
134
135 key = "%s/%s" % (model.switch.ofId, model.portId)
136 key = urllib.quote(key, safe='')
137
138 # deleting the port
139 self.delete_netcfg_item(key)