blob: df179f941f2925f0e8072a21b7edb0a2bfc265e8 [file] [log] [blame]
Illyoung Choi5d59ab62019-06-24 16:15:27 -07001# Copyright 2019-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
15import logging
16from att_helpers import *
17
18# Check the whitelist to see if the ONU is valid. If it is, make sure that it's enabled.
19def process_onu_state(model_accessor, si):
20 [valid, message] = validate_onu(model_accessor, logging, si)
21 si.status_message = message
22 if valid:
23 si.admin_onu_state = "ENABLED"
24 update_onu(model_accessor, si.serial_number, "ENABLED")
25 else:
26 si.admin_onu_state = "DISABLED"
27 update_onu(model_accessor, si.serial_number, "DISABLED")
28
29
30# If the ONU has been disabled then we force re-authentication when it
31# is re-enabled.
32# Setting si.authentication_state = AWAITING:
33# -> subscriber status = "awaiting_auth"
34# -> service chain deleted
35# -> need authentication to restore connectivity after ONU enabled
36def process_auth_state(si):
37 auth_msgs = {
38 "AWAITING": " - Awaiting Authentication",
39 "REQUESTED": " - Authentication requested",
40 "STARTED": " - Authentication started",
41 "APPROVED": " - Authentication succeeded",
42 "DENIED": " - Authentication denied"
43 }
44 if si.admin_onu_state == "DISABLED" or si.oper_onu_status == "DISABLED":
45 si.authentication_state = "AWAITING"
46 else:
47 si.status_message += auth_msgs[si.authentication_state]
48
49
50# The DhcpL2Relay ONOS app generates events that update the fields below.
51# It only sends events when it processes DHCP packets. It keeps no internal state.
52# We reset dhcp_state when:
53# si.authentication_state in ["AWAITING", "REQUESTED", "STARTED"]
54# -> subscriber status = "awaiting_auth"
55# -> service chain not present
56# -> subscriber's OLT flow rules, xconnect not present
57# -> DHCP packets won't go through
58# Note, however, that the DHCP state at the endpoints is not changed.
59# A previously issued DHCP lease may still be valid.
60def process_dhcp_state(si):
61 if si.authentication_state in ["AWAITING", "REQUESTED", "STARTED"]:
62 si.ip_address = ""
63 si.mac_address = ""
64 si.dhcp_state = "AWAITING"
65
66
67# Make sure the object is in a legitimate state
68# It should be after the above processing steps
69# However this might still fail if an event has fired in the meantime
70# Valid states:
71# ONU | Auth | DHCP
72# ===============================
73# AWAITING | AWAITING | AWAITING
74# ENABLED | * | AWAITING
75# ENABLED | APPROVED | *
76# DISABLED | AWAITING | AWAITING
77def validate_states(si):
78 if (si.admin_onu_state == "AWAITING" or si.admin_onu_state ==
79 "DISABLED") and si.authentication_state == "AWAITING" and si.dhcp_state == "AWAITING":
80 return
81 if si.admin_onu_state == "ENABLED" and (si.authentication_state == "APPROVED" or si.dhcp_state == "AWAITING"):
82 return
83 logging.warning(
84 "MODEL_POLICY (validate_states): invalid state combination",
85 onu_state=si.admin_onu_state,
86 auth_state=si.authentication_state,
87 dhcp_state=si.dhcp_state)
88
89
90def update_onu(model_accessor, serial_number, admin_state):
91 onu = [onu for onu in model_accessor.ONUDevice.objects.all() if onu.serial_number.lower()
92 == serial_number.lower()][0]
93 if onu.admin_state == "ADMIN_DISABLED":
94 logging.debug(
95 "MODEL_POLICY: ONUDevice [%s] has been manually disabled, not changing state to %s" %
96 (serial_number, admin_state))
97 return
98 if onu.admin_state == admin_state:
99 logging.debug(
100 "MODEL_POLICY: ONUDevice [%s] already has admin_state to %s" %
101 (serial_number, admin_state))
102 else:
103 logging.debug("MODEL_POLICY: setting ONUDevice [%s] admin_state to %s" % (serial_number, admin_state))
104 onu.admin_state = admin_state
105 onu.save_changed_fields(always_update_timestamp=True)
106
107
108def get_subscriber(model_accessor, serial_number):
109 try:
110 return [s for s in model_accessor.RCORDSubscriber.objects.all() if s.onu_device.lower()
111 == serial_number.lower()][0]
112 except IndexError:
113 # If the subscriber doesn't exist we don't do anything
114 logging.debug(
115 "MODEL_POLICY: subscriber does not exists for this SI, doing nothing",
116 onu_device=serial_number)
117 return None
118
119
120def update_subscriber_ip(model_accessor, subscriber, ip):
121 # TODO check if the subscriber has an IP and update it,
122 # or create a new one
123 try:
124 ip = model_accessor.RCORDIpAddress.objects.filter(
125 subscriber_id=subscriber.id,
126 ip=ip
127 )[0]
128 logging.debug("MODEL_POLICY: found existing RCORDIpAddress for subscriber",
129 onu_device=subscriber.onu_device, subscriber_status=subscriber.status, ip=ip)
130 ip.save_changed_fields()
131 except IndexError:
132 logging.debug(
133 "MODEL_POLICY: Creating new RCORDIpAddress for subscriber",
134 onu_device=subscriber.onu_device,
135 subscriber_status=subscriber.status,
136 ip=ip)
137 ip = model_accessor.RCORDIpAddress(
138 subscriber_id=subscriber.id,
139 ip=ip,
140 description="DHCP Assigned IP Address"
141 )
142 ip.save()
143
144
145def delete_subscriber_ip(model_accessor, subscriber, ip):
146 try:
147 ip = model_accessor.RCORDIpAddress.objects.filter(
148 subscriber_id=subscriber.id,
149 ip=ip
150 )[0]
151 logging.debug(
152 "MODEL_POLICY: delete RCORDIpAddress for subscriber",
153 onu_device=subscriber.onu_device,
154 subscriber_status=subscriber.status,
155 ip=ip)
156 ip.delete()
157 except BaseException:
158 logging.warning("MODEL_POLICY: no RCORDIpAddress object found, cannot delete", ip=ip)
159
160
161def update_subscriber(model_accessor, subscriber, si):
162 cur_status = subscriber.status
163 # Don't change state if someone has disabled the subscriber
164 if subscriber.status != "disabled":
165 if si.authentication_state in ["AWAITING", "REQUESTED", "STARTED"]:
166 subscriber.status = "awaiting-auth"
167 elif si.authentication_state == "APPROVED":
168 subscriber.status = "enabled"
169 elif si.authentication_state == "DENIED":
170 subscriber.status = "auth-failed"
171
172 # NOTE we save the subscriber only if:
173 # - the status has changed
174 # - we get a DHCPACK event
175 if cur_status != subscriber.status or si.dhcp_state == "DHCPACK":
176 logging.debug(
177 "MODEL_POLICY: updating subscriber",
178 onu_device=subscriber.onu_device,
179 authentication_state=si.authentication_state,
180 subscriber_status=subscriber.status)
181 if subscriber.status == "awaiting-auth":
182 delete_subscriber_ip(model_accessor, subscriber, si.ip_address)
183 subscriber.mac_address = ""
184 elif si.ip_address and si.mac_address:
185 update_subscriber_ip(model_accessor, subscriber, si.ip_address)
186 subscriber.mac_address = si.mac_address
187 subscriber.save_changed_fields(always_update_timestamp=True)
188 else:
189 logging.debug("MODEL_POLICY: subscriber status has not changed", onu_device=subscriber.onu_device,
190 authentication_state=si.authentication_state, subscriber_status=subscriber.status)