3 # -------------------------------------------------------------------------
4 # Copyright (C) 2022 Wipro Limited.
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
10 # http://www.apache.org/licenses/LICENSE-2.0
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
18 # -------------------------------------------------------------------------
22 from conductor.common import rest
23 from conductor.i18n import _LE
25 from oslo_config import cfg
26 from oslo_log import log
30 LOG = log.getLogger(__name__)
35 cfg.StrOpt('table_prefix',
37 help='Data Store table prefix.'),
38 cfg.StrOpt('server_url',
39 default='https://controller:8443/dcae',
40 help='Base URL for DCAE, up to and not including '
41 'the version, and without a trailing slash.'),
42 cfg.StrOpt('dcae_rest_timeout',
44 help='Timeout for DCAE Rest Call'),
45 cfg.StrOpt('dcae_retries',
47 help='Number of retry for DCAE Rest Call'),
48 cfg.StrOpt('server_url_version',
50 help='The version of DCAE in v# format.'),
51 cfg.StrOpt('certificate_file',
52 default='certificate.pem',
53 help='SSL/TLS certificate file in pem format.'
54 'This certificate must be registered with the A&AI '
56 cfg.StrOpt('certificate_key_file',
57 default='certificate_key.pem',
58 help='Private Certificate Key file in pem format.'),
59 cfg.StrOpt('certificate_authority_bundle_file',
61 help='Certificate Authority Bundle file in pem format. '
62 'Must contain the appropriate trust chain for the '
64 cfg.StrOpt('username',
66 help='Username for DCAE'),
67 cfg.StrOpt('password',
69 help='Password for DCAE'),
70 cfg.StrOpt('get_slice_config_url',
72 help="url to get slice configuration from DCAE")
75 CONF.register_opts(DCAE_OPTS, group='dcae')
80 """DCAE Inventory Provider"""
85 self.base = self.conf.dcae.server_url.rstrip('/')
86 self.version = self.conf.dcae.server_url_version.rstrip('/')
87 self.cert = self.conf.dcae.certificate_file
88 self.key = self.conf.dcae.certificate_key_file
89 self.verify = self.conf.dcae.certificate_authority_bundle_file
90 self.timeout = self.conf.dcae.dcae_rest_timeout
91 self.retries = self.conf.dcae.dcae_retries
92 self.username = self.conf.dcae.username
93 self.password = self.conf.dcae.password
94 self._init_python_request()
98 """Perform any late initialization."""
99 # Initialize the Python requests
100 # self._init_python_request()
102 def _init_python_request(self):
106 "server_url": self.base,
108 "retries": self.retries,
110 "username": self.username,
112 "password": self.password,
114 "read_timeout": self.timeout,
116 "ca_bundle_file": self.verify,
119 self.rest = rest.REST(**kwargs)
121 def _dcae_versioned_path(self, path):
123 """Return a URL path with the DCAE version prepended"""
124 return '/{}/{}'.format(self.version, path.lstrip('/'))
126 def capacity_filter(self, candidates):
128 updated_candidateList = []
129 LOG.debug("from AAI ", candidates)
130 for candidate in candidates:
131 inventory_type = candidate.get('inventory_type')
132 candidate_id = candidate.get('candidate_id')
133 domain = candidate.get('domain')
134 response = self.get_dcae_response()
135 # max_no_of_connections = self.get_max_no_of_connections(response)
136 dLThpt = self.get_dLThpt(response, candidate_id)
137 uLThpt = self.get_uLThpt(response, candidate_id)
138 # max_no_of_pdu_sessions = self.get_max_no_of_pdu_sessions()
139 if inventory_type == 'nsi':
140 uLThpt_ServiceProfile = candidate.get('uLThptPerSlice')
141 dLThpt_ServiceProfile = candidate.get('dLThptPerSlice')
142 uLThpt_difference = self.get_difference(uLThpt_ServiceProfile, uLThpt)
143 dLThpt_difference = self.get_difference(dLThpt_ServiceProfile, dLThpt)
144 candidate['uLThpt_difference'] = uLThpt_difference
145 candidate['dLThpt_difference'] = dLThpt_difference
146 elif inventory_type == 'nssi' and (domain != 'tn_fh' and domain != 'tn_mh'):
147 uLThpt_SliceProfile = candidate.get('exp_data_rate_ul')
148 dLThpt_SliceProfile = candidate.get('exp_data_rate_dl')
149 uLThpt_difference = self.get_difference(uLThpt_SliceProfile, uLThpt)
150 dLThpt_difference = self.get_difference(dLThpt_SliceProfile, dLThpt)
151 candidate['uLThpt_difference'] = uLThpt_difference
152 candidate['dLThpt_difference'] = dLThpt_difference
153 # connections_difference = self.get_difference(max_no_of_pdu_sessions, max_no_of_connections)
154 elif inventory_type == 'nssi' and (domain == 'tn_fh' and domain == 'tn_mh'):
155 uLThpt_difference = 10
156 dLThpt_difference = 10
157 candidate['uLThpt_difference'] = uLThpt_difference
158 candidate['dLThpt_difference'] = dLThpt_difference
160 LOG.debug("No difference attribute was added to the candidate")
161 candidatesList.update(candidate)
162 LOG.debug("capacity filter ", candidatesList)
163 updated_candidateList.append(candidatesList)
164 LOG.debug("updated candidate list ", updated_candidateList)
165 return updated_candidateList
166 # def get_max_no_of_connections(self, response, candidate_id)
167 # responseJson = json.loads(response)
168 # maxNoConns = responseJson['sliceConfigDetails'][candidate_id]['aggregatedConfig']['maxNumberOfConns']
171 def get_uLThpt(self, response, candidate_id):
172 responseJson = json.loads(response)
173 configDetails = responseJson["sliceConfigDetails"]
174 for i in range(len(configDetails)):
175 if configDetails[i]["sliceIdentifier"] == candidate_id:
176 aggregatedConfig = configDetails[i]['aggregatedConfig']
177 uLThpt = aggregatedConfig.get("uLThptPerSlice")
180 def get_dLThpt(self, response, candidate_id):
181 responseJson = json.loads(response)
182 configDetails = responseJson["sliceConfigDetails"]
183 for i in range(len(configDetails)):
184 if configDetails[i]["sliceIdentifier"] == candidate_id:
185 aggregatedConfig = configDetails[i]['aggregatedConfig']
186 dLThpt = aggregatedConfig.get("dLThptPerSlice")
189 def get_difference(self, attribute1, attribute2):
190 LOG.debug("Computing the difference between two attributes")
191 difference = attribute1 - attribute2
194 def _request(self, method='get', path='/', data=None, context=None, value=None):
196 """Performs HTTP request"""
199 'X-FromAppId': 'CONDUCTOR',
200 'X-TransactionId': str(uuid.uuid4()),
208 "content_type": "application/json"
210 start_time = time.time()
211 response = self.rest.request(**kwargs)
212 elapsed = time.time() - start_time
213 LOG.debug("Total time for DCAE request ({0:}: {1:}): {2:.3f} sec".format(context, value, elapsed))
215 LOG.error(_LE("No response from DCAE ({}: {})").format(context, value))
216 elif response.status_code != 200:
217 LOG.error(_LE("DCAE request ({}: {}) returned HTTP status {} {},"
218 "link: {}{}").format(context, value, response.status_code, response.reason, self.base, path))
221 def get_dcae_response(self):
222 path = self.conf.dcae.get_slice_config_url
223 dcae_response = self._request('get', path, data=None)
224 if dcae_response is None or dcae_response.status_code != 200: