blob: 4e1aacb8c05588555887432544f5273be4959037 [file] [log] [blame]
Matteo Scandoload0c1752018-08-09 15:47:16 -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
Matteo Scandoloea529092018-09-11 16:36:39 -070017
Matteo Scandolo74f63302018-11-01 14:05:01 -070018from synchronizers.new_base.modelaccessor import RCORDSubscriber, RCORDIpAddress, ONUDevice, model_accessor
Matteo Scandoload0c1752018-08-09 15:47:16 -070019from synchronizers.new_base.policy import Policy
20
Matteo Scandoloea529092018-09-11 16:36:39 -070021import os
22import sys
23
24sync_path = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), ".."))
25sys.path.append(sync_path)
26
27from helpers import AttHelpers
28
Matteo Scandoloe8c33d62018-08-16 14:37:24 -070029class DeferredException(Exception):
30 pass
31
Matteo Scandoload0c1752018-08-09 15:47:16 -070032class AttWorkflowDriverServiceInstancePolicy(Policy):
33 model_name = "AttWorkflowDriverServiceInstance"
34
35 def handle_create(self, si):
36 self.logger.debug("MODEL_POLICY: handle_create for AttWorkflowDriverServiceInstance %s " % si.id)
37 self.handle_update(si)
38
Matteo Scandoload0c1752018-08-09 15:47:16 -070039 def handle_update(self, si):
Matteo Scandolob8da43d2018-09-12 15:52:16 -070040 self.logger.debug("MODEL_POLICY: handle_update for AttWorkflowDriverServiceInstance %s " % (si.id), onu_state=si.onu_state, authentication_state=si.authentication_state)
Matteo Scandoloe8c33d62018-08-16 14:37:24 -070041
Andy Bavierafaf1762019-01-16 09:41:43 -070042 # Changing ONU state can change auth state
43 # Changing auth state can change DHCP state
44 # So need to process in this order
45 self.process_onu_state(si)
46 self.process_auth_state(si)
47 self.process_dhcp_state(si)
48
49 self.validate_states(si)
Matteo Scandoloe8c33d62018-08-16 14:37:24 -070050
Matteo Scandoloea529092018-09-11 16:36:39 -070051 # handling the subscriber status
Andy Bavierafaf1762019-01-16 09:41:43 -070052 # It's a combination of all the other states
Matteo Scandoloea529092018-09-11 16:36:39 -070053 subscriber = self.get_subscriber(si.serial_number)
Matteo Scandoloea529092018-09-11 16:36:39 -070054 if subscriber:
55 self.update_subscriber(subscriber, si)
Matteo Scandoload0c1752018-08-09 15:47:16 -070056
Andy Bavierafaf1762019-01-16 09:41:43 -070057 si.save_changed_fields()
58
59 def process_onu_state(self, si):
60 if si.onu_state == "AWAITING" or si.onu_state == "ENABLED":
61 [valid, message] = AttHelpers.validate_onu(self.logger, si)
62 si.status_message = message
63 if valid:
64 si.onu_state = "ENABLED"
65 self.update_onu(si.serial_number, "ENABLED")
66 else:
67 si.onu_state = "DISABLED"
68 self.update_onu(si.serial_number, "DISABLED")
69 else:
70 si.status_message = "ONU has been disabled"
71 self.update_onu(si.serial_number, "DISABLED")
72
73 def process_auth_state(self, si):
74 auth_msgs = {
75 "AWAITING": " - Awaiting Authentication",
76 "REQUESTED": " - Authentication requested",
77 "STARTED": " - Authentication started",
78 "APPROVED": " - Authentication succeeded",
79 "DENIED": " - Authentication denied"
80 }
81 if si.onu_state == "DISABLED":
82 si.authentication_state = "AWAITING"
83 else:
84 si.status_message += auth_msgs[si.authentication_state]
85
86 def process_dhcp_state(self, si):
Andy Bavier8ed30c92018-12-11 13:46:25 -070087 if si.authentication_state in ["AWAITING", "REQUESTED", "STARTED"]:
88 si.ip_address = ""
89 si.mac_address = ""
Andy Bavier15310cf2018-12-13 14:16:49 -070090 si.dhcp_state = "AWAITING"
Andy Bavier8ed30c92018-12-11 13:46:25 -070091
Andy Bavierafaf1762019-01-16 09:41:43 -070092 # Make sure the object is in a legitimate state
93 # It should be after the above processing steps
94 # However this might still fail if an event has fired in the meantime
95 # Valid states:
96 # ONU | Auth | DHCP
97 # ===============================
98 # AWAITING | AWAITING | AWAITING
99 # ENABLED | * | AWAITING
100 # ENABLED | APPROVED | *
101 # DISABLED | AWAITING | AWAITING
102 def validate_states(self, si):
103 if (si.onu_state == "AWAITING" or si.onu_state == "DISABLED") and si.authentication_state == "AWAITING" and si.dhcp_state == "AWAITING":
104 return
105 if si.onu_state == "ENABLED" and (si.authentication_state == "APPROVED" or si.dhcp_state == "AWAITING"):
106 return
107 self.logger.warning("MODEL_POLICY (validate_states): invalid state combination", onu_state=si.onu_state, auth_state=si.authentication_state, dhcp_state=si.dhcp_state)
Matteo Scandoloe8c33d62018-08-16 14:37:24 -0700108
Matteo Scandoload0c1752018-08-09 15:47:16 -0700109
Matteo Scandoloea529092018-09-11 16:36:39 -0700110 def update_onu(self, serial_number, admin_state):
Matteo Scandoloc6ac74a2018-09-14 08:14:51 -0700111 onu = [onu for onu in ONUDevice.objects.all() if onu.serial_number.lower() == serial_number.lower()][0]
112 if onu.admin_state == admin_state:
113 self.logger.debug("MODEL_POLICY: ONUDevice [%s] already has admin_state to %s" % (serial_number, admin_state))
114 else:
115 self.logger.debug("MODEL_POLICY: setting ONUDevice [%s] admin_state to %s" % (serial_number, admin_state))
116 onu.admin_state = admin_state
Andy Bavier0d631eb2018-10-17 18:05:04 -0700117 onu.save_changed_fields(always_update_timestamp=True)
Matteo Scandoload0c1752018-08-09 15:47:16 -0700118
Matteo Scandoloea529092018-09-11 16:36:39 -0700119 def get_subscriber(self, serial_number):
120 try:
121 return [s for s in RCORDSubscriber.objects.all() if s.onu_device.lower() == serial_number.lower()][0]
122 except IndexError:
123 # If the subscriber doesn't exist we don't do anything
124 self.logger.debug("MODEL_POLICY: subscriber does not exists for this SI, doing nothing", onu_device=serial_number)
125 return None
Matteo Scandoload0c1752018-08-09 15:47:16 -0700126
Matteo Scandolo74f63302018-11-01 14:05:01 -0700127 def update_subscriber_ip(self, subscriber, ip):
128 # TODO check if the subscriber has an IP and update it,
129 # or create a new one
130 try:
131 ip = RCORDIpAddress.objects.filter(
132 subscriber_id=subscriber.id,
133 ip=ip
134 )[0]
135 self.logger.debug("MODEL_POLICY: found existing RCORDIpAddress for subscriber", onu_device=subscriber.onu_device, subscriber_status=subscriber.status, ip=ip)
136 ip.save_changed_fields()
137 except IndexError:
138 self.logger.debug("MODEL_POLICY: Creating new RCORDIpAddress for subscriber", onu_device=subscriber.onu_device, subscriber_status=subscriber.status, ip=ip)
139 ip = RCORDIpAddress(
140 subscriber_id=subscriber.id,
141 ip=ip,
142 description="DHCP Assigned IP Address"
143 )
144 ip.save()
145
Andy Bavier8ed30c92018-12-11 13:46:25 -0700146 def delete_subscriber_ip(self, subscriber, ip):
147 try:
148 ip = RCORDIpAddress.objects.filter(
149 subscriber_id=subscriber.id,
150 ip=ip
151 )[0]
152 self.logger.debug("MODEL_POLICY: delete RCORDIpAddress for subscriber", onu_device=subscriber.onu_device, subscriber_status=subscriber.status, ip=ip)
153 ip.delete()
154 except:
155 self.logger.warning("MODEL_POLICY: no RCORDIpAddress object found, cannot delete", ip=ip)
156
Matteo Scandoloea529092018-09-11 16:36:39 -0700157 def update_subscriber(self, subscriber, si):
Matteo Scandoloc6ac74a2018-09-14 08:14:51 -0700158 cur_status = subscriber.status
Andy Bavierafaf1762019-01-16 09:41:43 -0700159 # Don't change state if someone has disabled the subscriber
160 if subscriber.status != "disabled":
161 if si.authentication_state in ["AWAITING", "REQUESTED", "STARTED"]:
162 subscriber.status = "awaiting-auth"
163 elif si.authentication_state == "APPROVED":
164 subscriber.status = "enabled"
165 elif si.authentication_state == "DENIED":
166 subscriber.status = "auth-failed"
Matteo Scandoload0c1752018-08-09 15:47:16 -0700167
Matteo Scandolode8cfa82018-10-16 13:49:05 -0700168 # NOTE we save the subscriber only if:
169 # - the status has changed
170 # - we get a DHCPACK event
171 if cur_status != subscriber.status or si.dhcp_state == "DHCPACK":
172 self.logger.debug("MODEL_POLICY: updating subscriber", onu_device=subscriber.onu_device, authentication_state=si.authentication_state, subscriber_status=subscriber.status)
Andy Bavier8ed30c92018-12-11 13:46:25 -0700173 if subscriber.status == "awaiting-auth":
174 self.delete_subscriber_ip(subscriber, si.ip_address)
175 subscriber.mac_address = ""
176 elif si.ip_address and si.mac_address:
Matteo Scandolo74f63302018-11-01 14:05:01 -0700177 self.update_subscriber_ip(subscriber, si.ip_address)
Matteo Scandolode8cfa82018-10-16 13:49:05 -0700178 subscriber.mac_address = si.mac_address
Andy Bavier0d631eb2018-10-17 18:05:04 -0700179 subscriber.save_changed_fields(always_update_timestamp=True)
Matteo Scandolode8cfa82018-10-16 13:49:05 -0700180 else:
Matteo Scandoloc6ac74a2018-09-14 08:14:51 -0700181 self.logger.debug("MODEL_POLICY: subscriber status has not changed", onu_device=subscriber.onu_device,
182 authentication_state=si.authentication_state, subscriber_status=subscriber.status)
Matteo Scandoload0c1752018-08-09 15:47:16 -0700183
184 def handle_delete(self, si):
185 pass