blob: f9628e3fc2595f792c6297b790cd719a3c4f7277 [file] [log] [blame]
Andy Bavier561f3e52019-03-15 10:46:05 -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
16
Andy Bavier0ce0dae2019-05-10 17:46:02 -070017from helpers import TtHelpers
Andy Bavier561f3e52019-03-15 10:46:05 -070018from xossynchronizer.model_policies.policy import Policy
19
20import os
21import sys
22
23sync_path = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), ".."))
24sys.path.append(sync_path)
25
Andy Bavier561f3e52019-03-15 10:46:05 -070026
27class DeferredException(Exception):
28 pass
29
30class TtWorkflowDriverServiceInstancePolicy(Policy):
31 model_name = "TtWorkflowDriverServiceInstance"
32
33 def handle_create(self, si):
34 self.logger.debug("MODEL_POLICY: handle_create for TtWorkflowDriverServiceInstance %s " % si.id)
35 self.handle_update(si)
36
37 def handle_update(self, si):
Andy Bavier0ce0dae2019-05-10 17:46:02 -070038 self.logger.debug("MODEL_POLICY: handle_update for TtWorkflowDriverServiceInstance %s " % (si.id), onu_state=si.admin_onu_state)
Andy Bavier561f3e52019-03-15 10:46:05 -070039
40 self.process_onu_state(si)
41 self.process_dhcp_state(si)
42
43 self.validate_states(si)
44
45 # handling the subscriber status
46 # It's a combination of all the other states
47 subscriber = self.get_subscriber(si.serial_number)
48 if subscriber:
49 self.update_subscriber(subscriber, si)
50
51 si.save_changed_fields()
52
Andy Bavier0ce0dae2019-05-10 17:46:02 -070053 # Check the whitelist to see if the ONU is valid. If it is, make sure that it's enabled.
Andy Bavier561f3e52019-03-15 10:46:05 -070054 def process_onu_state(self, si):
55 [valid, message] = TtHelpers.validate_onu(self.model_accessor, self.logger, si)
Andy Bavier0ce0dae2019-05-10 17:46:02 -070056 si.status_message = message
57 if valid:
58 si.admin_onu_state = "ENABLED"
59 self.update_onu(si.serial_number, "ENABLED")
60 else:
61 si.admin_onu_state = "DISABLED"
Andy Bavier561f3e52019-03-15 10:46:05 -070062 self.update_onu(si.serial_number, "DISABLED")
63
64
65 # The DhcpL2Relay ONOS app generates events that update the fields below.
66 # It only sends events when it processes DHCP packets. It keeps no internal state.
67 def process_dhcp_state(self, si):
Andy Bavier0ce0dae2019-05-10 17:46:02 -070068 if si.admin_onu_state in ["AWAITING", "DISABLED"]:
Andy Bavier561f3e52019-03-15 10:46:05 -070069 si.ip_address = ""
70 si.mac_address = ""
71 si.dhcp_state = "AWAITING"
72
73 # Make sure the object is in a legitimate state
74 # It should be after the above processing steps
75 # However this might still fail if an event has fired in the meantime
76 # Valid states:
77 # ONU | DHCP
78 # ===============================
79 # AWAITING | AWAITING
80 # ENABLED | *
81 # DISABLED | AWAITING
82 def validate_states(self, si):
Andy Bavier0ce0dae2019-05-10 17:46:02 -070083 if (si.admin_onu_state == "AWAITING" or si.admin_onu_state == "DISABLED") and si.dhcp_state == "AWAITING":
Andy Bavier561f3e52019-03-15 10:46:05 -070084 return
Andy Bavier0ce0dae2019-05-10 17:46:02 -070085 if si.admin_onu_state == "ENABLED":
Andy Bavier561f3e52019-03-15 10:46:05 -070086 return
Andy Bavier0ce0dae2019-05-10 17:46:02 -070087 self.logger.warning("MODEL_POLICY (validate_states): invalid state combination", onu_state=si.admin_onu_state, dhcp_state=si.dhcp_state)
Andy Bavier561f3e52019-03-15 10:46:05 -070088
89
90 def update_onu(self, serial_number, admin_state):
Andy Bavier0ce0dae2019-05-10 17:46:02 -070091 onu = [onu for onu in self.model_accessor.ONUDevice.objects.all() if onu.serial_number.lower()
92 == serial_number.lower()][0]
Andy Bavier561f3e52019-03-15 10:46:05 -070093 if onu.admin_state == admin_state:
Andy Bavier0ce0dae2019-05-10 17:46:02 -070094 self.logger.debug(
95 "MODEL_POLICY: ONUDevice [%s] already has admin_state to %s" %
96 (serial_number, admin_state))
Andy Bavier561f3e52019-03-15 10:46:05 -070097 else:
98 self.logger.debug("MODEL_POLICY: setting ONUDevice [%s] admin_state to %s" % (serial_number, admin_state))
99 onu.admin_state = admin_state
100 onu.save_changed_fields(always_update_timestamp=True)
101
102 def get_subscriber(self, serial_number):
103 try:
Andy Bavier0ce0dae2019-05-10 17:46:02 -0700104 return [s for s in self.model_accessor.RCORDSubscriber.objects.all() if s.onu_device.lower()
105 == serial_number.lower()][0]
Andy Bavier561f3e52019-03-15 10:46:05 -0700106 except IndexError:
107 # If the subscriber doesn't exist we don't do anything
Andy Bavier0ce0dae2019-05-10 17:46:02 -0700108 self.logger.debug(
109 "MODEL_POLICY: subscriber does not exists for this SI, doing nothing",
110 onu_device=serial_number)
Andy Bavier561f3e52019-03-15 10:46:05 -0700111 return None
112
113 def update_subscriber_ip(self, subscriber, ip):
114 # TODO check if the subscriber has an IP and update it,
115 # or create a new one
116 try:
117 ip = self.model_accessor.RCORDIpAddress.objects.filter(
118 subscriber_id=subscriber.id,
119 ip=ip
120 )[0]
Andy Bavier0ce0dae2019-05-10 17:46:02 -0700121 self.logger.debug("MODEL_POLICY: found existing RCORDIpAddress for subscriber",
122 onu_device=subscriber.onu_device, subscriber_status=subscriber.status, ip=ip)
Andy Bavier561f3e52019-03-15 10:46:05 -0700123 ip.save_changed_fields()
124 except IndexError:
Andy Bavier0ce0dae2019-05-10 17:46:02 -0700125 self.logger.debug(
126 "MODEL_POLICY: Creating new RCORDIpAddress for subscriber",
127 onu_device=subscriber.onu_device,
128 subscriber_status=subscriber.status,
129 ip=ip)
Andy Bavier561f3e52019-03-15 10:46:05 -0700130 ip = self.model_accessor.RCORDIpAddress(
131 subscriber_id=subscriber.id,
132 ip=ip,
133 description="DHCP Assigned IP Address"
134 )
135 ip.save()
136
137 def delete_subscriber_ip(self, subscriber, ip):
138 try:
139 ip = self.model_accessor.RCORDIpAddress.objects.filter(
140 subscriber_id=subscriber.id,
141 ip=ip
142 )[0]
Andy Bavier0ce0dae2019-05-10 17:46:02 -0700143 self.logger.debug(
144 "MODEL_POLICY: delete RCORDIpAddress for subscriber",
145 onu_device=subscriber.onu_device,
146 subscriber_status=subscriber.status,
147 ip=ip)
Andy Bavier561f3e52019-03-15 10:46:05 -0700148 ip.delete()
Andy Bavier0ce0dae2019-05-10 17:46:02 -0700149 except BaseException:
Andy Bavier561f3e52019-03-15 10:46:05 -0700150 self.logger.warning("MODEL_POLICY: no RCORDIpAddress object found, cannot delete", ip=ip)
151
152 def update_subscriber(self, subscriber, si):
153 cur_status = subscriber.status
154 # Don't change state if someone has disabled the subscriber
155 if subscriber.status != "disabled":
Andy Bavier0ce0dae2019-05-10 17:46:02 -0700156 if si.admin_onu_state == "ENABLED":
Andy Bavier561f3e52019-03-15 10:46:05 -0700157 subscriber.status = "enabled"
Andy Bavier0ce0dae2019-05-10 17:46:02 -0700158 elif si.admin_onu_state == "DISABLED":
Andy Bavier561f3e52019-03-15 10:46:05 -0700159 subscriber.status = "awaiting-auth"
160
161 # NOTE we save the subscriber only if:
162 # - the status has changed
163 # - we get a DHCPACK event
164 if cur_status != subscriber.status or si.dhcp_state == "DHCPACK":
Andy Bavier0ce0dae2019-05-10 17:46:02 -0700165 self.logger.debug(
166 "MODEL_POLICY: updating subscriber",
167 onu_device=subscriber.onu_device,
168 subscriber_status=subscriber.status)
Andy Bavier561f3e52019-03-15 10:46:05 -0700169 if subscriber.status == "awaiting-auth":
170 self.delete_subscriber_ip(subscriber, si.ip_address)
171 subscriber.mac_address = ""
172 elif si.ip_address and si.mac_address:
173 self.update_subscriber_ip(subscriber, si.ip_address)
174 subscriber.mac_address = si.mac_address
175 subscriber.save_changed_fields(always_update_timestamp=True)
176 else:
177 self.logger.debug("MODEL_POLICY: subscriber status has not changed", onu_device=subscriber.onu_device,
178 subscriber_status=subscriber.status)
179
180 def handle_delete(self, si):
181 pass