blob: c70e384d52b151457c7e27d4301e692e116233a5 [file] [log] [blame]
tiernof27c79b2018-03-12 17:08:42 +01001#! /usr/bin/python3
2# -*- coding: utf-8 -*-
3
tiernod125caf2018-11-22 16:05:54 +00004# 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
13# implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
tiernof27c79b2018-03-12 17:08:42 +010017import getopt
18import sys
19import requests
tiernof27c79b2018-03-12 17:08:42 +010020import json
21import logging
22import yaml
tierno2236d202018-05-16 19:05:16 +020023# import json
tiernoc32ba4a2018-05-24 18:06:41 +020024# import tarfile
25from time import sleep
tiernoff6485d2018-11-28 17:19:46 +000026from random import randint
tiernoc32ba4a2018-05-24 18:06:41 +020027import os
tiernoff6485d2018-11-28 17:19:46 +000028from sys import stderr
tiernof27c79b2018-03-12 17:08:42 +010029
30__author__ = "Alfonso Tierno, alfonso.tiernosepulveda@telefonica.com"
31__date__ = "$2018-03-01$"
gcalvino337ec512018-07-30 10:30:13 +020032__version__ = "0.3"
33version_date = "Oct 2018"
tiernof27c79b2018-03-12 17:08:42 +010034
35
36def usage():
37 print("Usage: ", sys.argv[0], "[options]")
tiernoc32ba4a2018-05-24 18:06:41 +020038 print(" Performs system tests over running NBI. It can be used for real OSM test using option '--test-osm'")
tiernoff6485d2018-11-28 17:19:46 +000039 print(" If this is the case env variables 'OSMNBITEST_VIM_NAME' must be supplied to create a VIM if not exist "
tiernoc32ba4a2018-05-24 18:06:41 +020040 "where deployment is done")
41 print("OPTIONS")
tiernof27c79b2018-03-12 17:08:42 +010042 print(" -h|--help: shows this help")
tiernoc32ba4a2018-05-24 18:06:41 +020043 print(" --insecure: Allows non trusted https NBI server")
44 print(" --list: list available tests")
45 print(" --manual-check: Deployment tests stop after deployed to allow manual inspection. Only make sense with "
46 "'--test-osm'")
47 print(" -p|--password PASSWORD: NBI access password. 'admin' by default")
48 print(" ---project PROJECT: NBI access project. 'admin' by default")
49 print(" --test TEST[,...]: Execute only a test or a comma separated list of tests")
50 print(" --params key=val: params to the previous test. key can be vnfd-files, nsd-file, ns-name, ns-config")
51 print(" --test-osm: If missing this test is intended for NBI only, no other OSM components are expected. Use "
52 "this flag to test the system. LCM and RO components are expected to be up and running")
53 print(" --timeout TIMEOUT: General NBI timeout, by default {}s".format(timeout))
54 print(" --timeout-deploy TIMEOUT: Timeout used for getting NS deployed, by default {}s".format(timeout_deploy))
55 print(" --timeout-configure TIMEOUT: Timeout used for getting NS deployed and configured,"
56 " by default {}s".format(timeout_configure))
57 print(" -u|--user USERNAME: NBI access username. 'admin' by default")
58 print(" --url URL: complete NBI server URL. 'https//localhost:9999/osm' by default")
tiernof27c79b2018-03-12 17:08:42 +010059 print(" -v|--verbose print debug information, can be used several times")
tiernoc32ba4a2018-05-24 18:06:41 +020060 print(" --no-verbose remove verbosity")
61 print(" --version: prints current version")
62 print("ENV variables used for real deployment tests with option osm-test.")
63 print(" export OSMNBITEST_VIM_NAME=vim-name")
64 print(" export OSMNBITEST_VIM_URL=vim-url")
65 print(" export OSMNBITEST_VIM_TYPE=vim-type")
66 print(" export OSMNBITEST_VIM_TENANT=vim-tenant")
67 print(" export OSMNBITEST_VIM_USER=vim-user")
68 print(" export OSMNBITEST_VIM_PASSWORD=vim-password")
69 print(" export OSMNBITEST_VIM_CONFIG=\"vim-config\"")
70 print(" export OSMNBITEST_NS_NAME=\"vim-config\"")
tiernof27c79b2018-03-12 17:08:42 +010071 return
72
73
74r_header_json = {"Content-type": "application/json"}
tiernof717cbe2018-12-03 16:35:42 +000075headers_json = {"Content-type": "application/json", "Accept": "application/json"}
tiernof27c79b2018-03-12 17:08:42 +010076r_header_yaml = {"Content-type": "application/yaml"}
tiernof717cbe2018-12-03 16:35:42 +000077headers_yaml = {"Content-type": "application/yaml", "Accept": "application/yaml"}
tiernof27c79b2018-03-12 17:08:42 +010078r_header_text = {"Content-type": "text/plain"}
79r_header_octect = {"Content-type": "application/octet-stream"}
tiernof717cbe2018-12-03 16:35:42 +000080headers_text = {"Accept": "text/plain,application/yaml"}
tiernof27c79b2018-03-12 17:08:42 +010081r_header_zip = {"Content-type": "application/zip"}
tiernof717cbe2018-12-03 16:35:42 +000082headers_zip = {"Accept": "application/zip,application/yaml"}
83headers_zip_yaml = {"Accept": "application/yaml", "Content-type": "application/zip"}
84r_headers_yaml_location_vnfd = {"Location": "/vnfpkgm/v1/vnf_packages_content/", "Content-Type": "application/yaml"}
85r_headers_yaml_location_nsd = {"Location": "/nsd/v1/ns_descriptors_content/", "Content-Type": "application/yaml"}
86r_headers_yaml_location_nst = {"Location": "/nst/v1/netslice_templates_content", "Content-Type": "application/yaml"}
87r_headers_yaml_location_nslcmop = {"Location": "nslcm/v1/ns_lcm_op_occs/", "Content-Type": "application/yaml"}
Felipe Vicens09e65422019-01-22 15:06:46 +010088r_headers_yaml_location_nsilcmop = {"Location": "/osm/nsilcm/v1/nsi_lcm_op_occs/", "Content-Type": "application/yaml"}
tiernof27c79b2018-03-12 17:08:42 +010089
90# test ones authorized
91test_authorized_list = (
tierno2236d202018-05-16 19:05:16 +020092 ("AU1", "Invalid vnfd id", "GET", "/vnfpkgm/v1/vnf_packages/non-existing-id",
93 headers_json, None, 404, r_header_json, "json"),
94 ("AU2", "Invalid nsd id", "GET", "/nsd/v1/ns_descriptors/non-existing-id",
95 headers_yaml, None, 404, r_header_yaml, "yaml"),
96 ("AU3", "Invalid nsd id", "DELETE", "/nsd/v1/ns_descriptors_content/non-existing-id",
97 headers_yaml, None, 404, r_header_yaml, "yaml"),
tierno0f98af52018-03-19 10:28:22 +010098)
tiernoc32ba4a2018-05-24 18:06:41 +020099timeout = 120 # general timeout
100timeout_deploy = 60*10 # timeout for NS deploying without charms
101timeout_configure = 60*20 # timeout for NS deploying and configuring
tiernof27c79b2018-03-12 17:08:42 +0100102
tierno2236d202018-05-16 19:05:16 +0200103
tiernof27c79b2018-03-12 17:08:42 +0100104class TestException(Exception):
105 pass
106
107
108class TestRest:
tiernoc32ba4a2018-05-24 18:06:41 +0200109 def __init__(self, url_base, header_base=None, verify=False, user="admin", password="admin", project="admin"):
tiernof27c79b2018-03-12 17:08:42 +0100110 self.url_base = url_base
tiernoc32ba4a2018-05-24 18:06:41 +0200111 if header_base is None:
112 self.header_base = {}
113 else:
114 self.header_base = header_base.copy()
tiernof27c79b2018-03-12 17:08:42 +0100115 self.s = requests.session()
tiernoc32ba4a2018-05-24 18:06:41 +0200116 self.s.headers = self.header_base
tiernof27c79b2018-03-12 17:08:42 +0100117 self.verify = verify
tiernoc32ba4a2018-05-24 18:06:41 +0200118 self.token = False
119 self.user = user
120 self.password = password
121 self.project = project
122 self.vim_id = None
tierno0f98af52018-03-19 10:28:22 +0100123 # contains ID of tests obtained from Location response header. "" key contains last obtained id
tiernoff6485d2018-11-28 17:19:46 +0000124 self.last_id = ""
tierno36ec8602018-11-02 17:27:11 +0100125 self.test_name = None
tiernoff6485d2018-11-28 17:19:46 +0000126 self.step = 0 # number of subtest under test
127 self.passed_tests = 0
128 self.failed_tests = 0
tiernof27c79b2018-03-12 17:08:42 +0100129
tiernoff6485d2018-11-28 17:19:46 +0000130 def set_test_name(self, test_name):
131 self.test_name = test_name
132 self.step = 0
133 self.last_id = ""
delacruzramoc061f562019-04-05 11:00:02 +0200134
tiernof27c79b2018-03-12 17:08:42 +0100135 def set_header(self, header):
136 self.s.headers.update(header)
137
tierno36ec8602018-11-02 17:27:11 +0100138 def set_tet_name(self, test_name):
139 self.test_name = test_name
140
tiernocd54a4a2018-09-12 16:40:35 +0200141 def unset_header(self, key):
142 if key in self.s.headers:
143 del self.s.headers[key]
144
tiernoff6485d2018-11-28 17:19:46 +0000145 def test(self, description, method, url, headers, payload, expected_codes, expected_headers,
146 expected_payload, store_file=None, pooling=False):
tiernof27c79b2018-03-12 17:08:42 +0100147 """
tierno0f98af52018-03-19 10:28:22 +0100148 Performs an http request and check http code response. Exit if different than allowed. It get the returned id
149 that can be used by following test in the URL with {name} where name is the name of the test
tierno0f98af52018-03-19 10:28:22 +0100150 :param description: description of the test
tiernof27c79b2018-03-12 17:08:42 +0100151 :param method: HTTP method: GET,PUT,POST,DELETE,...
152 :param url: complete URL or relative URL
153 :param headers: request headers to add to the base headers
154 :param payload: Can be a dict, transformed to json, a text or a file if starts with '@'
155 :param expected_codes: expected response codes, can be int, int tuple or int range
156 :param expected_headers: expected response headers, dict with key values
tierno49e42062018-10-24 12:50:53 +0200157 :param expected_payload: expected payload, 0 if empty, 'yaml', 'json', 'text', 'zip', 'octet-stream'
158 :param store_file: filename to store content
tiernoff6485d2018-11-28 17:19:46 +0000159 :param pooling: if True do not count neither log this test. Because a pooling is done with many equal requests
tierno0f98af52018-03-19 10:28:22 +0100160 :return: requests response
tiernof27c79b2018-03-12 17:08:42 +0100161 """
tiernoc32ba4a2018-05-24 18:06:41 +0200162 r = None
tiernof27c79b2018-03-12 17:08:42 +0100163 try:
164 if not self.s:
165 self.s = requests.session()
tierno0f98af52018-03-19 10:28:22 +0100166 # URL
tiernof27c79b2018-03-12 17:08:42 +0100167 if not url:
168 url = self.url_base
169 elif not url.startswith("http"):
170 url = self.url_base + url
tierno0f98af52018-03-19 10:28:22 +0100171
tiernoff6485d2018-11-28 17:19:46 +0000172 # replace url <> with the last ID
173 url = url.replace("<>", self.last_id)
tiernof27c79b2018-03-12 17:08:42 +0100174 if payload:
175 if isinstance(payload, str):
176 if payload.startswith("@"):
177 mode = "r"
178 file_name = payload[1:]
179 if payload.startswith("@b"):
180 mode = "rb"
181 file_name = payload[2:]
182 with open(file_name, mode) as f:
183 payload = f.read()
184 elif isinstance(payload, dict):
185 payload = json.dumps(payload)
tierno2236d202018-05-16 19:05:16 +0200186
tiernoff6485d2018-11-28 17:19:46 +0000187 if not pooling:
188 test_description = "Test {}{} {} {} {}".format(self.test_name, self.step, description, method, url)
tiernoc32ba4a2018-05-24 18:06:41 +0200189 logger.warning(test_description)
tiernoff6485d2018-11-28 17:19:46 +0000190 self.step += 1
tiernof27c79b2018-03-12 17:08:42 +0100191 stream = False
tierno49e42062018-10-24 12:50:53 +0200192 if expected_payload in ("zip", "octet-string") or store_file:
193 stream = True
tiernobee085c2018-12-12 17:03:04 +0000194 __retry = 0
195 while True:
196 try:
197 r = getattr(self.s, method.lower())(url, data=payload, headers=headers, verify=self.verify,
198 stream=stream)
199 break
200 except requests.exceptions.ConnectionError as e:
201 if __retry == 2:
202 raise
203 logger.error("Exception {}. Retrying".format(e))
204 __retry += 1
205
tierno49e42062018-10-24 12:50:53 +0200206 if expected_payload in ("zip", "octet-string") or store_file:
207 logger.debug("RX {}".format(r.status_code))
208 else:
209 logger.debug("RX {}: {}".format(r.status_code, r.text))
tiernof27c79b2018-03-12 17:08:42 +0100210
211 # check response
212 if expected_codes:
213 if isinstance(expected_codes, int):
214 expected_codes = (expected_codes,)
215 if r.status_code not in expected_codes:
216 raise TestException(
217 "Got status {}. Expected {}. {}".format(r.status_code, expected_codes, r.text))
218
219 if expected_headers:
220 for header_key, header_val in expected_headers.items():
221 if header_key.lower() not in r.headers:
222 raise TestException("Header {} not present".format(header_key))
223 if header_val and header_val.lower() not in r.headers[header_key]:
224 raise TestException("Header {} does not contain {} but {}".format(header_key, header_val,
225 r.headers[header_key]))
226
227 if expected_payload is not None:
228 if expected_payload == 0 and len(r.content) > 0:
229 raise TestException("Expected empty payload")
230 elif expected_payload == "json":
231 try:
232 r.json()
233 except Exception as e:
234 raise TestException("Expected json response payload, but got Exception {}".format(e))
235 elif expected_payload == "yaml":
236 try:
237 yaml.safe_load(r.text)
238 except Exception as e:
239 raise TestException("Expected yaml response payload, but got Exception {}".format(e))
tierno49e42062018-10-24 12:50:53 +0200240 elif expected_payload in ("zip", "octet-string"):
tiernof27c79b2018-03-12 17:08:42 +0100241 if len(r.content) == 0:
242 raise TestException("Expected some response payload, but got empty")
243 # try:
244 # tar = tarfile.open(None, 'r:gz', fileobj=r.raw)
245 # for tarinfo in tar:
246 # tarname = tarinfo.name
247 # print(tarname)
248 # except Exception as e:
249 # raise TestException("Expected zip response payload, but got Exception {}".format(e))
250 elif expected_payload == "text":
251 if len(r.content) == 0:
252 raise TestException("Expected some response payload, but got empty")
tierno2236d202018-05-16 19:05:16 +0200253 # r.text
tierno49e42062018-10-24 12:50:53 +0200254 if store_file:
255 with open(store_file, 'wb') as fd:
256 for chunk in r.iter_content(chunk_size=128):
257 fd.write(chunk)
258
tierno0f98af52018-03-19 10:28:22 +0100259 location = r.headers.get("Location")
260 if location:
261 _id = location[location.rfind("/") + 1:]
262 if _id:
tiernoff6485d2018-11-28 17:19:46 +0000263 self.last_id = str(_id)
264 if not pooling:
265 self.passed_tests += 1
tiernof27c79b2018-03-12 17:08:42 +0100266 return r
267 except TestException as e:
tiernoff6485d2018-11-28 17:19:46 +0000268 self.failed_tests += 1
tiernoc32ba4a2018-05-24 18:06:41 +0200269 r_status_code = None
270 r_text = None
271 if r:
272 r_status_code = r.status_code
273 r_text = r.text
274 logger.error("{} \nRX code{}: {}".format(e, r_status_code, r_text))
tiernoff6485d2018-11-28 17:19:46 +0000275 return None
276 # exit(1)
tiernof27c79b2018-03-12 17:08:42 +0100277 except IOError as e:
tiernoff6485d2018-11-28 17:19:46 +0000278 if store_file:
279 logger.error("Cannot open file {}: {}".format(store_file, e))
280 else:
281 logger.error("Exception: {}".format(e), exc_info=True)
282 self.failed_tests += 1
283 return None
284 # exit(1)
tiernobee085c2018-12-12 17:03:04 +0000285 except requests.exceptions.RequestException as e:
286 logger.error("Exception: {}".format(e))
tiernof27c79b2018-03-12 17:08:42 +0100287
tiernoc32ba4a2018-05-24 18:06:41 +0200288 def get_autorization(self): # user=None, password=None, project=None):
289 if self.token: # and self.user == user and self.password == password and self.project == project:
290 return
291 # self.user = user
292 # self.password = password
293 # self.project = project
tiernoff6485d2018-11-28 17:19:46 +0000294 r = self.test("Obtain token", "POST", "/admin/v1/tokens", headers_json,
tiernoc32ba4a2018-05-24 18:06:41 +0200295 {"username": self.user, "password": self.password, "project_id": self.project},
tiernocd54a4a2018-09-12 16:40:35 +0200296 (200, 201), r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000297 if not r:
298 return
tiernoc32ba4a2018-05-24 18:06:41 +0200299 response = r.json()
300 self.token = response["id"]
301 self.set_header({"Authorization": "Bearer {}".format(self.token)})
302
tiernocd54a4a2018-09-12 16:40:35 +0200303 def remove_authorization(self):
304 if self.token:
tiernoff6485d2018-11-28 17:19:46 +0000305 self.test("Delete token", "DELETE", "/admin/v1/tokens/{}".format(self.token), headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200306 None, (200, 201, 204), None, None)
307 self.token = None
308 self.unset_header("Authorization")
309
tiernoc32ba4a2018-05-24 18:06:41 +0200310 def get_create_vim(self, test_osm):
311 if self.vim_id:
312 return self.vim_id
313 self.get_autorization()
314 if test_osm:
315 vim_name = os.environ.get("OSMNBITEST_VIM_NAME")
316 if not vim_name:
317 raise TestException(
318 "Needed to define OSMNBITEST_VIM_XXX variables to create a real VIM for deployment")
319 else:
320 vim_name = "fakeVim"
321 # Get VIM
tiernoff6485d2018-11-28 17:19:46 +0000322 r = self.test("Get VIM ID", "GET", "/admin/v1/vim_accounts?name={}".format(vim_name), headers_json,
tiernoc32ba4a2018-05-24 18:06:41 +0200323 None, 200, r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000324 if not r:
325 return
tiernoc32ba4a2018-05-24 18:06:41 +0200326 vims = r.json()
327 if vims:
328 return vims[0]["_id"]
329 # Add VIM
330 if test_osm:
331 # check needed environ parameters:
332 if not os.environ.get("OSMNBITEST_VIM_URL") or not os.environ.get("OSMNBITEST_VIM_TENANT"):
333 raise TestException("Env OSMNBITEST_VIM_URL and OSMNBITEST_VIM_TENANT are needed for create a real VIM"
334 " to deploy on whit the --test-osm option")
335 vim_data = "{{schema_version: '1.0', name: '{}', vim_type: {}, vim_url: '{}', vim_tenant_name: '{}', "\
336 "vim_user: {}, vim_password: {}".format(vim_name,
337 os.environ.get("OSMNBITEST_VIM_TYPE", "openstack"),
338 os.environ.get("OSMNBITEST_VIM_URL"),
339 os.environ.get("OSMNBITEST_VIM_TENANT"),
340 os.environ.get("OSMNBITEST_VIM_USER"),
341 os.environ.get("OSMNBITEST_VIM_PASSWORD"))
342 if os.environ.get("OSMNBITEST_VIM_CONFIG"):
343 vim_data += " ,config: {}".format(os.environ.get("OSMNBITEST_VIM_CONFIG"))
344 vim_data += "}"
345 else:
346 vim_data = "{schema_version: '1.0', name: fakeVim, vim_type: openstack, vim_url: 'http://10.11.12.13/fake'"\
347 ", vim_tenant_name: 'vimtenant', vim_user: vimuser, vim_password: vimpassword}"
tiernoff6485d2018-11-28 17:19:46 +0000348 self.test("Create VIM", "POST", "/admin/v1/vim_accounts", headers_yaml, vim_data,
tiernobdebce92019-07-01 15:36:49 +0000349 (201, 202), {"Location": "/admin/v1/vim_accounts/", "Content-Type": "application/yaml"}, "yaml")
tiernoff6485d2018-11-28 17:19:46 +0000350 return self.last_id
351
352 def print_results(self):
353 print("\n\n\n--------------------------------------------")
354 print("TEST RESULTS: Total: {}, Passed: {}, Failed: {}".format(self.passed_tests + self.failed_tests,
355 self.passed_tests, self.failed_tests))
356 print("--------------------------------------------")
357
358 def wait_until_delete(self, url_op, timeout_delete):
359 """
360 Make a pooling until topic is not present, because of deleted
361 :param url_op:
362 :param timeout_delete:
363 :return:
364 """
365 description = "Wait to topic being deleted"
366 test_description = "Test {}{} {} {} {}".format(self.test_name, self.step, description, "GET", url_op)
367 logger.warning(test_description)
368 self.step += 1
369
370 wait = timeout_delete
371 while wait >= 0:
tierno55ba2e62018-12-11 17:22:22 +0000372 r = self.test(description, "GET", url_op, headers_yaml, None, (200, 404), None, r_header_yaml, "yaml",
373 pooling=True)
tiernoff6485d2018-11-28 17:19:46 +0000374 if not r:
375 return
376 if r.status_code == 404:
377 self.passed_tests += 1
378 break
379 elif r.status_code == 200:
380 wait -= 5
381 sleep(5)
382 else:
383 raise TestException("Topic is not deleted after {} seconds".format(timeout_delete))
384 self.failed_tests += 1
385
386 def wait_operation_ready(self, ns_nsi, opp_id, timeout, expected_fail=False):
387 """
388 Wait until nslcmop or nsilcmop finished
389 :param ns_nsi: "ns" o "nsi"
390 :param opp_id: Id o fthe operation
391 :param timeout:
392 :param expected_fail:
393 :return: None. Updates passed/failed_tests
394 """
395 if ns_nsi == "ns":
396 url_op = "/nslcm/v1/ns_lcm_op_occs/{}".format(opp_id)
397 else:
398 url_op = "/nsilcm/v1/nsi_lcm_op_occs/{}".format(opp_id)
399 description = "Wait to {} lcm operation complete".format(ns_nsi)
400 test_description = "Test {}{} {} {} {}".format(self.test_name, self.step, description, "GET", url_op)
401 logger.warning(test_description)
402 self.step += 1
403 wait = timeout
404 while wait >= 0:
405 r = self.test(description, "GET", url_op, headers_json, None,
406 200, r_header_json, "json", pooling=True)
407 if not r:
408 return
409 nslcmop = r.json()
410 if "COMPLETED" in nslcmop["operationState"]:
411 if expected_fail:
tiernobee085c2018-12-12 17:03:04 +0000412 logger.error("NS terminate has success, expecting failing: {}".format(nslcmop["detailed-status"]))
tiernoff6485d2018-11-28 17:19:46 +0000413 self.failed_tests += 1
414 else:
415 self.passed_tests += 1
416 break
417 elif "FAILED" in nslcmop["operationState"]:
418 if not expected_fail:
419 logger.error("NS terminate has failed: {}".format(nslcmop["detailed-status"]))
tiernobee085c2018-12-12 17:03:04 +0000420 self.failed_tests += 1
tiernoff6485d2018-11-28 17:19:46 +0000421 else:
422 self.passed_tests += 1
423 break
424
425 print(".", end="", file=stderr)
426 wait -= 10
427 sleep(10)
428 else:
429 self.failed_tests += 1
430 logger.error("NS instantiate is not terminate after {} seconds".format(timeout))
431 return
432 print("", file=stderr)
tiernoc32ba4a2018-05-24 18:06:41 +0200433
434
435class TestNonAuthorized:
tiernobee085c2018-12-12 17:03:04 +0000436 description = "Test invalid URLs. methods and no authorization"
tiernoc32ba4a2018-05-24 18:06:41 +0200437
438 @staticmethod
tiernocd54a4a2018-09-12 16:40:35 +0200439 def run(engine, test_osm, manual_check, test_params=None):
tiernoff6485d2018-11-28 17:19:46 +0000440 engine.set_test_name("NonAuth")
tiernocd54a4a2018-09-12 16:40:35 +0200441 engine.remove_authorization()
tiernoc32ba4a2018-05-24 18:06:41 +0200442 test_not_authorized_list = (
tiernoff6485d2018-11-28 17:19:46 +0000443 ("Invalid token", "GET", "/admin/v1/users", headers_json, None, 401, r_header_json, "json"),
444 ("Invalid URL", "POST", "/admin/v1/nonexist", headers_yaml, None, 405, r_header_yaml, "yaml"),
445 ("Invalid version", "DELETE", "/admin/v2/users", headers_yaml, None, 405, r_header_yaml, "yaml"),
tiernoc32ba4a2018-05-24 18:06:41 +0200446 )
447 for t in test_not_authorized_list:
448 engine.test(*t)
449
450
tiernocd54a4a2018-09-12 16:40:35 +0200451class TestUsersProjects:
452 description = "test project and user creation"
453
454 @staticmethod
455 def run(engine, test_osm, manual_check, test_params=None):
tiernoff6485d2018-11-28 17:19:46 +0000456 engine.set_test_name("UserProject")
tiernocd54a4a2018-09-12 16:40:35 +0200457 engine.get_autorization()
tiernoff6485d2018-11-28 17:19:46 +0000458 engine.test("Create project non admin", "POST", "/admin/v1/projects", headers_json, {"name": "P1"},
tiernocd54a4a2018-09-12 16:40:35 +0200459 (201, 204), {"Location": "/admin/v1/projects/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000460 engine.test("Create project admin", "POST", "/admin/v1/projects", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200461 {"name": "Padmin", "admin": True}, (201, 204),
462 {"Location": "/admin/v1/projects/", "Content-Type": "application/json"}, "json")
delacruzramoc061f562019-04-05 11:00:02 +0200463 engine.test("Create project bad format", "POST", "/admin/v1/projects", headers_json, {"name": 1}, (400, 422),
tiernocd54a4a2018-09-12 16:40:35 +0200464 r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000465 engine.test("Create user with bad project", "POST", "/admin/v1/users", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200466 {"username": "U1", "projects": ["P1", "P2", "Padmin"], "password": "pw1"}, 409,
467 r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000468 engine.test("Create user with bad project and force", "POST", "/admin/v1/users?FORCE=True", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200469 {"username": "U1", "projects": ["P1", "P2", "Padmin"], "password": "pw1"}, 201,
470 {"Location": "/admin/v1/users/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000471 engine.test("Create user 2", "POST", "/admin/v1/users", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200472 {"username": "U2", "projects": ["P1"], "password": "pw2"}, 201,
473 {"Location": "/admin/v1/users/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000474 engine.test("Edit user U1, delete P2 project", "PATCH", "/admin/v1/users/U1", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200475 {"projects": {"$'P2'": None}}, 204, None, None)
tiernoff6485d2018-11-28 17:19:46 +0000476 res = engine.test("Check user U1, contains the right projects", "GET", "/admin/v1/users/U1",
tiernocd54a4a2018-09-12 16:40:35 +0200477 headers_json, None, 200, None, json)
tiernoff6485d2018-11-28 17:19:46 +0000478 if res:
479 u1 = res.json()
480 # print(u1)
481 expected_projects = ["P1", "Padmin"]
482 if u1["projects"] != expected_projects:
483 logger.error("User content projects '{}' different than expected '{}'. Edition has not done"
484 " properly".format(u1["projects"], expected_projects))
485 engine.failed_tests += 1
tiernocd54a4a2018-09-12 16:40:35 +0200486
tiernoff6485d2018-11-28 17:19:46 +0000487 engine.test("Edit user U1, set Padmin as default project", "PUT", "/admin/v1/users/U1", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200488 {"projects": {"$'Padmin'": None, "$+[0]": "Padmin"}}, 204, None, None)
tiernoff6485d2018-11-28 17:19:46 +0000489 res = engine.test("Check user U1, contains the right projects", "GET", "/admin/v1/users/U1",
tiernocd54a4a2018-09-12 16:40:35 +0200490 headers_json, None, 200, None, json)
tiernoff6485d2018-11-28 17:19:46 +0000491 if res:
492 u1 = res.json()
493 # print(u1)
494 expected_projects = ["Padmin", "P1"]
495 if u1["projects"] != expected_projects:
496 logger.error("User content projects '{}' different than expected '{}'. Edition has not done"
497 " properly".format(u1["projects"], expected_projects))
498 engine.failed_tests += 1
tiernocd54a4a2018-09-12 16:40:35 +0200499
tiernoff6485d2018-11-28 17:19:46 +0000500 engine.test("Edit user U1, change password", "PATCH", "/admin/v1/users/U1", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200501 {"password": "pw1_new"}, 204, None, None)
502
tiernoff6485d2018-11-28 17:19:46 +0000503 engine.test("Change to project P1 non existing", "POST", "/admin/v1/tokens/", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200504 {"project_id": "P1"}, 401, r_header_json, "json")
505
tiernoff6485d2018-11-28 17:19:46 +0000506 res = engine.test("Change to user U1 project P1", "POST", "/admin/v1/tokens", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200507 {"username": "U1", "password": "pw1_new", "project_id": "P1"}, (200, 201),
508 r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000509 if res:
510 response = res.json()
511 engine.set_header({"Authorization": "Bearer {}".format(response["id"])})
tiernocd54a4a2018-09-12 16:40:35 +0200512
tiernoff6485d2018-11-28 17:19:46 +0000513 engine.test("Edit user projects non admin", "PUT", "/admin/v1/users/U1", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200514 {"projects": {"$'P1'": None}}, 401, r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000515 engine.test("Add new project non admin", "POST", "/admin/v1/projects", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200516 {"name": "P2"}, 401, r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000517 engine.test("Add new user non admin", "POST", "/admin/v1/users", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200518 {"username": "U3", "projects": ["P1"], "password": "pw3"}, 401,
519 r_header_json, "json")
520
tiernoff6485d2018-11-28 17:19:46 +0000521 res = engine.test("Change to user U1 project Padmin", "POST", "/admin/v1/tokens", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200522 {"project_id": "Padmin"}, (200, 201), r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000523 if res:
524 response = res.json()
525 engine.set_header({"Authorization": "Bearer {}".format(response["id"])})
tiernocd54a4a2018-09-12 16:40:35 +0200526
tiernoff6485d2018-11-28 17:19:46 +0000527 engine.test("Add new project admin", "POST", "/admin/v1/projects", headers_json, {"name": "P2"},
tiernocd54a4a2018-09-12 16:40:35 +0200528 (201, 204), {"Location": "/admin/v1/projects/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000529 engine.test("Add new user U3 admin", "POST", "/admin/v1/users",
tiernocd54a4a2018-09-12 16:40:35 +0200530 headers_json, {"username": "U3", "projects": ["P2"], "password": "pw3"}, (201, 204),
531 {"Location": "/admin/v1/users/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000532 engine.test("Edit user projects admin", "PUT", "/admin/v1/users/U3", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200533 {"projects": ["P2"]}, 204, None, None)
534
tiernoff6485d2018-11-28 17:19:46 +0000535 engine.test("Delete project P2 conflict", "DELETE", "/admin/v1/projects/P2", headers_json, None, 409,
tiernocd54a4a2018-09-12 16:40:35 +0200536 r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000537 engine.test("Delete project P2 forcing", "DELETE", "/admin/v1/projects/P2?FORCE=True", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200538 None, 204, None, None)
539
tiernoff6485d2018-11-28 17:19:46 +0000540 engine.test("Delete user U1. Conflict deleting own user", "DELETE", "/admin/v1/users/U1", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200541 None, 409, r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000542 engine.test("Delete user U2", "DELETE", "/admin/v1/users/U2", headers_json, None, 204, None, None)
543 engine.test("Delete user U3", "DELETE", "/admin/v1/users/U3", headers_json, None, 204, None, None)
tiernocd54a4a2018-09-12 16:40:35 +0200544 # change to admin
545 engine.remove_authorization() # To force get authorization
546 engine.get_autorization()
delacruzramoc061f562019-04-05 11:00:02 +0200547 engine.test("Delete user U1 by Name", "DELETE", "/admin/v1/users/U1", headers_json, None, 204, None, None)
548 engine.test("Delete project P1 by Name", "DELETE", "/admin/v1/projects/P1", headers_json, None, 204, None, None)
549 engine.test("Delete project Padmin by Name", "DELETE", "/admin/v1/projects/Padmin", headers_json, None, 204,
tiernocd54a4a2018-09-12 16:40:35 +0200550 None, None)
551
delacruzramoc061f562019-04-05 11:00:02 +0200552 # BEGIN New Tests - Addressing Projects/Users by Name/ID
553 res = engine.test("Create new project P1", "POST", "/admin/v1/projects", headers_json, {"name": "P1"},
554 201, {"Location": "/admin/v1/projects/", "Content-Type": "application/json"}, "json")
555 if res:
556 pid1 = res.json()["id"]
557 # print("# pid =", pid1)
558 res = engine.test("Create new project P2", "POST", "/admin/v1/projects", headers_json, {"name": "P2"},
559 201, {"Location": "/admin/v1/projects/", "Content-Type": "application/json"}, "json")
560 if res:
561 pid2 = res.json()["id"]
562 # print("# pid =", pid2)
563 res = engine.test("Create new user U1", "POST", "/admin/v1/users", headers_json,
564 {"username": "U1", "projects": ["P1"], "password": "pw1"}, 201,
565 {"Location": "/admin/v1/users/", "Content-Type": "application/json"}, "json")
566 if res:
567 uid1 = res.json()["id"]
568 # print("# uid =", uid1)
569 res = engine.test("Create new user U2", "POST", "/admin/v1/users", headers_json,
570 {"username": "U2", "projects": ["P2"], "password": "pw2"}, 201,
571 {"Location": "/admin/v1/users/", "Content-Type": "application/json"}, "json")
572 if res:
573 uid2 = res.json()["id"]
574 # print("# uid =", uid2)
575 engine.test("Get Project P1 by Name", "GET", "/admin/v1/projects/P1", headers_json, None, 200, None, "json")
576 engine.test("Get Project P1 by ID", "GET", "/admin/v1/projects/"+pid1, headers_json, None, 200, None, "json")
577 engine.test("Get User U1 by Name", "GET", "/admin/v1/users/U1", headers_json, None, 200, None, "json")
578 engine.test("Get User U1 by ID", "GET", "/admin/v1/users/"+uid1, headers_json, None, 200, None, "json")
579 engine.test("Rename Project P1 by Name", "PUT", "/admin/v1/projects/P1", headers_json,
580 {"name": "P3"}, 204, None, None)
581 engine.test("Rename Project P2 by ID", "PUT", "/admin/v1/projects/"+pid2, headers_json,
582 {"name": "P4"}, 204, None, None)
583 engine.test("Rename User U1 by Name", "PUT", "/admin/v1/users/U1", headers_json,
584 {"username": "U3"}, 204, None, None)
585 engine.test("Rename User U2 by ID", "PUT", "/admin/v1/users/"+uid2, headers_json,
586 {"username": "U4"}, 204, None, None)
587 engine.test("Get Project P1 by new Name", "GET", "/admin/v1/projects/P3", headers_json, None, 200, None, "json")
588 engine.test("Get User U1 by new Name", "GET", "/admin/v1/users/U3", headers_json, None, 200, None, "json")
589 engine.test("Delete User U1 by Name", "DELETE", "/admin/v1/users/U3", headers_json, None, 204, None, None)
590 engine.test("Delete User U2 by ID", "DELETE", "/admin/v1/users/"+uid2, headers_json, None, 204, None, None)
591 engine.test("Delete Project P1 by Name", "DELETE", "/admin/v1/projects/P3", headers_json, None, 204, None,
592 None)
593 engine.test("Delete Project P2 by ID", "DELETE", "/admin/v1/projects/"+pid2, headers_json, None, 204, None,
594 None)
595 # END New Tests - Addressing Projects/Users by Name
596 engine.remove_authorization() # To finish
597
tiernocd54a4a2018-09-12 16:40:35 +0200598
tierno65ca36d2019-02-12 19:27:52 +0100599class TestProjectsDescriptors:
600 description = "test descriptors visibility among projects"
601
602 @staticmethod
603 def run(engine, test_osm, manual_check, test_params=None):
604 vnfd_ids = []
605 engine.set_test_name("ProjectDescriptors")
606 engine.get_autorization()
tiernobdebce92019-07-01 15:36:49 +0000607
608 project_admin_id = None
609 res = engine.test("Get my project Padmin", "GET", "/admin/v1/projects/{}".format(engine.project), headers_json,
610 None, 200, r_header_json, "json")
611 if res:
612 response = res.json()
613 project_admin_id = response["_id"]
tierno65ca36d2019-02-12 19:27:52 +0100614 engine.test("Create project Padmin", "POST", "/admin/v1/projects", headers_json,
615 {"name": "Padmin", "admin": True}, (201, 204),
616 {"Location": "/admin/v1/projects/", "Content-Type": "application/json"}, "json")
617 engine.test("Create project P2", "POST", "/admin/v1/projects", headers_json, {"name": "P2"},
618 (201, 204), {"Location": "/admin/v1/projects/", "Content-Type": "application/json"}, "json")
619 engine.test("Create project P3", "POST", "/admin/v1/projects", headers_json, {"name": "P3"},
620 (201, 204), {"Location": "/admin/v1/projects/", "Content-Type": "application/json"}, "json")
621
622 engine.test("Create user U1", "POST", "/admin/v1/users", headers_json,
tierno1546f2a2019-08-20 15:38:11 +0000623 {"username": "U1", "password": "pw1",
624 "project_role_mappings": [{"project": "Padmin", "role": "system_admin"},
625 {"project": "P2", "role": "project_admin"},
626 {"project": "P3", "role": "project_admin"}],
627 }, 201, {"Location": "/admin/v1/users/", "Content-Type": "application/json"}, "json")
tierno65ca36d2019-02-12 19:27:52 +0100628
629 engine.test("Onboard VNFD id1", "POST", "/vnfpkgm/v1/vnf_packages_content?id=id1", headers_yaml,
630 TestDescriptors.vnfd_empty, 201, r_headers_yaml_location_vnfd, "yaml")
631 vnfd_ids.append(engine.last_id)
632 engine.test("Onboard VNFD id2 PUBLIC", "POST", "/vnfpkgm/v1/vnf_packages_content?id=id2&PUBLIC=TRUE",
633 headers_yaml, TestDescriptors.vnfd_empty, 201, r_headers_yaml_location_vnfd, "yaml")
634 vnfd_ids.append(engine.last_id)
635 engine.test("Onboard VNFD id3", "POST", "/vnfpkgm/v1/vnf_packages_content?id=id3&PUBLIC=FALSE", headers_yaml,
636 TestDescriptors.vnfd_empty, 201, r_headers_yaml_location_vnfd, "yaml")
637 vnfd_ids.append(engine.last_id)
638
639 res = engine.test("Get VNFD descriptors", "GET", "/vnfpkgm/v1/vnf_packages?id=id1,id2,id3",
640 headers_json, None, 200, r_header_json, "json")
641 response = res.json()
642 if len(response) != 3:
643 logger.error("Only 3 vnfds should be present for project admin. {} listed".format(len(response)))
644 engine.failed_tests += 1
645
646 # Change to other project Padmin
647 res = engine.test("Change to user U1 project Padmin", "POST", "/admin/v1/tokens", headers_json,
648 {"username": "U1", "password": "pw1", "project_id": "Padmin"}, (200, 201),
649 r_header_json, "json")
650 if res:
651 response = res.json()
652 engine.set_header({"Authorization": "Bearer {}".format(response["id"])})
653
654 # list vnfds
655 res = engine.test("List VNFD descriptors for Padmin", "GET", "/vnfpkgm/v1/vnf_packages",
656 headers_json, None, 200, r_header_json, "json")
657 response = res.json()
658 if len(response) != 0:
659 logger.error("Only 0 vnfds should be present for project Padmin. {} listed".format(len(response)))
660 engine.failed_tests += 1
661
662 # list Public vnfds
663 res = engine.test("List VNFD public descriptors", "GET", "/vnfpkgm/v1/vnf_packages?PUBLIC=True",
664 headers_json, None, 200, r_header_json, "json")
665 response = res.json()
666 if len(response) != 1:
667 logger.error("Only 1 vnfds should be present for project Padmin. {} listed".format(len(response)))
668 engine.failed_tests += 1
669
670 # list vnfds belonging to project "admin"
tiernobdebce92019-07-01 15:36:49 +0000671 res = engine.test("List VNFD of admin project", "GET",
672 "/vnfpkgm/v1/vnf_packages?ADMIN={}".format(project_admin_id),
tierno65ca36d2019-02-12 19:27:52 +0100673 headers_json, None, 200, r_header_json, "json")
674 response = res.json()
675 if len(response) != 3:
676 logger.error("Only 3 vnfds should be present for project Padmin. {} listed".format(len(response)))
677 engine.failed_tests += 1
678
679 # Get Public vnfds
680 engine.test("Get VNFD public descriptors", "GET", "/vnfpkgm/v1/vnf_packages/{}".format(vnfd_ids[1]),
681 headers_json, None, 200, r_header_json, "json")
682 # Edit not owned vnfd
683 engine.test("Edit VNFD ", "PATCH", "/vnfpkgm/v1/vnf_packages/{}".format(vnfd_ids[0]),
684 headers_yaml, '{name: pepe}', 404, r_header_yaml, "yaml")
685
686 # Add to my catalog
687 engine.test("Add VNFD id2 to my catalog", "PATCH", "/vnfpkgm/v1/vnf_packages/{}?SET_PROJECT".
688 format(vnfd_ids[1]), headers_json, None, 204, None, 0)
689
690 # Add a new vnfd
691 engine.test("Onboard VNFD id4", "POST", "/vnfpkgm/v1/vnf_packages_content?id=id4", headers_yaml,
692 TestDescriptors.vnfd_empty, 201, r_headers_yaml_location_vnfd, "yaml")
693 vnfd_ids.append(engine.last_id)
694
695 # list vnfds
696 res = engine.test("List VNFD public descriptors", "GET", "/vnfpkgm/v1/vnf_packages",
697 headers_json, None, 200, r_header_json, "json")
698 response = res.json()
699 if len(response) != 2:
700 logger.error("Only 2 vnfds should be present for project Padmin. {} listed".format(len(response)))
701 engine.failed_tests += 1
702
703 if manual_check:
704 input('VNFDs have been omboarded. Perform manual check and press enter to resume')
705
706 test_rest.test("Delete VNFD id2", "DELETE", "/vnfpkgm/v1/vnf_packages/{}".format(vnfd_ids[1]),
707 headers_yaml, None, 204, None, 0)
708
709 # change to admin project
710 engine.remove_authorization() # To force get authorization
711 engine.get_autorization()
712 test_rest.test("Delete VNFD id1", "DELETE", "/vnfpkgm/v1/vnf_packages/{}".format(vnfd_ids[0]),
713 headers_yaml, None, 204, None, 0)
714 test_rest.test("Delete VNFD id2", "DELETE", "/vnfpkgm/v1/vnf_packages/{}".format(vnfd_ids[1]),
715 headers_yaml, None, 204, None, 0)
716 test_rest.test("Delete VNFD id3", "DELETE", "/vnfpkgm/v1/vnf_packages/{}".format(vnfd_ids[2]),
717 headers_yaml, None, 204, None, 0)
718 test_rest.test("Delete VNFD id4", "DELETE", "/vnfpkgm/v1/vnf_packages/{}".format(vnfd_ids[3]),
719 headers_yaml, None, 404, r_header_yaml, "yaml")
720 test_rest.test("Delete VNFD id4", "DELETE", "/vnfpkgm/v1/vnf_packages/{}?ADMIN".format(vnfd_ids[3]),
721 headers_yaml, None, 204, None, 0)
722 # Get Public vnfds
723 engine.test("Get VNFD deleted id1", "GET", "/vnfpkgm/v1/vnf_packages/{}?ADMIN".format(vnfd_ids[0]),
724 headers_json, None, 404, r_header_json, "json")
725 engine.test("Get VNFD deleted id2", "GET", "/vnfpkgm/v1/vnf_packages/{}?ADMIN".format(vnfd_ids[1]),
726 headers_json, None, 404, r_header_json, "json")
727 engine.test("Get VNFD deleted id3", "GET", "/vnfpkgm/v1/vnf_packages/{}?ADMIN".format(vnfd_ids[2]),
728 headers_json, None, 404, r_header_json, "json")
729 engine.test("Get VNFD deleted id4", "GET", "/vnfpkgm/v1/vnf_packages/{}?ADMIN".format(vnfd_ids[3]),
730 headers_json, None, 404, r_header_json, "json")
731
732 engine.test("Delete user U1", "DELETE", "/admin/v1/users/U1", headers_json, None, 204, None, None)
733 engine.test("Delete project Padmin", "DELETE", "/admin/v1/projects/Padmin", headers_json, None, 204, None, None)
734 engine.test("Delete project P2", "DELETE", "/admin/v1/projects/P2", headers_json, None, 204, None, None)
735 engine.test("Delete project P3", "DELETE", "/admin/v1/projects/P3", headers_json, None, 204, None, None)
736
737
tiernoc32ba4a2018-05-24 18:06:41 +0200738class TestFakeVim:
739 description = "Creates/edit/delete fake VIMs and SDN controllers"
740
741 def __init__(self):
742 self.vim = {
743 "schema_version": "1.0",
744 "schema_type": "No idea",
745 "name": "myVim",
746 "description": "Descriptor name",
747 "vim_type": "openstack",
748 "vim_url": "http://localhost:/vim",
749 "vim_tenant_name": "vimTenant",
750 "vim_user": "user",
751 "vim_password": "password",
752 "config": {"config_param": 1}
753 }
754 self.sdn = {
755 "name": "sdn-name",
756 "description": "sdn-description",
757 "dpid": "50:50:52:54:00:94:21:21",
758 "ip": "192.168.15.17",
759 "port": 8080,
760 "type": "opendaylight",
761 "version": "3.5.6",
762 "user": "user",
763 "password": "passwd"
764 }
765 self.port_mapping = [
766 {"compute_node": "compute node 1",
767 "ports": [{"pci": "0000:81:00.0", "switch_port": "port-2/1", "switch_mac": "52:54:00:94:21:21"},
768 {"pci": "0000:81:00.1", "switch_port": "port-2/2", "switch_mac": "52:54:00:94:21:22"}
769 ]},
770 {"compute_node": "compute node 2",
771 "ports": [{"pci": "0000:81:00.0", "switch_port": "port-2/3", "switch_mac": "52:54:00:94:21:23"},
772 {"pci": "0000:81:00.1", "switch_port": "port-2/4", "switch_mac": "52:54:00:94:21:24"}
773 ]}
774 ]
775
tiernocd54a4a2018-09-12 16:40:35 +0200776 def run(self, engine, test_osm, manual_check, test_params=None):
tiernoc32ba4a2018-05-24 18:06:41 +0200777
778 vim_bad = self.vim.copy()
779 vim_bad.pop("name")
780
tiernoff6485d2018-11-28 17:19:46 +0000781 engine.set_test_name("FakeVim")
tiernoc32ba4a2018-05-24 18:06:41 +0200782 engine.get_autorization()
tiernobdebce92019-07-01 15:36:49 +0000783 engine.test("Create VIM", "POST", "/admin/v1/vim_accounts", headers_json, self.vim, (201, 202),
tiernoc32ba4a2018-05-24 18:06:41 +0200784 {"Location": "/admin/v1/vim_accounts/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000785 vim_id = engine.last_id
786 engine.test("Create VIM without name, bad schema", "POST", "/admin/v1/vim_accounts", headers_json,
tiernoc32ba4a2018-05-24 18:06:41 +0200787 vim_bad, 422, None, headers_json)
tiernoff6485d2018-11-28 17:19:46 +0000788 engine.test("Create VIM name repeated", "POST", "/admin/v1/vim_accounts", headers_json, self.vim,
tiernoc32ba4a2018-05-24 18:06:41 +0200789 409, None, headers_json)
tiernoff6485d2018-11-28 17:19:46 +0000790 engine.test("Show VIMs", "GET", "/admin/v1/vim_accounts", headers_yaml, None, 200, r_header_yaml,
tiernoc32ba4a2018-05-24 18:06:41 +0200791 "yaml")
tiernoff6485d2018-11-28 17:19:46 +0000792 engine.test("Show VIM", "GET", "/admin/v1/vim_accounts/{}".format(vim_id), headers_yaml, None, 200,
tiernoc32ba4a2018-05-24 18:06:41 +0200793 r_header_yaml, "yaml")
794 if not test_osm:
795 # delete with FORCE
tiernoff6485d2018-11-28 17:19:46 +0000796 engine.test("Delete VIM", "DELETE", "/admin/v1/vim_accounts/{}?FORCE=True".format(vim_id), headers_yaml,
tiernoc32ba4a2018-05-24 18:06:41 +0200797 None, 202, None, 0)
tiernoff6485d2018-11-28 17:19:46 +0000798 engine.test("Check VIM is deleted", "GET", "/admin/v1/vim_accounts/{}".format(vim_id), headers_yaml, None,
tiernoc32ba4a2018-05-24 18:06:41 +0200799 404, r_header_yaml, "yaml")
800 else:
801 # delete and wait until is really deleted
tiernoff6485d2018-11-28 17:19:46 +0000802 engine.test("Delete VIM", "DELETE", "/admin/v1/vim_accounts/{}".format(vim_id), headers_yaml, None, 202,
tiernoc32ba4a2018-05-24 18:06:41 +0200803 None, 0)
tiernoff6485d2018-11-28 17:19:46 +0000804 engine.wait_until_delete("/admin/v1/vim_accounts/{}".format(vim_id), timeout)
tiernoc32ba4a2018-05-24 18:06:41 +0200805
806
807class TestVIMSDN(TestFakeVim):
808 description = "Creates VIM with SDN editing SDN controllers and port_mapping"
809
810 def __init__(self):
811 TestFakeVim.__init__(self)
tierno55ba2e62018-12-11 17:22:22 +0000812 self.wim = {
813 "schema_version": "1.0",
814 "schema_type": "No idea",
815 "name": "myWim",
816 "description": "Descriptor name",
817 "wim_type": "odl",
818 "wim_url": "http://localhost:/wim",
819 "user": "user",
820 "password": "password",
821 "config": {"config_param": 1}
822 }
tiernoc32ba4a2018-05-24 18:06:41 +0200823
tiernocd54a4a2018-09-12 16:40:35 +0200824 def run(self, engine, test_osm, manual_check, test_params=None):
tiernoff6485d2018-11-28 17:19:46 +0000825 engine.set_test_name("VimSdn")
tiernoc32ba4a2018-05-24 18:06:41 +0200826 engine.get_autorization()
827 # Added SDN
tiernobdebce92019-07-01 15:36:49 +0000828 engine.test("Create SDN", "POST", "/admin/v1/sdns", headers_json, self.sdn, (201, 202),
tiernoc32ba4a2018-05-24 18:06:41 +0200829 {"Location": "/admin/v1/sdns/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000830 sdnc_id = engine.last_id
tiernocd54a4a2018-09-12 16:40:35 +0200831 # sleep(5)
tiernoc32ba4a2018-05-24 18:06:41 +0200832 # Edit SDN
tiernoff6485d2018-11-28 17:19:46 +0000833 engine.test("Edit SDN", "PATCH", "/admin/v1/sdns/{}".format(sdnc_id), headers_json, {"name": "new_sdn_name"},
tiernobdebce92019-07-01 15:36:49 +0000834 (202, 204), None, None)
tiernocd54a4a2018-09-12 16:40:35 +0200835 # sleep(5)
tiernoc32ba4a2018-05-24 18:06:41 +0200836 # VIM with SDN
tiernoff6485d2018-11-28 17:19:46 +0000837 self.vim["config"]["sdn-controller"] = sdnc_id
tiernoc32ba4a2018-05-24 18:06:41 +0200838 self.vim["config"]["sdn-port-mapping"] = self.port_mapping
tiernobdebce92019-07-01 15:36:49 +0000839 engine.test("Create VIM", "POST", "/admin/v1/vim_accounts", headers_json, self.vim, (200, 202, 201),
tiernoc32ba4a2018-05-24 18:06:41 +0200840 {"Location": "/admin/v1/vim_accounts/", "Content-Type": "application/json"}, "json"),
841
tiernoff6485d2018-11-28 17:19:46 +0000842 vim_id = engine.last_id
tiernoc32ba4a2018-05-24 18:06:41 +0200843 self.port_mapping[0]["compute_node"] = "compute node XX"
tiernoff6485d2018-11-28 17:19:46 +0000844 engine.test("Edit VIM change port-mapping", "PUT", "/admin/v1/vim_accounts/{}".format(vim_id), headers_json,
tiernobdebce92019-07-01 15:36:49 +0000845 {"config": {"sdn-port-mapping": self.port_mapping}}, (202, 204), None, None)
tiernoff6485d2018-11-28 17:19:46 +0000846 engine.test("Edit VIM remove port-mapping", "PUT", "/admin/v1/vim_accounts/{}".format(vim_id), headers_json,
tiernobdebce92019-07-01 15:36:49 +0000847 {"config": {"sdn-port-mapping": None}}, (202, 204), None, None)
tiernocd54a4a2018-09-12 16:40:35 +0200848
tiernobdebce92019-07-01 15:36:49 +0000849 engine.test("Create WIM", "POST", "/admin/v1/wim_accounts", headers_json, self.wim, (200, 202, 201),
tierno55ba2e62018-12-11 17:22:22 +0000850 {"Location": "/admin/v1/wim_accounts/", "Content-Type": "application/json"}, "json"),
851 wim_id = engine.last_id
852
tiernocd54a4a2018-09-12 16:40:35 +0200853 if not test_osm:
854 # delete with FORCE
tiernoff6485d2018-11-28 17:19:46 +0000855 engine.test("Delete VIM remove port-mapping", "DELETE",
856 "/admin/v1/vim_accounts/{}?FORCE=True".format(vim_id), headers_json, None, 202, None, 0)
857 engine.test("Delete SDNC", "DELETE", "/admin/v1/sdns/{}?FORCE=True".format(sdnc_id), headers_json, None,
tiernocd54a4a2018-09-12 16:40:35 +0200858 202, None, 0)
859
tierno55ba2e62018-12-11 17:22:22 +0000860 engine.test("Delete WIM", "DELETE",
861 "/admin/v1/wim_accounts/{}?FORCE=True".format(wim_id), headers_json, None, 202, None, 0)
tiernoff6485d2018-11-28 17:19:46 +0000862 engine.test("Check VIM is deleted", "GET", "/admin/v1/vim_accounts/{}".format(vim_id), headers_yaml,
tiernocd54a4a2018-09-12 16:40:35 +0200863 None, 404, r_header_yaml, "yaml")
tiernoff6485d2018-11-28 17:19:46 +0000864 engine.test("Check SDN is deleted", "GET", "/admin/v1/sdns/{}".format(sdnc_id), headers_yaml, None,
tiernocd54a4a2018-09-12 16:40:35 +0200865 404, r_header_yaml, "yaml")
tierno55ba2e62018-12-11 17:22:22 +0000866 engine.test("Check WIM is deleted", "GET", "/admin/v1/wim_accounts/{}".format(wim_id), headers_yaml,
867 None, 404, r_header_yaml, "yaml")
tiernocd54a4a2018-09-12 16:40:35 +0200868 else:
tierno55ba2e62018-12-11 17:22:22 +0000869 if manual_check:
870 input('VIM, SDN, WIM has been deployed. Perform manual check and press enter to resume')
tiernocd54a4a2018-09-12 16:40:35 +0200871 # delete and wait until is really deleted
tiernoff6485d2018-11-28 17:19:46 +0000872 engine.test("Delete VIM remove port-mapping", "DELETE", "/admin/v1/vim_accounts/{}".format(vim_id),
tiernocd54a4a2018-09-12 16:40:35 +0200873 headers_json, None, (202, 201, 204), None, 0)
tiernoff6485d2018-11-28 17:19:46 +0000874 engine.test("Delete SDN", "DELETE", "/admin/v1/sdns/{}".format(sdnc_id), headers_json, None,
tiernocd54a4a2018-09-12 16:40:35 +0200875 (202, 201, 204), None, 0)
tierno55ba2e62018-12-11 17:22:22 +0000876 engine.test("Delete VIM", "DELETE", "/admin/v1/wim_accounts/{}".format(wim_id),
877 headers_json, None, (202, 201, 204), None, 0)
tiernoff6485d2018-11-28 17:19:46 +0000878 engine.wait_until_delete("/admin/v1/vim_accounts/{}".format(vim_id), timeout)
879 engine.wait_until_delete("/admin/v1/sdns/{}".format(sdnc_id), timeout)
tierno55ba2e62018-12-11 17:22:22 +0000880 engine.wait_until_delete("/admin/v1/wim_accounts/{}".format(wim_id), timeout)
tiernoc32ba4a2018-05-24 18:06:41 +0200881
882
883class TestDeploy:
884 description = "Base class for downloading descriptors from ETSI, onboard and deploy in real VIM"
885
886 def __init__(self):
tiernoff6485d2018-11-28 17:19:46 +0000887 self.test_name = "DEPLOY"
tiernoc32ba4a2018-05-24 18:06:41 +0200888 self.nsd_id = None
889 self.vim_id = None
gcalvino337ec512018-07-30 10:30:13 +0200890 self.ns_id = None
tiernocc103432018-10-19 14:10:35 +0200891 self.vnfds_id = []
tiernoc32ba4a2018-05-24 18:06:41 +0200892 self.descriptor_url = "https://osm-download.etsi.org/ftp/osm-3.0-three/2nd-hackfest/packages/"
893 self.vnfd_filenames = ("cirros_vnf.tar.gz",)
894 self.nsd_filename = "cirros_2vnf_ns.tar.gz"
tierno36ec8602018-11-02 17:27:11 +0100895 self.descriptor_edit = None
tiernoc32ba4a2018-05-24 18:06:41 +0200896 self.uses_configuration = False
tiernobee085c2018-12-12 17:03:04 +0000897 self.users = {}
898 self.passwords = {}
899 self.commands = {}
gcalvino337ec512018-07-30 10:30:13 +0200900 self.keys = {}
901 self.timeout = 120
tierno36ec8602018-11-02 17:27:11 +0100902 self.qforce = ""
tiernobee085c2018-12-12 17:03:04 +0000903 self.ns_params = None
kuuse587aeea2019-04-26 12:33:07 +0200904 self.vnfr_ip_list = {}
tiernoc32ba4a2018-05-24 18:06:41 +0200905
906 def create_descriptors(self, engine):
gcalvino337ec512018-07-30 10:30:13 +0200907 temp_dir = os.path.dirname(os.path.abspath(__file__)) + "/temp/"
tiernoc32ba4a2018-05-24 18:06:41 +0200908 if not os.path.exists(temp_dir):
909 os.makedirs(temp_dir)
tierno36ec8602018-11-02 17:27:11 +0100910 for vnfd_index, vnfd_filename in enumerate(self.vnfd_filenames):
tiernoc32ba4a2018-05-24 18:06:41 +0200911 if "/" in vnfd_filename:
912 vnfd_filename_path = vnfd_filename
913 if not os.path.exists(vnfd_filename_path):
914 raise TestException("File '{}' does not exist".format(vnfd_filename_path))
915 else:
916 vnfd_filename_path = temp_dir + vnfd_filename
917 if not os.path.exists(vnfd_filename_path):
918 with open(vnfd_filename_path, "wb") as file:
919 response = requests.get(self.descriptor_url + vnfd_filename)
920 if response.status_code >= 300:
921 raise TestException("Error downloading descriptor from '{}': {}".format(
922 self.descriptor_url + vnfd_filename, response.status_code))
923 file.write(response.content)
924 if vnfd_filename_path.endswith(".yaml"):
925 headers = headers_yaml
926 else:
927 headers = headers_zip_yaml
tiernoff6485d2018-11-28 17:19:46 +0000928 if randint(0, 1) == 0:
tiernoc32ba4a2018-05-24 18:06:41 +0200929 # vnfd CREATE AND UPLOAD in one step:
tiernoff6485d2018-11-28 17:19:46 +0000930 engine.test("Onboard VNFD in one step", "POST",
tierno36ec8602018-11-02 17:27:11 +0100931 "/vnfpkgm/v1/vnf_packages_content" + self.qforce, headers, "@b" + vnfd_filename_path, 201,
tiernof717cbe2018-12-03 16:35:42 +0000932 r_headers_yaml_location_vnfd,
tierno36ec8602018-11-02 17:27:11 +0100933 "yaml")
tiernoff6485d2018-11-28 17:19:46 +0000934 self.vnfds_id.append(engine.last_id)
tiernoc32ba4a2018-05-24 18:06:41 +0200935 else:
936 # vnfd CREATE AND UPLOAD ZIP
tiernoff6485d2018-11-28 17:19:46 +0000937 engine.test("Onboard VNFD step 1", "POST", "/vnfpkgm/v1/vnf_packages",
tiernoc32ba4a2018-05-24 18:06:41 +0200938 headers_json, None, 201,
939 {"Location": "/vnfpkgm/v1/vnf_packages/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000940 self.vnfds_id.append(engine.last_id)
941 engine.test("Onboard VNFD step 2 as ZIP", "PUT",
tierno36ec8602018-11-02 17:27:11 +0100942 "/vnfpkgm/v1/vnf_packages/<>/package_content" + self.qforce,
tiernoc32ba4a2018-05-24 18:06:41 +0200943 headers, "@b" + vnfd_filename_path, 204, None, 0)
tiernoc32ba4a2018-05-24 18:06:41 +0200944
tierno36ec8602018-11-02 17:27:11 +0100945 if self.descriptor_edit:
946 if "vnfd{}".format(vnfd_index) in self.descriptor_edit:
947 # Modify VNFD
tiernoff6485d2018-11-28 17:19:46 +0000948 engine.test("Edit VNFD ", "PATCH",
tierno36ec8602018-11-02 17:27:11 +0100949 "/vnfpkgm/v1/vnf_packages/{}".format(self.vnfds_id[-1]),
950 headers_yaml, self.descriptor_edit["vnfd{}".format(vnfd_index)], 204, None, None)
tierno36ec8602018-11-02 17:27:11 +0100951
tiernoc32ba4a2018-05-24 18:06:41 +0200952 if "/" in self.nsd_filename:
953 nsd_filename_path = self.nsd_filename
954 if not os.path.exists(nsd_filename_path):
955 raise TestException("File '{}' does not exist".format(nsd_filename_path))
956 else:
957 nsd_filename_path = temp_dir + self.nsd_filename
958 if not os.path.exists(nsd_filename_path):
959 with open(nsd_filename_path, "wb") as file:
960 response = requests.get(self.descriptor_url + self.nsd_filename)
961 if response.status_code >= 300:
962 raise TestException("Error downloading descriptor from '{}': {}".format(
963 self.descriptor_url + self.nsd_filename, response.status_code))
964 file.write(response.content)
965 if nsd_filename_path.endswith(".yaml"):
966 headers = headers_yaml
967 else:
968 headers = headers_zip_yaml
969
tiernoff6485d2018-11-28 17:19:46 +0000970 if randint(0, 1) == 0:
tiernoc32ba4a2018-05-24 18:06:41 +0200971 # nsd CREATE AND UPLOAD in one step:
tiernoff6485d2018-11-28 17:19:46 +0000972 engine.test("Onboard NSD in one step", "POST",
tierno36ec8602018-11-02 17:27:11 +0100973 "/nsd/v1/ns_descriptors_content" + self.qforce, headers, "@b" + nsd_filename_path, 201,
tiernof717cbe2018-12-03 16:35:42 +0000974 r_headers_yaml_location_nsd, yaml)
tiernoff6485d2018-11-28 17:19:46 +0000975 self.nsd_id = engine.last_id
tiernoc32ba4a2018-05-24 18:06:41 +0200976 else:
977 # nsd CREATE AND UPLOAD ZIP
tiernoff6485d2018-11-28 17:19:46 +0000978 engine.test("Onboard NSD step 1", "POST", "/nsd/v1/ns_descriptors",
tiernoc32ba4a2018-05-24 18:06:41 +0200979 headers_json, None, 201,
980 {"Location": "/nsd/v1/ns_descriptors/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000981 self.nsd_id = engine.last_id
982 engine.test("Onboard NSD step 2 as ZIP", "PUT",
tierno36ec8602018-11-02 17:27:11 +0100983 "/nsd/v1/ns_descriptors/<>/nsd_content" + self.qforce,
tiernoc32ba4a2018-05-24 18:06:41 +0200984 headers, "@b" + nsd_filename_path, 204, None, 0)
tierno36ec8602018-11-02 17:27:11 +0100985
986 if self.descriptor_edit and "nsd" in self.descriptor_edit:
987 # Modify NSD
tiernoff6485d2018-11-28 17:19:46 +0000988 engine.test("Edit NSD ", "PATCH",
tierno36ec8602018-11-02 17:27:11 +0100989 "/nsd/v1/ns_descriptors/{}".format(self.nsd_id),
990 headers_yaml, self.descriptor_edit["nsd"], 204, None, None)
tiernoc32ba4a2018-05-24 18:06:41 +0200991
992 def delete_descriptors(self, engine):
993 # delete descriptors
tiernoff6485d2018-11-28 17:19:46 +0000994 engine.test("Delete NSSD SOL005", "DELETE",
tierno36ec8602018-11-02 17:27:11 +0100995 "/nsd/v1/ns_descriptors/{}".format(self.nsd_id),
tiernoc32ba4a2018-05-24 18:06:41 +0200996 headers_yaml, None, 204, None, 0)
tierno36ec8602018-11-02 17:27:11 +0100997 for vnfd_id in self.vnfds_id:
tiernoff6485d2018-11-28 17:19:46 +0000998 engine.test("Delete VNFD SOL005", "DELETE",
tierno36ec8602018-11-02 17:27:11 +0100999 "/vnfpkgm/v1/vnf_packages/{}".format(vnfd_id), headers_yaml, None, 204, None, 0)
tiernoc32ba4a2018-05-24 18:06:41 +02001000
1001 def instantiate(self, engine, ns_data):
1002 ns_data_text = yaml.safe_dump(ns_data, default_flow_style=True, width=256)
1003 # create NS Two steps
tiernoff6485d2018-11-28 17:19:46 +00001004 r = engine.test("Create NS step 1", "POST", "/nslcm/v1/ns_instances",
tiernobdebce92019-07-01 15:36:49 +00001005 headers_yaml, ns_data_text, (201, 202),
tiernoc32ba4a2018-05-24 18:06:41 +02001006 {"Location": "nslcm/v1/ns_instances/", "Content-Type": "application/yaml"}, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001007 if not r:
1008 return
1009 self.ns_id = engine.last_id
1010 engine.test("Instantiate NS step 2", "POST",
1011 "/nslcm/v1/ns_instances/{}/instantiate".format(self.ns_id), headers_yaml, ns_data_text,
tiernobdebce92019-07-01 15:36:49 +00001012 (201, 202), r_headers_yaml_location_nslcmop, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001013 nslcmop_id = engine.last_id
tiernoc32ba4a2018-05-24 18:06:41 +02001014
1015 if test_osm:
1016 # Wait until status is Ok
tiernoff6485d2018-11-28 17:19:46 +00001017 timeout = timeout_configure if self.uses_configuration else timeout_deploy
1018 engine.wait_operation_ready("ns", nslcmop_id, timeout)
tiernoc32ba4a2018-05-24 18:06:41 +02001019
1020 def terminate(self, engine):
1021 # remove deployment
1022 if test_osm:
tiernoff6485d2018-11-28 17:19:46 +00001023 engine.test("Terminate NS", "POST", "/nslcm/v1/ns_instances/{}/terminate".format(self.ns_id), headers_yaml,
tiernobdebce92019-07-01 15:36:49 +00001024 None, (201, 202), r_headers_yaml_location_nslcmop, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001025 nslcmop2_id = engine.last_id
tiernoc32ba4a2018-05-24 18:06:41 +02001026 # Wait until status is Ok
tiernoff6485d2018-11-28 17:19:46 +00001027 engine.wait_operation_ready("ns", nslcmop2_id, timeout_deploy)
tiernoc32ba4a2018-05-24 18:06:41 +02001028
tiernoff6485d2018-11-28 17:19:46 +00001029 engine.test("Delete NS", "DELETE", "/nslcm/v1/ns_instances/{}".format(self.ns_id), headers_yaml, None,
1030 204, None, 0)
tiernoc32ba4a2018-05-24 18:06:41 +02001031 else:
tiernoff6485d2018-11-28 17:19:46 +00001032 engine.test("Delete NS with FORCE", "DELETE", "/nslcm/v1/ns_instances/{}?FORCE=True".format(self.ns_id),
1033 headers_yaml, None, 204, None, 0)
tiernoc32ba4a2018-05-24 18:06:41 +02001034
1035 # check all it is deleted
tiernoff6485d2018-11-28 17:19:46 +00001036 engine.test("Check NS is deleted", "GET", "/nslcm/v1/ns_instances/{}".format(self.ns_id), headers_yaml, None,
1037 404, None, "yaml")
1038 r = engine.test("Check NSLCMOPs are deleted", "GET",
1039 "/nslcm/v1/ns_lcm_op_occs?nsInstanceId={}".format(self.ns_id), headers_json, None,
tiernoc32ba4a2018-05-24 18:06:41 +02001040 200, None, "json")
tiernoff6485d2018-11-28 17:19:46 +00001041 if not r:
1042 return
tiernoc32ba4a2018-05-24 18:06:41 +02001043 nslcmops = r.json()
1044 if not isinstance(nslcmops, list) or nslcmops:
tiernoff6485d2018-11-28 17:19:46 +00001045 raise TestException("NS {} deleted but with ns_lcm_op_occ active: {}".format(self.ns_id, nslcmops))
tiernoc32ba4a2018-05-24 18:06:41 +02001046
gcalvino337ec512018-07-30 10:30:13 +02001047 def test_ns(self, engine, test_osm, commands=None, users=None, passwds=None, keys=None, timeout=0):
1048
tiernoff6485d2018-11-28 17:19:46 +00001049 r = engine.test("GET VNFR IDs", "GET",
gcalvino337ec512018-07-30 10:30:13 +02001050 "/nslcm/v1/ns_instances/{}".format(self.ns_id), headers_json, None,
1051 200, r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +00001052 if not r:
1053 return
gcalvino337ec512018-07-30 10:30:13 +02001054 ns_data = r.json()
1055
1056 vnfr_list = ns_data['constituent-vnfr-ref']
1057 time = 0
tiernobee085c2018-12-12 17:03:04 +00001058 _commands = commands if commands is not None else self.commands
1059 _users = users if users is not None else self.users
1060 _passwds = passwds if passwds is not None else self.passwords
1061 _keys = keys if keys is not None else self.keys
1062 _timeout = timeout if timeout != 0 else self.timeout
gcalvino337ec512018-07-30 10:30:13 +02001063
kuuse587aeea2019-04-26 12:33:07 +02001064 # vnfr_list=[d8272263-6bd3-4680-84ca-6a4be23b3f2d, 88b22e2f-994a-4b61-94fd-4a3c90de3dc4]
gcalvino337ec512018-07-30 10:30:13 +02001065 for vnfr_id in vnfr_list:
tiernoff6485d2018-11-28 17:19:46 +00001066 r = engine.test("Get VNFR to get IP_ADDRESS", "GET",
gcalvino337ec512018-07-30 10:30:13 +02001067 "/nslcm/v1/vnfrs/{}".format(vnfr_id), headers_json, None,
1068 200, r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +00001069 if not r:
1070 continue
gcalvino337ec512018-07-30 10:30:13 +02001071 vnfr_data = r.json()
1072
tiernoff6485d2018-11-28 17:19:46 +00001073 vnf_index = str(vnfr_data["member-vnf-index-ref"])
kuuse587aeea2019-04-26 12:33:07 +02001074
1075 ip_address = self.get_vnfr_ip(engine, vnf_index)
1076 description = "Exec command='{}' at VNFR={} IP={}".format(_commands.get(vnf_index)[0], vnf_index,
1077 ip_address)
1078 engine.step += 1
1079 test_description = "{}{} {}".format(engine.test_name, engine.step, description)
1080 logger.warning(test_description)
1081 while _timeout >= time:
1082 result, message = self.do_checks([ip_address],
1083 vnf_index=vnfr_data["member-vnf-index-ref"],
1084 commands=_commands.get(vnf_index), user=_users.get(vnf_index),
1085 passwd=_passwds.get(vnf_index), key=_keys.get(vnf_index))
1086 if result == 1:
1087 engine.passed_tests += 1
1088 logger.debug(message)
1089 break
1090 elif result == 0:
1091 time += 20
1092 sleep(20)
1093 elif result == -1:
1094 engine.failed_tests += 1
1095 logger.error(message)
1096 break
gcalvino337ec512018-07-30 10:30:13 +02001097 else:
1098 time -= 20
tiernoff6485d2018-11-28 17:19:46 +00001099 engine.failed_tests += 1
1100 logger.error(message)
gcalvino337ec512018-07-30 10:30:13 +02001101 else:
tiernoff6485d2018-11-28 17:19:46 +00001102 engine.failed_tests += 1
kuuse587aeea2019-04-26 12:33:07 +02001103 logger.error("VNFR {} has not mgmt address. Check failed".format(vnf_index))
gcalvino337ec512018-07-30 10:30:13 +02001104
1105 def do_checks(self, ip, vnf_index, commands=[], user=None, passwd=None, key=None):
1106 try:
1107 import urllib3
1108 from pssh.clients import ParallelSSHClient
1109 from pssh.utils import load_private_key
1110 from ssh2 import exceptions as ssh2Exception
1111 except ImportError as e:
tierno36ec8602018-11-02 17:27:11 +01001112 logger.critical("Package <pssh> or/and <urllib3> is not installed. Please add them with 'pip3 install "
1113 "parallel-ssh urllib3': {}".format(e))
tiernoff6485d2018-11-28 17:19:46 +00001114 return -1, "install needed packages 'pip3 install parallel-ssh urllib3'"
gcalvino337ec512018-07-30 10:30:13 +02001115 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
1116 try:
1117 p_host = os.environ.get("PROXY_HOST")
1118 p_user = os.environ.get("PROXY_USER")
1119 p_password = os.environ.get("PROXY_PASSWD")
1120
1121 if key:
1122 pkey = load_private_key(key)
1123 else:
1124 pkey = None
1125
1126 client = ParallelSSHClient(ip, user=user, password=passwd, pkey=pkey, proxy_host=p_host,
1127 proxy_user=p_user, proxy_password=p_password, timeout=10, num_retries=0)
1128 for cmd in commands:
1129 output = client.run_command(cmd)
1130 client.join(output)
1131 if output[ip[0]].exit_code:
tiernobee085c2018-12-12 17:03:04 +00001132 return -1, "VNFR {} command '{}' returns error: '{}'".format(ip[0], cmd,
1133 "\n".join(output[ip[0]].stderr))
gcalvino337ec512018-07-30 10:30:13 +02001134 else:
tiernobee085c2018-12-12 17:03:04 +00001135 return 1, "VNFR {} command '{}' successful".format(ip[0], cmd)
gcalvino337ec512018-07-30 10:30:13 +02001136 except (ssh2Exception.ChannelFailure, ssh2Exception.SocketDisconnectError, ssh2Exception.SocketTimeout,
1137 ssh2Exception.SocketRecvError) as e:
1138 return 0, "Timeout accessing the VNFR {}: {}".format(ip[0], str(e))
1139 except Exception as e:
1140 return -1, "ERROR checking the VNFR {}: {}".format(ip[0], str(e))
tiernoc32ba4a2018-05-24 18:06:41 +02001141
tiernobee085c2018-12-12 17:03:04 +00001142 def additional_operations(self, engine, test_osm, manual_check):
tiernoc32ba4a2018-05-24 18:06:41 +02001143 pass
1144
1145 def run(self, engine, test_osm, manual_check, test_params=None):
tiernoff6485d2018-11-28 17:19:46 +00001146 engine.set_test_name(self.test_name)
tiernoc32ba4a2018-05-24 18:06:41 +02001147 engine.get_autorization()
1148 nsname = os.environ.get("OSMNBITEST_NS_NAME", "OSMNBITEST")
1149 if test_params:
1150 if "vnfd-files" in test_params:
1151 self.vnfd_filenames = test_params["vnfd-files"].split(",")
1152 if "nsd-file" in test_params:
1153 self.nsd_filename = test_params["nsd-file"]
1154 if test_params.get("ns-name"):
1155 nsname = test_params["ns-name"]
1156 self.create_descriptors(engine)
1157
1158 # create real VIM if not exist
1159 self.vim_id = engine.get_create_vim(test_osm)
1160 ns_data = {"nsDescription": "default description", "nsName": nsname, "nsdId": self.nsd_id,
1161 "vimAccountId": self.vim_id}
tiernobee085c2018-12-12 17:03:04 +00001162 if self.ns_params:
1163 ns_data.update(self.ns_params)
tiernoc32ba4a2018-05-24 18:06:41 +02001164 if test_params and test_params.get("ns-config"):
1165 if isinstance(test_params["ns-config"], str):
1166 ns_data.update(yaml.load(test_params["ns-config"]))
1167 else:
1168 ns_data.update(test_params["ns-config"])
1169 self.instantiate(engine, ns_data)
1170
1171 if manual_check:
1172 input('NS has been deployed. Perform manual check and press enter to resume')
tiernobee085c2018-12-12 17:03:04 +00001173 if test_osm and self.commands:
1174 self.test_ns(engine, test_osm)
1175 self.additional_operations(engine, test_osm, manual_check)
tiernoc32ba4a2018-05-24 18:06:41 +02001176 self.terminate(engine)
1177 self.delete_descriptors(engine)
1178
kuuse587aeea2019-04-26 12:33:07 +02001179 def get_first_ip(self, ip_string):
1180 # When using a floating IP, the vnfr_data['ip-address'] contains a semicolon-separated list of IP:s.
1181 first_ip = ip_string.split(";")[0] if ip_string else ""
1182 return first_ip
1183
1184 def get_vnfr_ip(self, engine, vnfr_index_wanted):
1185 # If the IP address list has been obtained before, it has been stored in 'vnfr_ip_list'
1186 ip = self.vnfr_ip_list.get(vnfr_index_wanted, "")
1187 if (ip):
1188 return self.get_first_ip(ip)
1189 r = engine.test("Get VNFR to get IP_ADDRESS", "GET",
1190 "/nslcm/v1/vnfrs?member-vnf-index-ref={}&nsr-id-ref={}".format(
1191 vnfr_index_wanted, self.ns_id), headers_json, None,
1192 200, r_header_json, "json")
1193 if not r:
1194 return ""
1195 vnfr_data = r.json()
1196 if not (vnfr_data and vnfr_data[0]):
1197 return ""
1198 # Store the IP (or list of IPs) in 'vnfr_ip_list'
1199 ip_list = vnfr_data[0].get("ip-address", "")
1200 if ip_list:
1201 self.vnfr_ip_list[vnfr_index_wanted] = ip_list
1202 ip = self.get_first_ip(ip_list)
1203 return ip
1204
tiernoc32ba4a2018-05-24 18:06:41 +02001205
1206class TestDeployHackfestCirros(TestDeploy):
1207 description = "Load and deploy Hackfest cirros_2vnf_ns example"
1208
1209 def __init__(self):
1210 super().__init__()
tiernoff6485d2018-11-28 17:19:46 +00001211 self.test_name = "CIRROS"
tiernoc32ba4a2018-05-24 18:06:41 +02001212 self.vnfd_filenames = ("cirros_vnf.tar.gz",)
1213 self.nsd_filename = "cirros_2vnf_ns.tar.gz"
tiernobee085c2018-12-12 17:03:04 +00001214 self.commands = {'1': ['ls -lrt', ], '2': ['ls -lrt', ]}
1215 self.users = {'1': "cirros", '2': "cirros"}
1216 self.passwords = {'1': "cubswin:)", '2': "cubswin:)"}
tiernoc32ba4a2018-05-24 18:06:41 +02001217
tierno932499c2019-01-28 17:28:10 +00001218 def terminate(self, engine):
1219 # Make a delete in one step, overriding the normal two step of TestDeploy that launched terminate and delete
1220 if test_osm:
1221 engine.test("Terminate and delete NS in one step", "DELETE", "/nslcm/v1/ns_instances_content/{}".
1222 format(self.ns_id), headers_yaml, None, 202, None, "yaml")
1223
1224 engine .wait_until_delete("/nslcm/v1/ns_instances/{}".format(self.ns_id), timeout_deploy)
1225 else:
1226 engine.test("Delete NS with FORCE", "DELETE", "/nslcm/v1/ns_instances/{}?FORCE=True".format(self.ns_id),
1227 headers_yaml, None, 204, None, 0)
1228
1229 # check all it is deleted
1230 engine.test("Check NS is deleted", "GET", "/nslcm/v1/ns_instances/{}".format(self.ns_id), headers_yaml, None,
1231 404, None, "yaml")
1232 r = engine.test("Check NSLCMOPs are deleted", "GET",
1233 "/nslcm/v1/ns_lcm_op_occs?nsInstanceId={}".format(self.ns_id), headers_json, None,
1234 200, None, "json")
1235 if not r:
1236 return
1237 nslcmops = r.json()
1238 if not isinstance(nslcmops, list) or nslcmops:
1239 raise TestException("NS {} deleted but with ns_lcm_op_occ active: {}".format(self.ns_id, nslcmops))
1240
tiernoc32ba4a2018-05-24 18:06:41 +02001241
tiernocc103432018-10-19 14:10:35 +02001242class TestDeployHackfest1(TestDeploy):
1243 description = "Load and deploy Hackfest_1_vnfd example"
1244
1245 def __init__(self):
1246 super().__init__()
tiernoff6485d2018-11-28 17:19:46 +00001247 self.test_name = "HACKFEST1-"
tiernocc103432018-10-19 14:10:35 +02001248 self.vnfd_filenames = ("hackfest_1_vnfd.tar.gz",)
1249 self.nsd_filename = "hackfest_1_nsd.tar.gz"
tiernobee085c2018-12-12 17:03:04 +00001250 # self.commands = {'1': ['ls -lrt', ], '2': ['ls -lrt', ]}
1251 # self.users = {'1': "cirros", '2': "cirros"}
1252 # self.passwords = {'1': "cubswin:)", '2': "cubswin:)"}
tiernocc103432018-10-19 14:10:35 +02001253
1254
1255class TestDeployHackfestCirrosScaling(TestDeploy):
1256 description = "Load and deploy Hackfest cirros_2vnf_ns example with scaling modifications"
1257
1258 def __init__(self):
1259 super().__init__()
tiernoff6485d2018-11-28 17:19:46 +00001260 self.test_name = "CIRROS-SCALE"
tiernocc103432018-10-19 14:10:35 +02001261 self.vnfd_filenames = ("cirros_vnf.tar.gz",)
1262 self.nsd_filename = "cirros_2vnf_ns.tar.gz"
tiernocc103432018-10-19 14:10:35 +02001263 # Modify VNFD to add scaling and count=2
tiernoff6485d2018-11-28 17:19:46 +00001264 self.descriptor_edit = {
1265 "vnfd0": {
1266 "vdu": {
1267 "$id: 'cirros_vnfd-VM'": {"count": 2}
1268 },
1269 "scaling-group-descriptor": [{
1270 "name": "scale_cirros",
1271 "max-instance-count": 2,
1272 "vdu": [{
1273 "vdu-id-ref": "cirros_vnfd-VM",
1274 "count": 2
1275 }]
1276 }]
1277 }
1278 }
tiernocc103432018-10-19 14:10:35 +02001279
tiernobee085c2018-12-12 17:03:04 +00001280 def additional_operations(self, engine, test_osm, manual_check):
tiernocc103432018-10-19 14:10:35 +02001281 if not test_osm:
1282 return
1283 # 2 perform scale out twice
1284 payload = '{scaleType: SCALE_VNF, scaleVnfData: {scaleVnfType: SCALE_OUT, scaleByStepData: ' \
1285 '{scaling-group-descriptor: scale_cirros, member-vnf-index: "1"}}}'
1286 for i in range(0, 2):
tiernoff6485d2018-11-28 17:19:46 +00001287 engine.test("Execute scale action over NS", "POST",
1288 "/nslcm/v1/ns_instances/{}/scale".format(self.ns_id), headers_yaml, payload,
tiernobdebce92019-07-01 15:36:49 +00001289 (201, 202), r_headers_yaml_location_nslcmop, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001290 nslcmop2_scale_out = engine.last_id
1291 engine.wait_operation_ready("ns", nslcmop2_scale_out, timeout_deploy)
tiernocc103432018-10-19 14:10:35 +02001292 if manual_check:
1293 input('NS scale out done. Check that two more vdus are there')
1294 # TODO check automatic
1295
1296 # 2 perform scale in
1297 payload = '{scaleType: SCALE_VNF, scaleVnfData: {scaleVnfType: SCALE_IN, scaleByStepData: ' \
1298 '{scaling-group-descriptor: scale_cirros, member-vnf-index: "1"}}}'
1299 for i in range(0, 2):
tiernoff6485d2018-11-28 17:19:46 +00001300 engine.test("Execute scale IN action over NS", "POST",
1301 "/nslcm/v1/ns_instances/{}/scale".format(self.ns_id), headers_yaml, payload,
tiernobdebce92019-07-01 15:36:49 +00001302 (201, 202), r_headers_yaml_location_nslcmop, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001303 nslcmop2_scale_in = engine.last_id
1304 engine.wait_operation_ready("ns", nslcmop2_scale_in, timeout_deploy)
tiernocc103432018-10-19 14:10:35 +02001305 if manual_check:
1306 input('NS scale in done. Check that two less vdus are there')
1307 # TODO check automatic
1308
1309 # perform scale in that must fail as reached limit
tiernoff6485d2018-11-28 17:19:46 +00001310 engine.test("Execute scale IN out of limit action over NS", "POST",
1311 "/nslcm/v1/ns_instances/{}/scale".format(self.ns_id), headers_yaml, payload,
tiernobdebce92019-07-01 15:36:49 +00001312 (201, 202), r_headers_yaml_location_nslcmop, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001313 nslcmop2_scale_in = engine.last_id
1314 engine.wait_operation_ready("ns", nslcmop2_scale_in, timeout_deploy, expected_fail=True)
tiernocc103432018-10-19 14:10:35 +02001315
1316
tiernoc32ba4a2018-05-24 18:06:41 +02001317class TestDeployIpMac(TestDeploy):
1318 description = "Load and deploy descriptor examples setting mac, ip address at descriptor and instantiate params"
1319
1320 def __init__(self):
1321 super().__init__()
tiernoff6485d2018-11-28 17:19:46 +00001322 self.test_name = "SetIpMac"
tiernoc32ba4a2018-05-24 18:06:41 +02001323 self.vnfd_filenames = ("vnfd_2vdu_set_ip_mac2.yaml", "vnfd_2vdu_set_ip_mac.yaml")
1324 self.nsd_filename = "scenario_2vdu_set_ip_mac.yaml"
1325 self.descriptor_url = \
1326 "https://osm.etsi.org/gitweb/?p=osm/RO.git;a=blob_plain;f=test/RO_tests/v3_2vdu_set_ip_mac/"
tiernobee085c2018-12-12 17:03:04 +00001327 self.commands = {'1': ['ls -lrt', ], '2': ['ls -lrt', ]}
1328 self.users = {'1': "osm", '2': "osm"}
1329 self.passwords = {'1': "osm4u", '2': "osm4u"}
gcalvino337ec512018-07-30 10:30:13 +02001330 self.timeout = 360
tiernoc32ba4a2018-05-24 18:06:41 +02001331
1332 def run(self, engine, test_osm, manual_check, test_params=None):
1333 # super().run(engine, test_osm, manual_check, test_params)
1334 # run again setting IPs with instantiate parameters
1335 instantiation_params = {
1336 "vnf": [
1337 {
1338 "member-vnf-index": "1",
1339 "internal-vld": [
1340 {
1341 "name": "internal_vld1", # net_internal
1342 "ip-profile": {
1343 "ip-version": "ipv4",
1344 "subnet-address": "10.9.8.0/24",
1345 "dhcp-params": {"count": 100, "start-address": "10.9.8.100"}
1346 },
1347 "internal-connection-point": [
1348 {
1349 "id-ref": "eth2",
1350 "ip-address": "10.9.8.2",
1351 },
1352 {
1353 "id-ref": "eth3",
1354 "ip-address": "10.9.8.3",
1355 }
1356 ]
1357 },
1358 ],
1359
1360 "vdu": [
1361 {
1362 "id": "VM1",
1363 "interface": [
tierno7ce1db92018-07-25 12:50:52 +02001364 # {
1365 # "name": "iface11",
1366 # "floating-ip-required": True,
1367 # },
tiernoc32ba4a2018-05-24 18:06:41 +02001368 {
1369 "name": "iface13",
1370 "mac-address": "52:33:44:55:66:13"
1371 },
1372 ],
1373 },
1374 {
1375 "id": "VM2",
1376 "interface": [
1377 {
1378 "name": "iface21",
gcalvino337ec512018-07-30 10:30:13 +02001379 "ip-address": "10.31.31.22",
tiernoc32ba4a2018-05-24 18:06:41 +02001380 "mac-address": "52:33:44:55:66:21"
1381 },
1382 ],
1383 },
1384 ]
1385 },
1386 ]
1387 }
gcalvino337ec512018-07-30 10:30:13 +02001388
tiernoc32ba4a2018-05-24 18:06:41 +02001389 super().run(engine, test_osm, manual_check, test_params={"ns-config": instantiation_params})
1390
1391
1392class TestDeployHackfest4(TestDeploy):
1393 description = "Load and deploy Hackfest 4 example."
1394
1395 def __init__(self):
1396 super().__init__()
tiernoff6485d2018-11-28 17:19:46 +00001397 self.test_name = "HACKFEST4-"
tiernoc32ba4a2018-05-24 18:06:41 +02001398 self.vnfd_filenames = ("hackfest_4_vnfd.tar.gz",)
1399 self.nsd_filename = "hackfest_4_nsd.tar.gz"
1400 self.uses_configuration = True
tiernobee085c2018-12-12 17:03:04 +00001401 self.commands = {'1': ['ls -lrt', ], '2': ['ls -lrt', ]}
1402 self.users = {'1': "ubuntu", '2': "ubuntu"}
1403 self.passwords = {'1': "osm4u", '2': "osm4u"}
tiernoc32ba4a2018-05-24 18:06:41 +02001404 # Modify VNFD to add scaling
tierno932499c2019-01-28 17:28:10 +00001405 # self.descriptor_edit = {
1406 # "vnfd0": {
1407 # 'vnf-configuration': {
1408 # 'config-primitive': [{
1409 # 'name': 'touch',
1410 # 'parameter': [{
1411 # 'name': 'filename',
1412 # 'data-type': 'STRING',
1413 # 'default-value': '/home/ubuntu/touched'
1414 # }]
1415 # }]
1416 # },
1417 # 'scaling-group-descriptor': [{
1418 # 'name': 'scale_dataVM',
1419 # 'scaling-policy': [{
1420 # 'threshold-time': 0,
1421 # 'name': 'auto_cpu_util_above_threshold',
1422 # 'scaling-type': 'automatic',
1423 # 'scaling-criteria': [{
1424 # 'name': 'cpu_util_above_threshold',
1425 # 'vnf-monitoring-param-ref': 'all_aaa_cpu_util',
1426 # 'scale-out-relational-operation': 'GE',
1427 # 'scale-in-threshold': 15,
1428 # 'scale-out-threshold': 60,
1429 # 'scale-in-relational-operation': 'LE'
1430 # }],
1431 # 'cooldown-time': 60
1432 # }],
1433 # 'max-instance-count': 10,
1434 # 'scaling-config-action': [
1435 # {'vnf-config-primitive-name-ref': 'touch',
1436 # 'trigger': 'post-scale-out'},
1437 # {'vnf-config-primitive-name-ref': 'touch',
1438 # 'trigger': 'pre-scale-in'}
1439 # ],
1440 # 'vdu': [{
1441 # 'vdu-id-ref': 'dataVM',
1442 # 'count': 1
1443 # }]
1444 # }]
1445 # }
1446 # }
tiernoc32ba4a2018-05-24 18:06:41 +02001447
tiernoc32ba4a2018-05-24 18:06:41 +02001448
1449class TestDeployHackfest3Charmed(TestDeploy):
tiernobee085c2018-12-12 17:03:04 +00001450 description = "Load and deploy Hackfest 3charmed_ns example"
tiernoc32ba4a2018-05-24 18:06:41 +02001451
1452 def __init__(self):
1453 super().__init__()
tiernoff6485d2018-11-28 17:19:46 +00001454 self.test_name = "HACKFEST3-"
tiernoc32ba4a2018-05-24 18:06:41 +02001455 self.vnfd_filenames = ("hackfest_3charmed_vnfd.tar.gz",)
1456 self.nsd_filename = "hackfest_3charmed_nsd.tar.gz"
1457 self.uses_configuration = True
tiernobee085c2018-12-12 17:03:04 +00001458 self.commands = {'1': ['ls -lrt /home/ubuntu/first-touch'], '2': ['ls -lrt /home/ubuntu/first-touch']}
1459 self.users = {'1': "ubuntu", '2': "ubuntu"}
1460 self.passwords = {'1': "osm4u", '2': "osm4u"}
kuuse587aeea2019-04-26 12:33:07 +02001461 self.descriptor_edit = {
tierno65ca36d2019-02-12 19:27:52 +01001462 "vnfd0": yaml.safe_load(
kuuse587aeea2019-04-26 12:33:07 +02001463 """
1464 vnf-configuration:
1465 terminate-config-primitive:
1466 - seq: '1'
1467 name: touch
1468 parameter:
1469 - name: filename
1470 value: '/home/ubuntu/last-touch1'
1471 - seq: '3'
1472 name: touch
1473 parameter:
1474 - name: filename
1475 value: '/home/ubuntu/last-touch3'
1476 - seq: '2'
1477 name: touch
1478 parameter:
1479 - name: filename
1480 value: '/home/ubuntu/last-touch2'
1481 """)
1482 }
tiernoc32ba4a2018-05-24 18:06:41 +02001483
tiernobee085c2018-12-12 17:03:04 +00001484 def additional_operations(self, engine, test_osm, manual_check):
tiernoc32ba4a2018-05-24 18:06:41 +02001485 if not test_osm:
1486 return
1487 # 1 perform action
kuuse587aeea2019-04-26 12:33:07 +02001488 vnfr_index_selected = "2"
tiernoc32ba4a2018-05-24 18:06:41 +02001489 payload = '{member_vnf_index: "2", primitive: touch, primitive_params: { filename: /home/ubuntu/OSMTESTNBI }}'
tiernoff6485d2018-11-28 17:19:46 +00001490 engine.test("Exec service primitive over NS", "POST",
1491 "/nslcm/v1/ns_instances/{}/action".format(self.ns_id), headers_yaml, payload,
tiernobdebce92019-07-01 15:36:49 +00001492 (201, 202), r_headers_yaml_location_nslcmop, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001493 nslcmop2_action = engine.last_id
tiernoc32ba4a2018-05-24 18:06:41 +02001494 # Wait until status is Ok
tiernoff6485d2018-11-28 17:19:46 +00001495 engine.wait_operation_ready("ns", nslcmop2_action, timeout_deploy)
kuuse587aeea2019-04-26 12:33:07 +02001496 vnfr_ip = self.get_vnfr_ip(engine, vnfr_index_selected)
tiernoc32ba4a2018-05-24 18:06:41 +02001497 if manual_check:
kuuse587aeea2019-04-26 12:33:07 +02001498 input(
1499 "NS service primitive has been executed."
1500 "Check that file /home/ubuntu/OSMTESTNBI is present at {}".
1501 format(vnfr_ip))
tiernoff6485d2018-11-28 17:19:46 +00001502 if test_osm:
tiernobee085c2018-12-12 17:03:04 +00001503 commands = {'1': [''], '2': ['ls -lrt /home/ubuntu/OSMTESTNBI', ]}
1504 self.test_ns(engine, test_osm, commands=commands)
tiernoc32ba4a2018-05-24 18:06:41 +02001505
1506 # # 2 perform scale out
1507 # payload = '{scaleType: SCALE_VNF, scaleVnfData: {scaleVnfType: SCALE_OUT, scaleByStepData: ' \
1508 # '{scaling-group-descriptor: scale_dataVM, member-vnf-index: "1"}}}'
tiernoff6485d2018-11-28 17:19:46 +00001509 # engine.test("Execute scale action over NS", "POST",
1510 # "/nslcm/v1/ns_instances/{}/scale".format(self.ns_id), headers_yaml, payload,
tiernobdebce92019-07-01 15:36:49 +00001511 # (201, 202), r_headers_yaml_location_nslcmop, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001512 # nslcmop2_scale_out = engine.last_id
1513 # engine.wait_operation_ready("ns", nslcmop2_scale_out, timeout_deploy)
tiernoc32ba4a2018-05-24 18:06:41 +02001514 # if manual_check:
1515 # input('NS scale out done. Check that file /home/ubuntu/touched is present and new VM is created')
1516 # # TODO check automatic
1517 #
1518 # # 2 perform scale in
1519 # payload = '{scaleType: SCALE_VNF, scaleVnfData: {scaleVnfType: SCALE_IN, scaleByStepData: ' \
1520 # '{scaling-group-descriptor: scale_dataVM, member-vnf-index: "1"}}}'
tiernoff6485d2018-11-28 17:19:46 +00001521 # engine.test("Execute scale action over NS", "POST",
1522 # "/nslcm/v1/ns_instances/{}/scale".format(self.ns_id), headers_yaml, payload,
tiernobdebce92019-07-01 15:36:49 +00001523 # (201, 202), r_headers_yaml_location_nslcmop, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001524 # nslcmop2_scale_in = engine.last_id
1525 # engine.wait_operation_ready("ns", nslcmop2_scale_in, timeout_deploy)
tiernoc32ba4a2018-05-24 18:06:41 +02001526 # if manual_check:
1527 # input('NS scale in done. Check that file /home/ubuntu/touched is updated and new VM is deleted')
1528 # # TODO check automatic
1529
tiernof27c79b2018-03-12 17:08:42 +01001530
tiernoff6485d2018-11-28 17:19:46 +00001531class TestDeployHackfest3Charmed2(TestDeployHackfest3Charmed):
1532 description = "Load and deploy Hackfest 3charmed_ns example modified version of descriptors to have dots in " \
tiernobee085c2018-12-12 17:03:04 +00001533 "ids and member-vnf-index."
tiernoff6485d2018-11-28 17:19:46 +00001534
1535 def __init__(self):
1536 super().__init__()
tiernobee085c2018-12-12 17:03:04 +00001537 self.test_name = "HACKFEST3v2-"
tiernoff6485d2018-11-28 17:19:46 +00001538 self.qforce = "?FORCE=True"
1539 self.descriptor_edit = {
1540 "vnfd0": {
1541 "vdu": {
1542 "$[0]": {
1543 "interface": {"$[0]": {"external-connection-point-ref": "pdu-mgmt"}}
1544 },
1545 "$[1]": None
1546 },
1547 "vnf-configuration": None,
1548 "connection-point": {
1549 "$[0]": {
1550 "id": "pdu-mgmt",
1551 "name": "pdu-mgmt",
1552 "short-name": "pdu-mgmt"
1553 },
1554 "$[1]": None
1555 },
1556 "mgmt-interface": {"cp": "pdu-mgmt"},
1557 "description": "A vnf single vdu to be used as PDU",
1558 "id": "vdu-as-pdu",
1559 "internal-vld": {
1560 "$[0]": {
1561 "id": "pdu_internal",
1562 "name": "pdu_internal",
1563 "internal-connection-point": {"$[1]": None},
1564 "short-name": "pdu_internal",
1565 "type": "ELAN"
1566 }
1567 }
1568 },
1569
1570 # Modify NSD accordingly
1571 "nsd": {
1572 "constituent-vnfd": {
1573 "$[0]": {"vnfd-id-ref": "vdu-as-pdu"},
1574 "$[1]": None,
1575 },
1576 "description": "A nsd to deploy the vnf to act as as PDU",
1577 "id": "nsd-as-pdu",
1578 "name": "nsd-as-pdu",
1579 "short-name": "nsd-as-pdu",
1580 "vld": {
1581 "$[0]": {
1582 "id": "mgmt_pdu",
1583 "name": "mgmt_pdu",
1584 "short-name": "mgmt_pdu",
1585 "vnfd-connection-point-ref": {
1586 "$[0]": {
1587 "vnfd-connection-point-ref": "pdu-mgmt",
1588 "vnfd-id-ref": "vdu-as-pdu",
1589 },
1590 "$[1]": None
1591 },
1592 "type": "ELAN"
1593 },
1594 "$[1]": None,
1595 }
1596 }
1597 }
1598
1599
tiernobee085c2018-12-12 17:03:04 +00001600class TestDeployHackfest3Charmed3(TestDeployHackfest3Charmed):
1601 description = "Load and deploy Hackfest 3charmed_ns example modified version to test scaling and NS parameters"
1602
1603 def __init__(self):
1604 super().__init__()
1605 self.test_name = "HACKFEST3v3-"
tiernoa1c1b532019-01-16 14:12:22 +00001606 self.commands = {'1': ['ls -lrt /home/ubuntu/first-touch-1'], '2': ['ls -lrt /home/ubuntu/first-touch-2']}
tiernobee085c2018-12-12 17:03:04 +00001607 self.descriptor_edit = {
1608 "vnfd0": yaml.load(
1609 """
1610 scaling-group-descriptor:
1611 - name: "scale_dataVM"
1612 max-instance-count: 10
1613 scaling-policy:
1614 - name: "auto_cpu_util_above_threshold"
1615 scaling-type: "automatic"
1616 threshold-time: 0
1617 cooldown-time: 60
1618 scaling-criteria:
1619 - name: "cpu_util_above_threshold"
1620 scale-in-threshold: 15
1621 scale-in-relational-operation: "LE"
1622 scale-out-threshold: 60
1623 scale-out-relational-operation: "GE"
1624 vnf-monitoring-param-ref: "monitor1"
1625 vdu:
1626 - vdu-id-ref: dataVM
1627 count: 1
1628 scaling-config-action:
1629 - trigger: post-scale-out
1630 vnf-config-primitive-name-ref: touch
1631 - trigger: pre-scale-in
1632 vnf-config-primitive-name-ref: touch
1633 vdu:
1634 "$id: dataVM":
1635 monitoring-param:
1636 - id: "dataVM_cpu_util"
1637 nfvi-metric: "cpu_utilization"
1638
1639 monitoring-param:
1640 - id: "monitor1"
1641 name: "monitor1"
1642 aggregation-type: AVERAGE
1643 vdu-monitoring-param:
1644 vdu-ref: "dataVM"
1645 vdu-monitoring-param-ref: "dataVM_cpu_util"
1646 vnf-configuration:
1647 initial-config-primitive:
1648 "$[1]":
1649 parameter:
1650 "$[0]":
tiernoe4a07d52019-05-16 15:25:37 +00001651 value: "<touch_filename>" # default-value: /home/ubuntu/first-touch
tiernoa1c1b532019-01-16 14:12:22 +00001652 config-primitive:
1653 "$[0]":
1654 parameter:
1655 "$[0]":
tiernoe4a07d52019-05-16 15:25:37 +00001656 default-value: "<touch_filename2>"
tiernobee085c2018-12-12 17:03:04 +00001657 """)
1658 }
1659 self.ns_params = {
1660 "additionalParamsForVnf": [
tiernoe4a07d52019-05-16 15:25:37 +00001661 {"member-vnf-index": "1", "additionalParams": {"touch_filename": "/home/ubuntu/first-touch-1",
1662 "touch_filename2": "/home/ubuntu/second-touch-1"}},
1663 {"member-vnf-index": "2", "additionalParams": {"touch_filename": "/home/ubuntu/first-touch-2",
1664 "touch_filename2": "/home/ubuntu/second-touch-2"}},
tiernobee085c2018-12-12 17:03:04 +00001665 ]
1666 }
1667
1668 def additional_operations(self, engine, test_osm, manual_check):
1669 super().additional_operations(engine, test_osm, manual_check)
1670 if not test_osm:
1671 return
1672
1673 # 2 perform scale out
1674 payload = '{scaleType: SCALE_VNF, scaleVnfData: {scaleVnfType: SCALE_OUT, scaleByStepData: ' \
1675 '{scaling-group-descriptor: scale_dataVM, member-vnf-index: "1"}}}'
1676 engine.test("Execute scale action over NS", "POST",
1677 "/nslcm/v1/ns_instances/{}/scale".format(self.ns_id), headers_yaml, payload,
tiernobdebce92019-07-01 15:36:49 +00001678 (201, 202), r_headers_yaml_location_nslcmop, "yaml")
tiernobee085c2018-12-12 17:03:04 +00001679 nslcmop2_scale_out = engine.last_id
1680 engine.wait_operation_ready("ns", nslcmop2_scale_out, timeout_deploy)
1681 if manual_check:
tiernoa1c1b532019-01-16 14:12:22 +00001682 input('NS scale out done. Check that file /home/ubuntu/second-touch-1 is present and new VM is created')
tiernobee085c2018-12-12 17:03:04 +00001683 if test_osm:
tiernoa1c1b532019-01-16 14:12:22 +00001684 commands = {'1': ['ls -lrt /home/ubuntu/second-touch-1', ]}
tiernobee085c2018-12-12 17:03:04 +00001685 self.test_ns(engine, test_osm, commands=commands)
1686 # TODO check automatic connection to scaled VM
1687
1688 # 2 perform scale in
1689 payload = '{scaleType: SCALE_VNF, scaleVnfData: {scaleVnfType: SCALE_IN, scaleByStepData: ' \
1690 '{scaling-group-descriptor: scale_dataVM, member-vnf-index: "1"}}}'
1691 engine.test("Execute scale action over NS", "POST",
1692 "/nslcm/v1/ns_instances/{}/scale".format(self.ns_id), headers_yaml, payload,
tiernobdebce92019-07-01 15:36:49 +00001693 (201, 202), r_headers_yaml_location_nslcmop, "yaml")
tiernobee085c2018-12-12 17:03:04 +00001694 nslcmop2_scale_in = engine.last_id
1695 engine.wait_operation_ready("ns", nslcmop2_scale_in, timeout_deploy)
1696 if manual_check:
tiernoa1c1b532019-01-16 14:12:22 +00001697 input('NS scale in done. Check that file /home/ubuntu/second-touch-1 is updated and new VM is deleted')
tiernobee085c2018-12-12 17:03:04 +00001698 # TODO check automatic
1699
1700
1701class TestDeploySimpleCharm(TestDeploy):
1702 description = "Deploy hackfest-4 hackfest_simplecharm example"
1703
1704 def __init__(self):
1705 super().__init__()
1706 self.test_name = "HACKFEST-SIMPLE"
1707 self.descriptor_url = "https://osm-download.etsi.org/ftp/osm-4.0-four/4th-hackfest/packages/"
1708 self.vnfd_filenames = ("hackfest_simplecharm_vnf.tar.gz",)
1709 self.nsd_filename = "hackfest_simplecharm_ns.tar.gz"
1710 self.uses_configuration = True
1711 self.commands = {'1': [''], '2': ['ls -lrt /home/ubuntu/first-touch', ]}
1712 self.users = {'1': "ubuntu", '2': "ubuntu"}
1713 self.passwords = {'1': "osm4u", '2': "osm4u"}
1714
1715
1716class TestDeploySimpleCharm2(TestDeploySimpleCharm):
1717 description = "Deploy hackfest-4 hackfest_simplecharm example changing naming to contain dots on ids and " \
1718 "vnf-member-index"
1719
1720 def __init__(self):
1721 super().__init__()
1722 self.test_name = "HACKFEST-SIMPLE2-"
1723 self.qforce = "?FORCE=True"
1724 self.descriptor_edit = {
1725 "vnfd0": {
1726 "id": "hackfest.simplecharm.vnf"
1727 },
1728
1729 "nsd": {
1730 "id": "hackfest.simplecharm.ns",
1731 "constituent-vnfd": {
1732 "$[0]": {"vnfd-id-ref": "hackfest.simplecharm.vnf", "member-vnf-index": "$1"},
1733 "$[1]": {"vnfd-id-ref": "hackfest.simplecharm.vnf", "member-vnf-index": "$2"},
1734 },
1735 "vld": {
1736 "$[0]": {
1737 "vnfd-connection-point-ref": {"$[0]": {"member-vnf-index-ref": "$1",
1738 "vnfd-id-ref": "hackfest.simplecharm.vnf"},
1739 "$[1]": {"member-vnf-index-ref": "$2",
1740 "vnfd-id-ref": "hackfest.simplecharm.vnf"}},
1741 },
1742 "$[1]": {
1743 "vnfd-connection-point-ref": {"$[0]": {"member-vnf-index-ref": "$1",
1744 "vnfd-id-ref": "hackfest.simplecharm.vnf"},
1745 "$[1]": {"member-vnf-index-ref": "$2",
1746 "vnfd-id-ref": "hackfest.simplecharm.vnf"}},
1747 },
1748 }
1749 }
1750 }
1751
1752
tierno36ec8602018-11-02 17:27:11 +01001753class TestDeploySingleVdu(TestDeployHackfest3Charmed):
1754 description = "Generate a single VDU base on editing Hackfest3Charmed descriptors and deploy"
1755
1756 def __init__(self):
1757 super().__init__()
tiernoff6485d2018-11-28 17:19:46 +00001758 self.test_name = "SingleVDU"
tierno36ec8602018-11-02 17:27:11 +01001759 self.qforce = "?FORCE=True"
1760 self.descriptor_edit = {
1761 # Modify VNFD to remove one VDU
1762 "vnfd0": {
1763 "vdu": {
1764 "$[0]": {
1765 "interface": {"$[0]": {"external-connection-point-ref": "pdu-mgmt"}}
1766 },
1767 "$[1]": None
1768 },
1769 "vnf-configuration": None,
1770 "connection-point": {
1771 "$[0]": {
1772 "id": "pdu-mgmt",
1773 "name": "pdu-mgmt",
1774 "short-name": "pdu-mgmt"
1775 },
1776 "$[1]": None
1777 },
1778 "mgmt-interface": {"cp": "pdu-mgmt"},
1779 "description": "A vnf single vdu to be used as PDU",
1780 "id": "vdu-as-pdu",
1781 "internal-vld": {
1782 "$[0]": {
1783 "id": "pdu_internal",
1784 "name": "pdu_internal",
1785 "internal-connection-point": {"$[1]": None},
1786 "short-name": "pdu_internal",
1787 "type": "ELAN"
1788 }
1789 }
1790 },
1791
1792 # Modify NSD accordingly
1793 "nsd": {
1794 "constituent-vnfd": {
1795 "$[0]": {"vnfd-id-ref": "vdu-as-pdu"},
1796 "$[1]": None,
1797 },
1798 "description": "A nsd to deploy the vnf to act as as PDU",
1799 "id": "nsd-as-pdu",
1800 "name": "nsd-as-pdu",
1801 "short-name": "nsd-as-pdu",
1802 "vld": {
1803 "$[0]": {
1804 "id": "mgmt_pdu",
1805 "name": "mgmt_pdu",
1806 "short-name": "mgmt_pdu",
1807 "vnfd-connection-point-ref": {
1808 "$[0]": {
1809 "vnfd-connection-point-ref": "pdu-mgmt",
1810 "vnfd-id-ref": "vdu-as-pdu",
1811 },
1812 "$[1]": None
1813 },
1814 "type": "ELAN"
1815 },
1816 "$[1]": None,
1817 }
1818 }
1819 }
1820
1821
1822class TestDeployHnfd(TestDeployHackfest3Charmed):
1823 description = "Generate a HNFD base on editing Hackfest3Charmed descriptors and deploy"
1824
1825 def __init__(self):
1826 super().__init__()
tiernoff6485d2018-11-28 17:19:46 +00001827 self.test_name = "HNFD"
tierno36ec8602018-11-02 17:27:11 +01001828 self.pduDeploy = TestDeploySingleVdu()
1829 self.pdu_interface_0 = {}
1830 self.pdu_interface_1 = {}
1831
1832 self.pdu_id = None
1833 # self.vnf_to_pdu = """
1834 # vdu:
1835 # "$[0]":
1836 # pdu-type: PDU-TYPE-1
1837 # interface:
1838 # "$[0]":
1839 # name: mgmt-iface
1840 # "$[1]":
1841 # name: pdu-iface-internal
1842 # id: hfn1
1843 # description: HFND, one PDU + One VDU
1844 # name: hfn1
1845 # short-name: hfn1
1846 #
1847 # """
1848
1849 self.pdu_descriptor = {
1850 "name": "my-PDU",
1851 "type": "PDU-TYPE-1",
1852 "vim_accounts": "to-override",
1853 "interfaces": [
1854 {
1855 "name": "mgmt-iface",
1856 "mgmt": True,
1857 "type": "overlay",
1858 "ip-address": "to override",
1859 "mac-address": "mac_address",
1860 "vim-network-name": "mgmt",
1861 },
1862 {
1863 "name": "pdu-iface-internal",
1864 "mgmt": False,
1865 "type": "overlay",
1866 "ip-address": "to override",
1867 "mac-address": "mac_address",
1868 "vim-network-name": "pdu_internal", # OSMNBITEST-PDU-pdu_internal
1869 },
1870 ]
1871 }
1872 self.vnfd_filenames = ("hackfest_3charmed_vnfd.tar.gz", "hackfest_3charmed_vnfd.tar.gz")
1873
1874 self.descriptor_edit = {
1875 "vnfd0": {
1876 "id": "hfnd1",
1877 "name": "hfn1",
1878 "short-name": "hfn1",
1879 "vdu": {
1880 "$[0]": {
1881 "pdu-type": "PDU-TYPE-1",
1882 "interface": {
1883 "$[0]": {"name": "mgmt-iface"},
1884 "$[1]": {"name": "pdu-iface-internal"},
1885 }
1886 }
1887 }
1888 },
1889 "nsd": {
1890 "constituent-vnfd": {
1891 "$[1]": {"vnfd-id-ref": "hfnd1"}
tiernoff6485d2018-11-28 17:19:46 +00001892 },
1893 "vld": {
1894 "$[0]": {"vnfd-connection-point-ref": {"$[1]": {"vnfd-id-ref": "hfnd1"}}},
1895 "$[1]": {"vnfd-connection-point-ref": {"$[1]": {"vnfd-id-ref": "hfnd1"}}}
tierno36ec8602018-11-02 17:27:11 +01001896 }
1897 }
1898 }
1899
1900 def create_descriptors(self, engine):
1901 super().create_descriptors(engine)
1902
1903 # Create PDU
1904 self.pdu_descriptor["interfaces"][0].update(self.pdu_interface_0)
1905 self.pdu_descriptor["interfaces"][1].update(self.pdu_interface_1)
1906 self.pdu_descriptor["vim_accounts"] = [self.vim_id]
1907 # TODO get vim-network-name from vnfr.vld.name
1908 self.pdu_descriptor["interfaces"][1]["vim-network-name"] = "{}-{}-{}".format(
1909 os.environ.get("OSMNBITEST_NS_NAME", "OSMNBITEST"),
1910 "PDU", self.pdu_descriptor["interfaces"][1]["vim-network-name"])
tiernoff6485d2018-11-28 17:19:46 +00001911 engine.test("Onboard PDU descriptor", "POST", "/pdu/v1/pdu_descriptors",
tierno36ec8602018-11-02 17:27:11 +01001912 {"Location": "/pdu/v1/pdu_descriptors/", "Content-Type": "application/yaml"}, self.pdu_descriptor,
1913 201, r_header_yaml, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001914 self.pdu_id = engine.last_id
tierno36ec8602018-11-02 17:27:11 +01001915
1916 def run(self, engine, test_osm, manual_check, test_params=None):
1917 engine.get_autorization()
tiernoff6485d2018-11-28 17:19:46 +00001918 engine.set_test_name(self.test_name)
tierno36ec8602018-11-02 17:27:11 +01001919 nsname = os.environ.get("OSMNBITEST_NS_NAME", "OSMNBITEST")
1920
1921 # create real VIM if not exist
1922 self.vim_id = engine.get_create_vim(test_osm)
tiernoff6485d2018-11-28 17:19:46 +00001923 # instantiate PDU
tierno36ec8602018-11-02 17:27:11 +01001924 self.pduDeploy.create_descriptors(engine)
1925 self.pduDeploy.instantiate(engine, {"nsDescription": "to be used as PDU", "nsName": nsname + "-PDU",
1926 "nsdId": self.pduDeploy.nsd_id, "vimAccountId": self.vim_id})
1927 if manual_check:
1928 input('VNF to be used as PDU has been deployed. Perform manual check and press enter to resume')
tiernoff6485d2018-11-28 17:19:46 +00001929 if test_osm:
tiernobee085c2018-12-12 17:03:04 +00001930 self.pduDeploy.test_ns(engine, test_osm)
tierno36ec8602018-11-02 17:27:11 +01001931
1932 if test_osm:
tiernoff6485d2018-11-28 17:19:46 +00001933 r = engine.test("Get VNFR to obtain IP_ADDRESS", "GET",
tierno36ec8602018-11-02 17:27:11 +01001934 "/nslcm/v1/vnfrs?nsr-id-ref={}".format(self.pduDeploy.ns_id), headers_json, None,
1935 200, r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +00001936 if not r:
1937 return
tierno36ec8602018-11-02 17:27:11 +01001938 vnfr_data = r.json()
1939 # print(vnfr_data)
1940
1941 self.pdu_interface_0["ip-address"] = vnfr_data[0]["vdur"][0]["interfaces"][0].get("ip-address")
1942 self.pdu_interface_1["ip-address"] = vnfr_data[0]["vdur"][0]["interfaces"][1].get("ip-address")
1943 self.pdu_interface_0["mac-address"] = vnfr_data[0]["vdur"][0]["interfaces"][0].get("mac-address")
1944 self.pdu_interface_1["mac-address"] = vnfr_data[0]["vdur"][0]["interfaces"][1].get("mac-address")
1945 if not self.pdu_interface_0["ip-address"]:
1946 raise TestException("Vnfr has not managment ip address")
1947 else:
1948 self.pdu_interface_0["ip-address"] = "192.168.10.10"
1949 self.pdu_interface_1["ip-address"] = "192.168.11.10"
1950 self.pdu_interface_0["mac-address"] = "52:33:44:55:66:13"
1951 self.pdu_interface_1["mac-address"] = "52:33:44:55:66:14"
1952
1953 self.create_descriptors(engine)
1954
1955 ns_data = {"nsDescription": "default description", "nsName": nsname, "nsdId": self.nsd_id,
1956 "vimAccountId": self.vim_id}
1957 if test_params and test_params.get("ns-config"):
1958 if isinstance(test_params["ns-config"], str):
1959 ns_data.update(yaml.load(test_params["ns-config"]))
1960 else:
1961 ns_data.update(test_params["ns-config"])
1962
1963 self.instantiate(engine, ns_data)
1964 if manual_check:
1965 input('NS has been deployed. Perform manual check and press enter to resume')
tiernoff6485d2018-11-28 17:19:46 +00001966 if test_osm:
tiernobee085c2018-12-12 17:03:04 +00001967 self.test_ns(engine, test_osm)
1968 self.additional_operations(engine, test_osm, manual_check)
tierno36ec8602018-11-02 17:27:11 +01001969 self.terminate(engine)
1970 self.pduDeploy.terminate(engine)
1971 self.delete_descriptors(engine)
1972 self.pduDeploy.delete_descriptors(engine)
1973
tierno36ec8602018-11-02 17:27:11 +01001974 def delete_descriptors(self, engine):
1975 super().delete_descriptors(engine)
1976 # delete pdu
tiernoff6485d2018-11-28 17:19:46 +00001977 engine.test("Delete PDU SOL005", "DELETE",
tierno36ec8602018-11-02 17:27:11 +01001978 "/pdu/v1/pdu_descriptors/{}".format(self.pdu_id),
1979 headers_yaml, None, 204, None, 0)
1980
1981
tierno49e42062018-10-24 12:50:53 +02001982class TestDescriptors:
1983 description = "Test VNFD, NSD, PDU descriptors CRUD and dependencies"
tierno65ca36d2019-02-12 19:27:52 +01001984 vnfd_empty = """vnfd:vnfd-catalog:
1985 vnfd:
1986 - name: prova
1987 short-name: prova
1988 id: prova
1989 """
1990 vnfd_prova = """vnfd:vnfd-catalog:
1991 vnfd:
1992 - connection-point:
1993 - name: cp_0h8m
1994 type: VPORT
1995 id: prova
1996 name: prova
1997 short-name: prova
1998 vdu:
1999 - id: vdu_z4bm
2000 image: ubuntu
2001 interface:
2002 - external-connection-point-ref: cp_0h8m
2003 name: eth0
2004 virtual-interface:
2005 type: VIRTIO
2006 name: vdu_z4bm
2007 version: '1.0'
2008 """
tierno49e42062018-10-24 12:50:53 +02002009
2010 def __init__(self):
tierno49e42062018-10-24 12:50:53 +02002011 self.vnfd_filename = "hackfest_3charmed_vnfd.tar.gz"
2012 self.nsd_filename = "hackfest_3charmed_nsd.tar.gz"
2013 self.descriptor_url = "https://osm-download.etsi.org/ftp/osm-3.0-three/2nd-hackfest/packages/"
2014 self.vnfd_id = None
2015 self.nsd_id = None
2016
2017 def run(self, engine, test_osm, manual_check, test_params=None):
tiernoff6485d2018-11-28 17:19:46 +00002018 engine.set_test_name("Descriptors")
tierno49e42062018-10-24 12:50:53 +02002019 engine.get_autorization()
2020 temp_dir = os.path.dirname(os.path.abspath(__file__)) + "/temp/"
2021 if not os.path.exists(temp_dir):
2022 os.makedirs(temp_dir)
2023
2024 # download files
2025 for filename in (self.vnfd_filename, self.nsd_filename):
2026 filename_path = temp_dir + filename
2027 if not os.path.exists(filename_path):
2028 with open(filename_path, "wb") as file:
2029 response = requests.get(self.descriptor_url + filename)
2030 if response.status_code >= 300:
2031 raise TestException("Error downloading descriptor from '{}': {}".format(
2032 self.descriptor_url + filename, response.status_code))
2033 file.write(response.content)
2034
2035 vnfd_filename_path = temp_dir + self.vnfd_filename
2036 nsd_filename_path = temp_dir + self.nsd_filename
2037
tiernof717cbe2018-12-03 16:35:42 +00002038 engine.test("Onboard empty VNFD in one step", "POST", "/vnfpkgm/v1/vnf_packages_content", headers_yaml,
2039 self.vnfd_empty, 201, r_headers_yaml_location_vnfd, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00002040 self.vnfd_id = engine.last_id
tierno49e42062018-10-24 12:50:53 +02002041
tiernof717cbe2018-12-03 16:35:42 +00002042 # test bug 605
2043 engine.test("Upload invalid VNFD ", "PUT", "/vnfpkgm/v1/vnf_packages/{}/package_content".format(self.vnfd_id),
2044 headers_yaml, self.vnfd_prova, 422, r_header_yaml, "yaml")
2045
2046 engine.test("Upload VNFD {}".format(self.vnfd_filename), "PUT",
2047 "/vnfpkgm/v1/vnf_packages/{}/package_content".format(self.vnfd_id), headers_zip_yaml,
2048 "@b" + vnfd_filename_path, 204, None, 0)
2049
gcalvino95f94c22019-01-10 13:03:30 +01002050 queries = ["mgmt-interface.cp=mgmt", "vdu.0.interface.0.external-connection-point-ref=mgmt",
2051 "vdu.0.interface.1.internal-connection-point-ref=internal",
delacruzramo6902c912019-03-29 12:39:35 +01002052 "internal-vld.0.internal-connection-point.0.id-ref=internal",
2053 # Detection of duplicated VLD names in VNF Descriptors
2054 # URL: internal-vld=[
2055 # {id: internal1, name: internal, type:ELAN,
2056 # internal-connection-point: [{id-ref: mgmtVM-internal}, {id-ref: dataVM-internal}]},
2057 # {id: internal2, name: internal, type:ELAN,
2058 # internal-connection-point: [{id-ref: mgmtVM-internal}, {id-ref: dataVM-internal}]}
2059 # ]
2060 "internal-vld=%5B%7Bid%3A%20internal1%2C%20name%3A%20internal%2C%20type%3A%20ELAN%2C%20"
2061 "internal-connection-point%3A%20%5B%7Bid-ref%3A%20mgmtVM-internal%7D%2C%20%7Bid-ref%3A%20"
2062 "dataVM-internal%7D%5D%7D%2C%20%7Bid%3A%20internal2%2C%20name%3A%20internal%2C%20type%3A%20"
2063 "ELAN%2C%20internal-connection-point%3A%20%5B%7Bid-ref%3A%20mgmtVM-internal%7D%2C%20%7B"
2064 "id-ref%3A%20dataVM-internal%7D%5D%7D%5D"
2065 ]
gcalvino95f94c22019-01-10 13:03:30 +01002066 for query in queries:
2067 engine.test("Upload invalid VNFD ", "PUT",
2068 "/vnfpkgm/v1/vnf_packages/{}/package_content?{}".format(self.vnfd_id, query),
2069 headers_zip_yaml, "@b" + vnfd_filename_path, 422, r_header_yaml, "yaml")
2070
tiernof717cbe2018-12-03 16:35:42 +00002071 # test bug 605
2072 engine.test("Upload invalid VNFD ", "PUT", "/vnfpkgm/v1/vnf_packages/{}/package_content".format(self.vnfd_id),
2073 headers_yaml, self.vnfd_prova, 422, r_header_yaml, "yaml")
2074
tierno49e42062018-10-24 12:50:53 +02002075 # get vnfd descriptor
tiernof717cbe2018-12-03 16:35:42 +00002076 engine.test("Get VNFD descriptor", "GET", "/vnfpkgm/v1/vnf_packages/{}".format(self.vnfd_id),
2077 headers_yaml, None, 200, r_header_yaml, "yaml")
tierno49e42062018-10-24 12:50:53 +02002078
2079 # get vnfd file descriptor
tiernof717cbe2018-12-03 16:35:42 +00002080 engine.test("Get VNFD file descriptor", "GET", "/vnfpkgm/v1/vnf_packages/{}/vnfd".format(self.vnfd_id),
2081 headers_text, None, 200, r_header_text, "text", temp_dir+"vnfd-yaml")
tierno49e42062018-10-24 12:50:53 +02002082 # TODO compare files: diff vnfd-yaml hackfest_3charmed_vnfd/hackfest_3charmed_vnfd.yaml
2083
2084 # get vnfd zip file package
tiernoff6485d2018-11-28 17:19:46 +00002085 engine.test("Get VNFD zip package", "GET",
tierno49e42062018-10-24 12:50:53 +02002086 "/vnfpkgm/v1/vnf_packages/{}/package_content".format(self.vnfd_id), headers_zip, None, 200,
2087 r_header_zip, "zip", temp_dir+"vnfd-zip")
tierno49e42062018-10-24 12:50:53 +02002088 # TODO compare files: diff vnfd-zip hackfest_3charmed_vnfd.tar.gz
2089
2090 # get vnfd artifact
tiernoff6485d2018-11-28 17:19:46 +00002091 engine.test("Get VNFD artifact package", "GET",
tierno49e42062018-10-24 12:50:53 +02002092 "/vnfpkgm/v1/vnf_packages/{}/artifacts/icons/osm.png".format(self.vnfd_id), headers_zip, None, 200,
2093 r_header_octect, "octet-string", temp_dir+"vnfd-icon")
tierno49e42062018-10-24 12:50:53 +02002094 # TODO compare files: diff vnfd-icon hackfest_3charmed_vnfd/icons/osm.png
2095
2096 # nsd CREATE AND UPLOAD in one step:
tiernof717cbe2018-12-03 16:35:42 +00002097 engine.test("Onboard NSD in one step", "POST", "/nsd/v1/ns_descriptors_content", headers_zip_yaml,
2098 "@b" + nsd_filename_path, 201, r_headers_yaml_location_nsd, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00002099 self.nsd_id = engine.last_id
tierno49e42062018-10-24 12:50:53 +02002100
gcalvino95f94c22019-01-10 13:03:30 +01002101 queries = ["vld.0.vnfd-connection-point-ref.0.vnfd-id-ref=hf"]
2102 for query in queries:
2103 engine.test("Upload invalid NSD ", "PUT",
2104 "/nsd/v1/ns_descriptors/{}/nsd_content?{}".format(self.nsd_id, query),
2105 headers_zip_yaml, "@b" + nsd_filename_path, 422, r_header_yaml, "yaml")
2106
tierno49e42062018-10-24 12:50:53 +02002107 # get nsd descriptor
tiernof717cbe2018-12-03 16:35:42 +00002108 engine.test("Get NSD descriptor", "GET", "/nsd/v1/ns_descriptors/{}".format(self.nsd_id), headers_yaml,
2109 None, 200, r_header_yaml, "yaml")
tierno49e42062018-10-24 12:50:53 +02002110
2111 # get nsd file descriptor
tiernof717cbe2018-12-03 16:35:42 +00002112 engine.test("Get NSD file descriptor", "GET", "/nsd/v1/ns_descriptors/{}/nsd".format(self.nsd_id), headers_text,
2113 None, 200, r_header_text, "text", temp_dir+"nsd-yaml")
tierno49e42062018-10-24 12:50:53 +02002114 # TODO compare files: diff nsd-yaml hackfest_3charmed_nsd/hackfest_3charmed_nsd.yaml
2115
2116 # get nsd zip file package
tiernof717cbe2018-12-03 16:35:42 +00002117 engine.test("Get NSD zip package", "GET", "/nsd/v1/ns_descriptors/{}/nsd_content".format(self.nsd_id),
2118 headers_zip, None, 200, r_header_zip, "zip", temp_dir+"nsd-zip")
tierno49e42062018-10-24 12:50:53 +02002119 # TODO compare files: diff nsd-zip hackfest_3charmed_nsd.tar.gz
2120
2121 # get nsd artifact
tiernoff6485d2018-11-28 17:19:46 +00002122 engine.test("Get NSD artifact package", "GET",
tierno49e42062018-10-24 12:50:53 +02002123 "/nsd/v1/ns_descriptors/{}/artifacts/icons/osm.png".format(self.nsd_id), headers_zip, None, 200,
2124 r_header_octect, "octet-string", temp_dir+"nsd-icon")
tierno49e42062018-10-24 12:50:53 +02002125 # TODO compare files: diff nsd-icon hackfest_3charmed_nsd/icons/osm.png
2126
2127 # vnfd DELETE
tiernof717cbe2018-12-03 16:35:42 +00002128 test_rest.test("Delete VNFD conflict", "DELETE", "/vnfpkgm/v1/vnf_packages/{}".format(self.vnfd_id),
2129 headers_yaml, None, 409, None, None)
tierno49e42062018-10-24 12:50:53 +02002130
tiernof717cbe2018-12-03 16:35:42 +00002131 test_rest.test("Delete VNFD force", "DELETE", "/vnfpkgm/v1/vnf_packages/{}?FORCE=TRUE".format(self.vnfd_id),
2132 headers_yaml, None, 204, None, 0)
tierno49e42062018-10-24 12:50:53 +02002133
2134 # nsd DELETE
tiernof717cbe2018-12-03 16:35:42 +00002135 test_rest.test("Delete NSD", "DELETE", "/nsd/v1/ns_descriptors/{}".format(self.nsd_id), headers_yaml, None, 204,
2136 None, 0)
tierno49e42062018-10-24 12:50:53 +02002137
2138
Felipe Vicense36ab852018-11-23 14:12:09 +01002139class TestNetSliceTemplates:
Felipe Vicensb57758d2018-10-16 16:00:20 +02002140 description = "Upload a NST to OSM"
2141
2142 def __init__(self):
Felipe Vicens09e65422019-01-22 15:06:46 +01002143 self.vnfd_filename = ("@./slice_shared/vnfd/slice_shared_vnfd.yaml")
2144 self.vnfd_filename_middle = ("@./slice_shared/vnfd/slice_shared_middle_vnfd.yaml")
2145 self.nsd_filename = ("@./slice_shared/nsd/slice_shared_nsd.yaml")
2146 self.nsd_filename_middle = ("@./slice_shared/nsd/slice_shared_middle_nsd.yaml")
2147 self.nst_filenames = ("@./slice_shared/slice_shared_nstd.yaml")
Felipe Vicensb57758d2018-10-16 16:00:20 +02002148
2149 def run(self, engine, test_osm, manual_check, test_params=None):
2150 # nst CREATE
Felipe Vicens09e65422019-01-22 15:06:46 +01002151 engine.set_test_name("NST step ")
Felipe Vicensb57758d2018-10-16 16:00:20 +02002152 engine.get_autorization()
Felipe Vicens09e65422019-01-22 15:06:46 +01002153 temp_dir = os.path.dirname(os.path.abspath(__file__)) + "/temp/"
2154 if not os.path.exists(temp_dir):
2155 os.makedirs(temp_dir)
2156
2157 # Onboard VNFDs
2158 engine.test("Onboard edge VNFD", "POST", "/vnfpkgm/v1/vnf_packages_content", headers_yaml,
2159 self.vnfd_filename, 201, r_headers_yaml_location_vnfd, "yaml")
2160 self.vnfd_edge_id = engine.last_id
2161
2162 engine.test("Onboard middle VNFD", "POST", "/vnfpkgm/v1/vnf_packages_content", headers_yaml,
2163 self.vnfd_filename_middle, 201, r_headers_yaml_location_vnfd, "yaml")
2164 self.vnfd_middle_id = engine.last_id
2165
2166 # Onboard NSDs
2167 engine.test("Onboard NSD edge", "POST", "/nsd/v1/ns_descriptors_content", headers_yaml,
2168 self.nsd_filename, 201, r_headers_yaml_location_nsd, "yaml")
2169 self.nsd_edge_id = engine.last_id
2170
2171 engine.test("Onboard NSD middle", "POST", "/nsd/v1/ns_descriptors_content", headers_yaml,
2172 self.nsd_filename_middle, 201, r_headers_yaml_location_nsd, "yaml")
2173 self.nsd_middle_id = engine.last_id
2174
2175 # Onboard NST
tiernoff6485d2018-11-28 17:19:46 +00002176 engine.test("Onboard NST", "POST", "/nst/v1/netslice_templates_content", headers_yaml, self.nst_filenames,
tiernof717cbe2018-12-03 16:35:42 +00002177 201, r_headers_yaml_location_nst, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00002178 nst_id = engine.last_id
Felipe Vicensb57758d2018-10-16 16:00:20 +02002179
2180 # nstd SHOW OSM format
tiernoff6485d2018-11-28 17:19:46 +00002181 engine.test("Show NSTD OSM format", "GET", "/nst/v1/netslice_templates/{}".format(nst_id), headers_json, None,
2182 200, r_header_json, "json")
Felipe Vicensb57758d2018-10-16 16:00:20 +02002183
2184 # nstd DELETE
tiernoff6485d2018-11-28 17:19:46 +00002185 engine.test("Delete NSTD", "DELETE", "/nst/v1/netslice_templates/{}".format(nst_id), headers_json, None,
2186 204, None, 0)
Felipe Vicensb57758d2018-10-16 16:00:20 +02002187
Felipe Vicens09e65422019-01-22 15:06:46 +01002188 # NSDs DELETE
2189 test_rest.test("Delete NSD middle", "DELETE", "/nsd/v1/ns_descriptors/{}".format(self.nsd_middle_id),
2190 headers_json, None, 204, None, 0)
2191
2192 test_rest.test("Delete NSD edge", "DELETE", "/nsd/v1/ns_descriptors/{}".format(self.nsd_edge_id), headers_json,
2193 None, 204, None, 0)
2194
2195 # VNFDs DELETE
2196 test_rest.test("Delete VNFD edge", "DELETE", "/vnfpkgm/v1/vnf_packages/{}".format(self.vnfd_edge_id),
2197 headers_yaml, None, 204, None, 0)
2198
2199 test_rest.test("Delete VNFD middle", "DELETE", "/vnfpkgm/v1/vnf_packages/{}".format(self.vnfd_middle_id),
2200 headers_yaml, None, 204, None, 0)
2201
Felipe Vicensb57758d2018-10-16 16:00:20 +02002202
Felipe Vicense36ab852018-11-23 14:12:09 +01002203class TestNetSliceInstances:
Felipe Vicens09e65422019-01-22 15:06:46 +01002204 '''
2205 Test procedure:
2206 1. Populate databases with VNFD, NSD, NST with the following scenario
2207 +-----------------management-----------------+
2208 | | |
2209 +--+---+ +----+----+ +---+--+
2210 | | | | | |
2211 | edge +---data1----+ middle +---data2-----+ edge |
2212 | | | | | |
2213 +------+ +---------+ +------+
2214 shared-nss
2215 2. Create NSI-1
2216 3. Instantiate NSI-1
2217 4. Create NSI-2
2218 5. Instantiate NSI-2
2219 Manual check - Are 2 slices instantiated correctly?
2220 NSI-1 3 nss (2 nss-edges + 1 nss-middle)
2221 NSI-2 2 nss (2 nss-edge sharing nss-middle)
2222 6. Terminate NSI-1
2223 7. Delete NSI-1
2224 Manual check - Is slice NSI-1 deleted correctly?
2225 NSI-2 with 2 nss-edge + 1 nss-middle (The one from NSI-1)
2226 8. Create NSI-3
2227 9. Instantiate NSI-3
2228 Manual check - Is slice NSI-3 instantiated correctly?
2229 NSI-3 reuse nss-middle. NSI-3 only create 2 nss-edge
2230 10. Delete NSI-2
2231 11. Terminate NSI-2
2232 12. Delete NSI-3
2233 13. Terminate NSI-3
2234 Manual check - All cleaned correctly?
2235 NSI-2 and NSI-3 were terminated and deleted
2236 14. Cleanup database
2237 '''
2238
Felipe Vicense36ab852018-11-23 14:12:09 +01002239 description = "Upload a NST to OSM"
2240
2241 def __init__(self):
tiernoff6485d2018-11-28 17:19:46 +00002242 self.vim_id = None
Felipe Vicens09e65422019-01-22 15:06:46 +01002243 self.vnfd_filename = ("@./slice_shared/vnfd/slice_shared_vnfd.yaml")
2244 self.vnfd_filename_middle = ("@./slice_shared/vnfd/slice_shared_middle_vnfd.yaml")
2245 self.nsd_filename = ("@./slice_shared/nsd/slice_shared_nsd.yaml")
2246 self.nsd_filename_middle = ("@./slice_shared/nsd/slice_shared_middle_nsd.yaml")
2247 self.nst_filenames = ("@./slice_shared/slice_shared_nstd.yaml")
2248
2249 def create_slice(self, engine, nsi_data, name):
2250 ns_data_text = yaml.safe_dump(nsi_data, default_flow_style=True, width=256)
2251 r = engine.test(name, "POST", "/nsilcm/v1/netslice_instances",
tiernobdebce92019-07-01 15:36:49 +00002252 headers_yaml, ns_data_text, (201, 202),
Felipe Vicens09e65422019-01-22 15:06:46 +01002253 {"Location": "nsilcm/v1/netslice_instances/", "Content-Type": "application/yaml"}, "yaml")
2254 return r
2255
2256 def instantiate_slice(self, engine, nsi_data, nsi_id, name):
2257 ns_data_text = yaml.safe_dump(nsi_data, default_flow_style=True, width=256)
2258 engine.test(name, "POST",
2259 "/nsilcm/v1/netslice_instances/{}/instantiate".format(nsi_id), headers_yaml, ns_data_text,
tiernobdebce92019-07-01 15:36:49 +00002260 (201, 202), r_headers_yaml_location_nsilcmop, "yaml")
Felipe Vicens09e65422019-01-22 15:06:46 +01002261
2262 def terminate_slice(self, engine, nsi_id, name):
2263 engine.test(name, "POST", "/nsilcm/v1/netslice_instances/{}/terminate".format(nsi_id),
tiernobdebce92019-07-01 15:36:49 +00002264 headers_yaml, None, (201, 202), r_headers_yaml_location_nsilcmop, "yaml")
Felipe Vicens09e65422019-01-22 15:06:46 +01002265
2266 def delete_slice(self, engine, nsi_id, name):
2267 engine.test(name, "DELETE", "/nsilcm/v1/netslice_instances/{}".format(nsi_id), headers_yaml, None,
2268 204, None, 0)
Felipe Vicense36ab852018-11-23 14:12:09 +01002269
2270 def run(self, engine, test_osm, manual_check, test_params=None):
2271 # nst CREATE
tiernoff6485d2018-11-28 17:19:46 +00002272 engine.set_test_name("NSI")
Felipe Vicense36ab852018-11-23 14:12:09 +01002273 engine.get_autorization()
Felipe Vicens09e65422019-01-22 15:06:46 +01002274
2275 # Onboard VNFDs
2276 engine.test("Onboard edge VNFD", "POST", "/vnfpkgm/v1/vnf_packages_content", headers_yaml,
2277 self.vnfd_filename, 201, r_headers_yaml_location_vnfd, "yaml")
2278 self.vnfd_edge_id = engine.last_id
2279
2280 engine.test("Onboard middle VNFD", "POST", "/vnfpkgm/v1/vnf_packages_content", headers_yaml,
2281 self.vnfd_filename_middle, 201, r_headers_yaml_location_vnfd, "yaml")
2282 self.vnfd_middle_id = engine.last_id
2283
2284 # Onboard NSDs
2285 engine.test("Onboard NSD edge", "POST", "/nsd/v1/ns_descriptors_content", headers_yaml,
2286 self.nsd_filename, 201, r_headers_yaml_location_nsd, "yaml")
2287 self.nsd_edge_id = engine.last_id
2288
2289 engine.test("Onboard NSD middle", "POST", "/nsd/v1/ns_descriptors_content", headers_yaml,
2290 self.nsd_filename_middle, 201, r_headers_yaml_location_nsd, "yaml")
2291 self.nsd_middle_id = engine.last_id
2292
2293 # Onboard NST
2294 engine.test("Onboard NST", "POST", "/nst/v1/netslice_templates_content", headers_yaml, self.nst_filenames,
2295 201, r_headers_yaml_location_nst, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00002296 nst_id = engine.last_id
Felipe Vicense36ab852018-11-23 14:12:09 +01002297
tiernoff6485d2018-11-28 17:19:46 +00002298 self.vim_id = engine.get_create_vim(test_osm)
2299
Felipe Vicens09e65422019-01-22 15:06:46 +01002300 # CREATE NSI-1
2301 ns_data = {'nsiName': 'Deploy-NSI-1', 'vimAccountId': self.vim_id, 'nstId': nst_id, 'nsiDescription': 'default'}
2302 r = self.create_slice(engine, ns_data, "Create NSI-1 step 1")
2303 if not r:
2304 return
2305 self.nsi_id1 = engine.last_id
Felipe Vicense36ab852018-11-23 14:12:09 +01002306
Felipe Vicens09e65422019-01-22 15:06:46 +01002307 # INSTANTIATE NSI-1
2308 self.instantiate_slice(engine, ns_data, self.nsi_id1, "Instantiate NSI-1 step 2")
2309 nsilcmop_id1 = engine.last_id
Felipe Vicense36ab852018-11-23 14:12:09 +01002310
Felipe Vicens09e65422019-01-22 15:06:46 +01002311 # Waiting for NSI-1
tiernoe4a07d52019-05-16 15:25:37 +00002312 if test_osm:
2313 engine.wait_operation_ready("nsi", nsilcmop_id1, timeout_deploy)
Felipe Vicens09e65422019-01-22 15:06:46 +01002314
2315 # CREATE NSI-2
2316 ns_data = {'nsiName': 'Deploy-NSI-2', 'vimAccountId': self.vim_id, 'nstId': nst_id, 'nsiDescription': 'default'}
2317 r = self.create_slice(engine, ns_data, "Create NSI-2 step 1")
2318 if not r:
2319 return
2320 self.nsi_id2 = engine.last_id
2321
2322 # INSTANTIATE NSI-2
2323 self.instantiate_slice(engine, ns_data, self.nsi_id2, "Instantiate NSI-2 step 2")
2324 nsilcmop_id2 = engine.last_id
2325
2326 # Waiting for NSI-2
tiernoe4a07d52019-05-16 15:25:37 +00002327 if test_osm:
2328 engine.wait_operation_ready("nsi", nsilcmop_id2, timeout_deploy)
Felipe Vicens09e65422019-01-22 15:06:46 +01002329
2330 if manual_check:
2331 input('NSI-1 AND NSI-2 has been deployed. Perform manual check and press enter to resume')
2332
2333 # TERMINATE NSI-1
tiernoe4a07d52019-05-16 15:25:37 +00002334 if test_osm:
2335 self.terminate_slice(engine, self.nsi_id1, "Terminate NSI-1")
2336 nsilcmop1_id = engine.last_id
Felipe Vicens09e65422019-01-22 15:06:46 +01002337
tiernoe4a07d52019-05-16 15:25:37 +00002338 # Wait terminate NSI-1
2339 engine.wait_operation_ready("nsi", nsilcmop1_id, timeout_deploy)
Felipe Vicens09e65422019-01-22 15:06:46 +01002340
2341 # DELETE NSI-1
2342 self.delete_slice(engine, self.nsi_id1, "Delete NS")
2343
2344 if manual_check:
2345 input('NSI-1 has been deleted. Perform manual check and press enter to resume')
2346
2347 # CREATE NSI-3
2348 ns_data = {'nsiName': 'Deploy-NSI-3', 'vimAccountId': self.vim_id, 'nstId': nst_id, 'nsiDescription': 'default'}
2349 r = self.create_slice(engine, ns_data, "Create NSI-3 step 1")
2350
2351 if not r:
2352 return
2353 self.nsi_id3 = engine.last_id
2354
2355 # INSTANTIATE NSI-3
2356 self.instantiate_slice(engine, ns_data, self.nsi_id3, "Instantiate NSI-3 step 2")
2357 nsilcmop_id3 = engine.last_id
2358
2359 # Wait Instantiate NSI-3
tiernoe4a07d52019-05-16 15:25:37 +00002360 if test_osm:
2361 engine.wait_operation_ready("nsi", nsilcmop_id3, timeout_deploy)
Felipe Vicens09e65422019-01-22 15:06:46 +01002362
2363 if manual_check:
2364 input('NSI-3 has been deployed. Perform manual check and press enter to resume')
2365
2366 # TERMINATE NSI-2
tiernoe4a07d52019-05-16 15:25:37 +00002367 if test_osm:
2368 self.terminate_slice(engine, self.nsi_id2, "Terminate NSI-2")
2369 nsilcmop2_id = engine.last_id
Felipe Vicens09e65422019-01-22 15:06:46 +01002370
tiernoe4a07d52019-05-16 15:25:37 +00002371 # Wait terminate NSI-2
2372 engine.wait_operation_ready("nsi", nsilcmop2_id, timeout_deploy)
Felipe Vicense36ab852018-11-23 14:12:09 +01002373
Felipe Vicens09e65422019-01-22 15:06:46 +01002374 # DELETE NSI-2
2375 self.delete_slice(engine, self.nsi_id2, "DELETE NSI-2")
2376
2377 # TERMINATE NSI-3
tiernoe4a07d52019-05-16 15:25:37 +00002378 if test_osm:
2379 self. terminate_slice(engine, self.nsi_id3, "Terminate NSI-3")
2380 nsilcmop3_id = engine.last_id
2381
2382 # Wait terminate NSI-3
2383 engine.wait_operation_ready("nsi", nsilcmop3_id, timeout_deploy)
Felipe Vicens09e65422019-01-22 15:06:46 +01002384
2385 # DELETE NSI-3
2386 self.delete_slice(engine, self.nsi_id3, "DELETE NSI-3")
2387
2388 if manual_check:
2389 input('NSI-2 and NSI-3 has been deleted. Perform manual check and press enter to resume')
Felipe Vicense36ab852018-11-23 14:12:09 +01002390
2391 # nstd DELETE
tiernoff6485d2018-11-28 17:19:46 +00002392 engine.test("Delete NSTD", "DELETE", "/nst/v1/netslice_templates/{}".format(nst_id), headers_json, None,
2393 204, None, 0)
Felipe Vicense36ab852018-11-23 14:12:09 +01002394
Felipe Vicens09e65422019-01-22 15:06:46 +01002395 # NSDs DELETE
2396 test_rest.test("Delete NSD middle", "DELETE", "/nsd/v1/ns_descriptors/{}".format(self.nsd_middle_id),
2397 headers_json, None, 204, None, 0)
2398
2399 test_rest.test("Delete NSD edge", "DELETE", "/nsd/v1/ns_descriptors/{}".format(self.nsd_edge_id), headers_json,
2400 None, 204, None, 0)
2401
2402 # VNFDs DELETE
2403 test_rest.test("Delete VNFD edge", "DELETE", "/vnfpkgm/v1/vnf_packages/{}".format(self.vnfd_edge_id),
2404 headers_yaml, None, 204, None, 0)
2405
2406 test_rest.test("Delete VNFD middle", "DELETE", "/vnfpkgm/v1/vnf_packages/{}".format(self.vnfd_middle_id),
2407 headers_yaml, None, 204, None, 0)
2408
Felipe Vicense36ab852018-11-23 14:12:09 +01002409
tiernof27c79b2018-03-12 17:08:42 +01002410if __name__ == "__main__":
2411 global logger
2412 test = ""
tierno0f98af52018-03-19 10:28:22 +01002413
2414 # Disable warnings from self-signed certificates.
2415 requests.packages.urllib3.disable_warnings()
tiernof27c79b2018-03-12 17:08:42 +01002416 try:
2417 logging.basicConfig(format="%(levelname)s %(message)s", level=logging.ERROR)
2418 logger = logging.getLogger('NBI')
2419 # load parameters and configuration
2420 opts, args = getopt.getopt(sys.argv[1:], "hvu:p:",
tiernoc32ba4a2018-05-24 18:06:41 +02002421 ["url=", "user=", "password=", "help", "version", "verbose", "no-verbose",
2422 "project=", "insecure", "timeout", "timeout-deploy", "timeout-configure",
tiernoff6485d2018-11-28 17:19:46 +00002423 "test=", "list", "test-osm", "manual-check", "params=", 'fail-fast'])
tiernof27c79b2018-03-12 17:08:42 +01002424 url = "https://localhost:9999/osm"
2425 user = password = project = "admin"
tiernoc32ba4a2018-05-24 18:06:41 +02002426 test_osm = False
2427 manual_check = False
tiernof27c79b2018-03-12 17:08:42 +01002428 verbose = 0
2429 verify = True
tiernoff6485d2018-11-28 17:19:46 +00002430 fail_fast = False
tiernoc32ba4a2018-05-24 18:06:41 +02002431 test_classes = {
2432 "NonAuthorized": TestNonAuthorized,
2433 "FakeVIM": TestFakeVim,
tierno65ca36d2019-02-12 19:27:52 +01002434 "Users-Projects": TestUsersProjects,
2435 "Projects-Descriptors": TestProjectsDescriptors,
tiernoc32ba4a2018-05-24 18:06:41 +02002436 "VIM-SDN": TestVIMSDN,
2437 "Deploy-Custom": TestDeploy,
2438 "Deploy-Hackfest-Cirros": TestDeployHackfestCirros,
tiernocc103432018-10-19 14:10:35 +02002439 "Deploy-Hackfest-Cirros-Scaling": TestDeployHackfestCirrosScaling,
tiernoc32ba4a2018-05-24 18:06:41 +02002440 "Deploy-Hackfest-3Charmed": TestDeployHackfest3Charmed,
tiernobee085c2018-12-12 17:03:04 +00002441 "Deploy-Hackfest-3Charmed2": TestDeployHackfest3Charmed2,
2442 "Deploy-Hackfest-3Charmed3": TestDeployHackfest3Charmed3,
tiernoc32ba4a2018-05-24 18:06:41 +02002443 "Deploy-Hackfest-4": TestDeployHackfest4,
2444 "Deploy-CirrosMacIp": TestDeployIpMac,
tierno65ca36d2019-02-12 19:27:52 +01002445 "Descriptors": TestDescriptors,
2446 "Deploy-Hackfest1": TestDeployHackfest1,
gcalvino337ec512018-07-30 10:30:13 +02002447 # "Deploy-MultiVIM": TestDeployMultiVIM,
tierno65ca36d2019-02-12 19:27:52 +01002448 "Deploy-SingleVdu": TestDeploySingleVdu,
2449 "Deploy-Hnfd": TestDeployHnfd,
Felipe Vicens09e65422019-01-22 15:06:46 +01002450 "Upload-Slice-Template": TestNetSliceTemplates,
2451 "Deploy-Slice-Instance": TestNetSliceInstances,
tierno65ca36d2019-02-12 19:27:52 +01002452 "Deploy-SimpleCharm": TestDeploySimpleCharm,
2453 "Deploy-SimpleCharm2": TestDeploySimpleCharm2,
tiernoc32ba4a2018-05-24 18:06:41 +02002454 }
2455 test_to_do = []
2456 test_params = {}
tiernof27c79b2018-03-12 17:08:42 +01002457
2458 for o, a in opts:
tiernoc32ba4a2018-05-24 18:06:41 +02002459 # print("parameter:", o, a)
tiernof27c79b2018-03-12 17:08:42 +01002460 if o == "--version":
tierno2236d202018-05-16 19:05:16 +02002461 print("test version " + __version__ + ' ' + version_date)
tiernoc32ba4a2018-05-24 18:06:41 +02002462 exit()
2463 elif o == "--list":
tiernobee085c2018-12-12 17:03:04 +00002464 for test, test_class in sorted(test_classes.items()):
2465 print("{:32} {}".format(test + ":", test_class.description))
tiernoc32ba4a2018-05-24 18:06:41 +02002466 exit()
tiernof27c79b2018-03-12 17:08:42 +01002467 elif o in ("-v", "--verbose"):
2468 verbose += 1
tierno2236d202018-05-16 19:05:16 +02002469 elif o == "no-verbose":
tiernof27c79b2018-03-12 17:08:42 +01002470 verbose = -1
2471 elif o in ("-h", "--help"):
2472 usage()
2473 sys.exit()
tiernoc32ba4a2018-05-24 18:06:41 +02002474 elif o == "--test-osm":
2475 test_osm = True
2476 elif o == "--manual-check":
2477 manual_check = True
tierno2236d202018-05-16 19:05:16 +02002478 elif o == "--url":
tiernof27c79b2018-03-12 17:08:42 +01002479 url = a
2480 elif o in ("-u", "--user"):
2481 user = a
2482 elif o in ("-p", "--password"):
2483 password = a
tierno2236d202018-05-16 19:05:16 +02002484 elif o == "--project":
tiernof27c79b2018-03-12 17:08:42 +01002485 project = a
tiernoff6485d2018-11-28 17:19:46 +00002486 elif o == "--fail-fast":
2487 fail_fast = True
tiernoc32ba4a2018-05-24 18:06:41 +02002488 elif o == "--test":
2489 # print("asdfadf", o, a, a.split(","))
2490 for _test in a.split(","):
2491 if _test not in test_classes:
2492 print("Invalid test name '{}'. Use option '--list' to show available tests".format(_test),
2493 file=sys.stderr)
2494 exit(1)
2495 test_to_do.append(_test)
2496 elif o == "--params":
2497 param_key, _, param_value = a.partition("=")
2498 text_index = len(test_to_do)
2499 if text_index not in test_params:
2500 test_params[text_index] = {}
2501 test_params[text_index][param_key] = param_value
tierno2236d202018-05-16 19:05:16 +02002502 elif o == "--insecure":
tiernof27c79b2018-03-12 17:08:42 +01002503 verify = False
tiernoc32ba4a2018-05-24 18:06:41 +02002504 elif o == "--timeout":
2505 timeout = int(a)
2506 elif o == "--timeout-deploy":
2507 timeout_deploy = int(a)
2508 elif o == "--timeout-configure":
2509 timeout_configure = int(a)
tiernof27c79b2018-03-12 17:08:42 +01002510 else:
2511 assert False, "Unhandled option"
2512 if verbose == 0:
2513 logger.setLevel(logging.WARNING)
2514 elif verbose > 1:
2515 logger.setLevel(logging.DEBUG)
2516 else:
2517 logger.setLevel(logging.ERROR)
2518
tiernoc32ba4a2018-05-24 18:06:41 +02002519 test_rest = TestRest(url, user=user, password=password, project=project)
2520 # print("tests to do:", test_to_do)
2521 if test_to_do:
2522 text_index = 0
2523 for test in test_to_do:
tiernoff6485d2018-11-28 17:19:46 +00002524 if fail_fast and test_rest.failed_tests:
2525 break
tiernoc32ba4a2018-05-24 18:06:41 +02002526 text_index += 1
2527 test_class = test_classes[test]
2528 test_class().run(test_rest, test_osm, manual_check, test_params.get(text_index))
2529 else:
delacruzramoc061f562019-04-05 11:00:02 +02002530 for test, test_class in sorted(test_classes.items()):
tiernoff6485d2018-11-28 17:19:46 +00002531 if fail_fast and test_rest.failed_tests:
2532 break
tiernoc32ba4a2018-05-24 18:06:41 +02002533 test_class().run(test_rest, test_osm, manual_check, test_params.get(0))
tiernoff6485d2018-11-28 17:19:46 +00002534 test_rest.print_results()
2535 exit(1 if test_rest.failed_tests else 0)
tiernof27c79b2018-03-12 17:08:42 +01002536
tiernoc32ba4a2018-05-24 18:06:41 +02002537 except TestException as e:
2538 logger.error(test + "Test {} Exception: {}".format(test, str(e)))
2539 exit(1)
2540 except getopt.GetoptError as e:
2541 logger.error(e)
2542 print(e, file=sys.stderr)
2543 exit(1)
tiernof27c79b2018-03-12 17:08:42 +01002544 except Exception as e:
tiernoc32ba4a2018-05-24 18:06:41 +02002545 logger.critical(test + " Exception: " + str(e), exc_info=True)