blob: c50773bcc14b704d4cf0ce1389f717eea97a23ea [file] [log] [blame]
Matteo Scandoloc1102a52018-02-01 17:26:04 -08001
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
Scott Bakerb06daad2019-02-04 15:46:54 -080023from xossynchronizer.steps.syncstep import SyncStep
24from xossynchronizer.modelaccessor import ProgranServiceInstance, ENodeB, Handover, ServiceInstanceLink, MCordSubscriberInstance
Matteo Scandoloc1102a52018-02-01 17:26:04 -080025
26from xosconfig import Config
27from multistructlog import create_logger
Matteo Scandoloc1102a52018-02-01 17:26:04 -080028import 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
Matteo Scandolo830403a2018-02-05 10:51:59 -080055 log.debug("Reading profiles from progran")
Scott Bakerb06daad2019-02-04 15:46:54 -080056 onos = ProgranHelpers.get_progran_onos_info(self.model_accessor)
Matteo Scandoloc1102a52018-02-01 17:26:04 -080057 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
Matteo Scandolo830403a2018-02-05 10:51:59 -080061
Matteo Scandoloc1102a52018-02-01 17:26:04 -080062 # remove default profiles
63 res = [p for p in res if "Default" not in p['Name']]
Matteo Scandolo78742162018-02-23 10:24:34 -080064 pnames = [p['Name'] for p in res]
65 log.debug("Received Profiles: ", profiles=pnames)
Matteo Scandoloc1102a52018-02-01 17:26:04 -080066
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
Matteo Scandolo830403a2018-02-05 10:51:59 -080087
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'])
Matteo Scandolof6b6ed22018-02-13 15:27:21 -080092
Matteo Scandolo830403a2018-02-05 10:51:59 -080093 except IndexError:
94 si = ProgranServiceInstance()
95
Matteo Scandolo830403a2018-02-05 10:51:59 -080096 si.created_by = "Progran"
97
98 log.debug("Profile %s is new, creating it" % p['Name'])
99
Matteo Scandolo72a38902018-02-15 09:13:31 -0800100 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:
Matteo Scandolo78742162018-02-23 10:24:34 -0800133 log.debug("Skipping profile %s as not synchronized" % p['Name'])
Matteo Scandolo72a38902018-02-15 09:13:31 -0800134 # NOTE add it to the removed profiles to avoid deletion (this is ugly, I know)
135 updated_profiles.append(si.name)
136 continue
137
Matteo Scandolo830403a2018-02-05 10:51:59 -0800138 si = ProgranHelpers.update_fields(si, p, field_mapping, field_transformations)
139
Matteo Scandoloc1102a52018-02-01 17:26:04 -0800140 # checking for handovers
141 handover_dict = p['Handover']
142 handover_dict = ProgranHelpers.convert_keys(handover_dict, handover_mapping)
143 del p['Handover']
144
Matteo Scandolo830403a2018-02-05 10:51:59 -0800145 if si.handover_id:
146 handover = si.handover
147 log.debug("handover already exists, updating it", handover=handover_dict)
148 else:
Matteo Scandoloc1102a52018-02-01 17:26:04 -0800149 handover = Handover()
150 handover = ProgranHelpers.update_fields(handover, handover_dict)
Matteo Scandolo830403a2018-02-05 10:51:59 -0800151 log.debug("handover is new, creating it", handover=handover_dict)
152 handover.created_by = "Progran"
Matteo Scandoloc1102a52018-02-01 17:26:04 -0800153
Matteo Scandolo830403a2018-02-05 10:51:59 -0800154 handover = ProgranHelpers.update_fields(handover, handover_dict)
Matteo Scandoloc1102a52018-02-01 17:26:04 -0800155 handover.save()
156
Matteo Scandolo830403a2018-02-05 10:51:59 -0800157 # Assigning handover to profile
Matteo Scandoloc1102a52018-02-01 17:26:04 -0800158 si.handover = handover
159
Matteo Scandolo830403a2018-02-05 10:51:59 -0800160 si.backend_status = "OK"
161 si.backend_code = 1
162
Matteo Scandolo16f61762018-02-13 12:00:51 -0800163 si.no_sync = True
164 si.previously_sync = True
165
Matteo Scandolo8c096ef2018-02-16 22:42:04 -0800166 if p["MMECfg"]:
167 si.mmeip = str(p["MMECfg"]["IPAddr"])
168 si.mmeport = str(p["MMECfg"]["Port"])
169
Matteo Scandolof6b6ed22018-02-13 15:27:21 -0800170 si.enacted = time.mktime(datetime.datetime.now().timetuple())
171
Matteo Scandoloc1102a52018-02-01 17:26:04 -0800172 si.save()
173
174 updated_profiles.append(si.name)
175
176 existing_profiles = [p.name for p in ProgranServiceInstance.objects.all() if not p.is_new]
177 deleted_profiles = ProgranHelpers.list_diff(existing_profiles, updated_profiles)
178
179 if len(deleted_profiles) > 0:
Matteo Scandoloc1102a52018-02-01 17:26:04 -0800180 for p in deleted_profiles:
181 si = ProgranServiceInstance.objects.get(name=p)
Matteo Scandolo830403a2018-02-05 10:51:59 -0800182 if si.created_by == 'XOS' and si.previously_sync == False:
183 # don't delete if the profile has been created by XOS and it hasn't been sync'ed yet
184 continue
Matteo Scandolof6b6ed22018-02-13 15:27:21 -0800185 # TODO delete also the associated Handover
Matteo Scandolo3effc6e2018-03-26 13:18:52 -0700186 log.debug("Profiles %s have been removed in progran, removing it from XOS" % str(p))
Matteo Scandoloc1102a52018-02-01 17:26:04 -0800187 si.delete()