blob: cc1b10caed7353447e501eab29fffc474f0ecdf0 [file] [log] [blame]
Woojoong Kimf5dee562019-10-16 17:11:49 -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
17import os
18import sys
19
20import datetime
21import time
22
23from xossynchronizer.steps.syncstep import SyncStep
24from xossynchronizer.modelaccessor import ProgranServiceInstance, ENodeB, Handover, ServiceInstanceLink, MCordSubscriberInstance
25
26from xosconfig import Config
27from multistructlog import create_logger
28import requests
29from requests.auth import HTTPBasicAuth
30
31
32
33log = create_logger(Config().get('logging'))
34
35parentdir = os.path.join(os.path.dirname(__file__), "..")
36sys.path.insert(0, parentdir)
37sys.path.insert(0, os.path.dirname(__file__))
38from helpers import ProgranHelpers
39
40class SyncProgranServiceInstanceBack(SyncStep):
41 provides = [ProgranServiceInstance]
42
43 observes = ProgranServiceInstance
44
45
46 def call(self, failed=[], deletion=False):
47 """
48 Read profile from progran and save them in xos
49 """
50
51 if deletion == False:
52 # NOTE we won't it to run only after the delete has completed
53 return
54
55 log.debug("Reading profiles from progran")
56 onos = ProgranHelpers.get_progran_onos_info(self.model_accessor)
57 profile_url = "http://%s:%s/onos/progran/profile/" % (onos['url'], onos['port'])
58 r = requests.get(profile_url, auth=HTTPBasicAuth(onos['username'], onos['password']))
59 res = r.json()['ProfileArray']
60
61
62 # remove default profiles
63 res = [p for p in res if "Default" not in p['Name']]
64 pnames = [p['Name'] for p in res]
65 log.debug("Received Profiles: ", profiles=pnames)
66
67 field_mapping = {
68 'Name': 'name',
69 'Start': 'start',
70 'End': 'end',
71 }
72
73 field_transformations = {
74 'Start': ProgranHelpers.date_to_time,
75 'End': ProgranHelpers.date_to_time
76 }
77
78 handover_mapping = {
79 'A5Hysteresis': 'HysteresisA5',
80 'A3Hysteresis': 'HysteresisA3'
81 }
82
83 updated_profiles = []
84
85 for p in res:
86
87
88 # checking for profiles
89 try:
90 si = ProgranServiceInstance.objects.get(name=p['Name'])
91 log.debug("Profile %s already exists, updating it" % p['Name'])
92
93 except IndexError:
94 si = ProgranServiceInstance()
95
96 si.created_by = "Progran"
97
98 log.debug("Profile %s is new, creating it" % p['Name'])
99
100 if not si.is_new:
101 # update IMSI association
102 xos_imsis_for_profile = [i.subscriber_service_instance.leaf_model for i in si.provided_links.all()]
103 progran_imsis_for_profile = p['IMSIRuleArray']
104
105 log.debug("List of imsis for profile %s in XOS" % p["Name"], imsis=xos_imsis_for_profile)
106 log.debug("List of imsis for profile %s in ONOS" % p["Name"], imsis=progran_imsis_for_profile)
107
108 for i in xos_imsis_for_profile:
109 if not i.imsi_number in progran_imsis_for_profile:
110 log.debug("Removing Imsi %s from profile %s" % (i.imsi_number, p['Name']))
111
112 imsi_link = ServiceInstanceLink.objects.get(subscriber_service_instance_id=i.id)
113
114 # NOTE: this model has already been removed from the backend, no need to synchronize
115 imsi_link.backend_need_delete = False
116 imsi_link.no_sync = True
117 imsi_link.save() # we need to save it to avoid a synchronization loop
118
119 imsi_link.delete()
120 else:
121 # remove from imsi list coming from progran everything we already know about
122 progran_imsis_for_profile.remove(i.imsi_number)
123
124 for i in progran_imsis_for_profile:
125 log.debug("Adding Imsi %s to profile %s" % (i, p['Name']))
126 imsi = MCordSubscriberInstance.objects.get(imsi_number=i)
127 imsi_to_profile = ServiceInstanceLink(provider_service_instance=si,
128 subscriber_service_instance=imsi)
129 imsi_to_profile.save()
130
131 # if the model has not been synchronized yet, skip it
132 if not si.is_new and si.no_sync is False:
133 log.debug("Skipping profile %s as not synchronized" % p['Name'])
134 # NOTE add it to the removed profiles to avoid deletion (this is ugly, I know)
135 updated_profiles.append(si.name)
136 continue
137
138 # ugly fix
139 if 'AdmControl' in p.keys():
140 p['AdmControl'] = str(p['AdmControl'])
141
142 si = ProgranHelpers.update_fields(si, p, field_mapping, field_transformations)
143
144 # checking for handovers
145 handover_dict = p['Handover']
146 handover_dict = ProgranHelpers.convert_keys(handover_dict, handover_mapping)
147 del p['Handover']
148
149 if si.handover_id:
150 handover = si.handover
151 log.debug("handover already exists, updating it", handover=handover_dict)
152 else:
153 handover = Handover()
154 handover = ProgranHelpers.update_fields(handover, handover_dict)
155 log.debug("handover is new, creating it", handover=handover_dict)
156 handover.created_by = "Progran"
157
158 handover = ProgranHelpers.update_fields(handover, handover_dict)
159 handover.save()
160
161 # Assigning handover to profile
162 si.handover = handover
163
164 # si.backend_status = "OK"
165 # si.backend_code = 1
166
167 si.no_sync = True
168 si.previously_sync = True
169
170 if p["MMECfg"]:
171 si.mmeip = str(p["MMECfg"]["IPAddr"])
172 si.mmeport = str(p["MMECfg"]["Port"])
173
174 si.enacted = time.mktime(datetime.datetime.now().timetuple())
175
176 si.save()
177
178 updated_profiles.append(si.name)
179
180 existing_profiles = [p.name for p in ProgranServiceInstance.objects.all() if not p.is_new]
181 deleted_profiles = ProgranHelpers.list_diff(existing_profiles, updated_profiles)
182
183 if len(deleted_profiles) > 0:
184 for p in deleted_profiles:
185 si = ProgranServiceInstance.objects.get(name=p)
186 if si.created_by == 'XOS' and si.previously_sync == False:
187 # don't delete if the profile has been created by XOS and it hasn't been sync'ed yet
188 continue
189 # TODO delete also the associated Handover
190 log.debug("Profiles %s have been removed in progran, removing it from XOS" % str(p))
191 si.delete()