blob: 6bb04d956eb83c35ff0b3d4357cdfdd17a4cab36 [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"}
tiernof27c79b2018-03-12 17:08:42 +010088
89# test ones authorized
90test_authorized_list = (
tierno2236d202018-05-16 19:05:16 +020091 ("AU1", "Invalid vnfd id", "GET", "/vnfpkgm/v1/vnf_packages/non-existing-id",
92 headers_json, None, 404, r_header_json, "json"),
93 ("AU2", "Invalid nsd id", "GET", "/nsd/v1/ns_descriptors/non-existing-id",
94 headers_yaml, None, 404, r_header_yaml, "yaml"),
95 ("AU3", "Invalid nsd id", "DELETE", "/nsd/v1/ns_descriptors_content/non-existing-id",
96 headers_yaml, None, 404, r_header_yaml, "yaml"),
tierno0f98af52018-03-19 10:28:22 +010097)
tiernoc32ba4a2018-05-24 18:06:41 +020098timeout = 120 # general timeout
99timeout_deploy = 60*10 # timeout for NS deploying without charms
100timeout_configure = 60*20 # timeout for NS deploying and configuring
tiernof27c79b2018-03-12 17:08:42 +0100101
tierno2236d202018-05-16 19:05:16 +0200102
tiernof27c79b2018-03-12 17:08:42 +0100103class TestException(Exception):
104 pass
105
106
107class TestRest:
tiernoc32ba4a2018-05-24 18:06:41 +0200108 def __init__(self, url_base, header_base=None, verify=False, user="admin", password="admin", project="admin"):
tiernof27c79b2018-03-12 17:08:42 +0100109 self.url_base = url_base
tiernoc32ba4a2018-05-24 18:06:41 +0200110 if header_base is None:
111 self.header_base = {}
112 else:
113 self.header_base = header_base.copy()
tiernof27c79b2018-03-12 17:08:42 +0100114 self.s = requests.session()
tiernoc32ba4a2018-05-24 18:06:41 +0200115 self.s.headers = self.header_base
tiernof27c79b2018-03-12 17:08:42 +0100116 self.verify = verify
tiernoc32ba4a2018-05-24 18:06:41 +0200117 self.token = False
118 self.user = user
119 self.password = password
120 self.project = project
121 self.vim_id = None
tierno0f98af52018-03-19 10:28:22 +0100122 # contains ID of tests obtained from Location response header. "" key contains last obtained id
tiernoff6485d2018-11-28 17:19:46 +0000123 self.last_id = ""
tierno36ec8602018-11-02 17:27:11 +0100124 self.test_name = None
tiernoff6485d2018-11-28 17:19:46 +0000125 self.step = 0 # number of subtest under test
126 self.passed_tests = 0
127 self.failed_tests = 0
tiernof27c79b2018-03-12 17:08:42 +0100128
tiernoff6485d2018-11-28 17:19:46 +0000129 def set_test_name(self, test_name):
130 self.test_name = test_name
131 self.step = 0
132 self.last_id = ""
133
tiernof27c79b2018-03-12 17:08:42 +0100134 def set_header(self, header):
135 self.s.headers.update(header)
136
tierno36ec8602018-11-02 17:27:11 +0100137 def set_tet_name(self, test_name):
138 self.test_name = test_name
139
tiernocd54a4a2018-09-12 16:40:35 +0200140 def unset_header(self, key):
141 if key in self.s.headers:
142 del self.s.headers[key]
143
tiernoff6485d2018-11-28 17:19:46 +0000144 def test(self, description, method, url, headers, payload, expected_codes, expected_headers,
145 expected_payload, store_file=None, pooling=False):
tiernof27c79b2018-03-12 17:08:42 +0100146 """
tierno0f98af52018-03-19 10:28:22 +0100147 Performs an http request and check http code response. Exit if different than allowed. It get the returned id
148 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 +0100149 :param description: description of the test
tiernof27c79b2018-03-12 17:08:42 +0100150 :param method: HTTP method: GET,PUT,POST,DELETE,...
151 :param url: complete URL or relative URL
152 :param headers: request headers to add to the base headers
153 :param payload: Can be a dict, transformed to json, a text or a file if starts with '@'
154 :param expected_codes: expected response codes, can be int, int tuple or int range
155 :param expected_headers: expected response headers, dict with key values
tierno49e42062018-10-24 12:50:53 +0200156 :param expected_payload: expected payload, 0 if empty, 'yaml', 'json', 'text', 'zip', 'octet-stream'
157 :param store_file: filename to store content
tiernoff6485d2018-11-28 17:19:46 +0000158 :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 +0100159 :return: requests response
tiernof27c79b2018-03-12 17:08:42 +0100160 """
tiernoc32ba4a2018-05-24 18:06:41 +0200161 r = None
tiernof27c79b2018-03-12 17:08:42 +0100162 try:
163 if not self.s:
164 self.s = requests.session()
tierno0f98af52018-03-19 10:28:22 +0100165 # URL
tiernof27c79b2018-03-12 17:08:42 +0100166 if not url:
167 url = self.url_base
168 elif not url.startswith("http"):
169 url = self.url_base + url
tierno0f98af52018-03-19 10:28:22 +0100170
tiernoff6485d2018-11-28 17:19:46 +0000171 # replace url <> with the last ID
172 url = url.replace("<>", self.last_id)
tiernof27c79b2018-03-12 17:08:42 +0100173 if payload:
174 if isinstance(payload, str):
175 if payload.startswith("@"):
176 mode = "r"
177 file_name = payload[1:]
178 if payload.startswith("@b"):
179 mode = "rb"
180 file_name = payload[2:]
181 with open(file_name, mode) as f:
182 payload = f.read()
183 elif isinstance(payload, dict):
184 payload = json.dumps(payload)
tierno2236d202018-05-16 19:05:16 +0200185
tiernoff6485d2018-11-28 17:19:46 +0000186 if not pooling:
187 test_description = "Test {}{} {} {} {}".format(self.test_name, self.step, description, method, url)
tiernoc32ba4a2018-05-24 18:06:41 +0200188 logger.warning(test_description)
tiernoff6485d2018-11-28 17:19:46 +0000189 self.step += 1
tiernof27c79b2018-03-12 17:08:42 +0100190 stream = False
tierno49e42062018-10-24 12:50:53 +0200191 if expected_payload in ("zip", "octet-string") or store_file:
192 stream = True
tiernobee085c2018-12-12 17:03:04 +0000193 __retry = 0
194 while True:
195 try:
196 r = getattr(self.s, method.lower())(url, data=payload, headers=headers, verify=self.verify,
197 stream=stream)
198 break
199 except requests.exceptions.ConnectionError as e:
200 if __retry == 2:
201 raise
202 logger.error("Exception {}. Retrying".format(e))
203 __retry += 1
204
tierno49e42062018-10-24 12:50:53 +0200205 if expected_payload in ("zip", "octet-string") or store_file:
206 logger.debug("RX {}".format(r.status_code))
207 else:
208 logger.debug("RX {}: {}".format(r.status_code, r.text))
tiernof27c79b2018-03-12 17:08:42 +0100209
210 # check response
211 if expected_codes:
212 if isinstance(expected_codes, int):
213 expected_codes = (expected_codes,)
214 if r.status_code not in expected_codes:
215 raise TestException(
216 "Got status {}. Expected {}. {}".format(r.status_code, expected_codes, r.text))
217
218 if expected_headers:
219 for header_key, header_val in expected_headers.items():
220 if header_key.lower() not in r.headers:
221 raise TestException("Header {} not present".format(header_key))
222 if header_val and header_val.lower() not in r.headers[header_key]:
223 raise TestException("Header {} does not contain {} but {}".format(header_key, header_val,
224 r.headers[header_key]))
225
226 if expected_payload is not None:
227 if expected_payload == 0 and len(r.content) > 0:
228 raise TestException("Expected empty payload")
229 elif expected_payload == "json":
230 try:
231 r.json()
232 except Exception as e:
233 raise TestException("Expected json response payload, but got Exception {}".format(e))
234 elif expected_payload == "yaml":
235 try:
236 yaml.safe_load(r.text)
237 except Exception as e:
238 raise TestException("Expected yaml response payload, but got Exception {}".format(e))
tierno49e42062018-10-24 12:50:53 +0200239 elif expected_payload in ("zip", "octet-string"):
tiernof27c79b2018-03-12 17:08:42 +0100240 if len(r.content) == 0:
241 raise TestException("Expected some response payload, but got empty")
242 # try:
243 # tar = tarfile.open(None, 'r:gz', fileobj=r.raw)
244 # for tarinfo in tar:
245 # tarname = tarinfo.name
246 # print(tarname)
247 # except Exception as e:
248 # raise TestException("Expected zip response payload, but got Exception {}".format(e))
249 elif expected_payload == "text":
250 if len(r.content) == 0:
251 raise TestException("Expected some response payload, but got empty")
tierno2236d202018-05-16 19:05:16 +0200252 # r.text
tierno49e42062018-10-24 12:50:53 +0200253 if store_file:
254 with open(store_file, 'wb') as fd:
255 for chunk in r.iter_content(chunk_size=128):
256 fd.write(chunk)
257
tierno0f98af52018-03-19 10:28:22 +0100258 location = r.headers.get("Location")
259 if location:
260 _id = location[location.rfind("/") + 1:]
261 if _id:
tiernoff6485d2018-11-28 17:19:46 +0000262 self.last_id = str(_id)
263 if not pooling:
264 self.passed_tests += 1
tiernof27c79b2018-03-12 17:08:42 +0100265 return r
266 except TestException as e:
tiernoff6485d2018-11-28 17:19:46 +0000267 self.failed_tests += 1
tiernoc32ba4a2018-05-24 18:06:41 +0200268 r_status_code = None
269 r_text = None
270 if r:
271 r_status_code = r.status_code
272 r_text = r.text
273 logger.error("{} \nRX code{}: {}".format(e, r_status_code, r_text))
tiernoff6485d2018-11-28 17:19:46 +0000274 return None
275 # exit(1)
tiernof27c79b2018-03-12 17:08:42 +0100276 except IOError as e:
tiernoff6485d2018-11-28 17:19:46 +0000277 if store_file:
278 logger.error("Cannot open file {}: {}".format(store_file, e))
279 else:
280 logger.error("Exception: {}".format(e), exc_info=True)
281 self.failed_tests += 1
282 return None
283 # exit(1)
tiernobee085c2018-12-12 17:03:04 +0000284 except requests.exceptions.RequestException as e:
285 logger.error("Exception: {}".format(e))
tiernof27c79b2018-03-12 17:08:42 +0100286
tiernoc32ba4a2018-05-24 18:06:41 +0200287 def get_autorization(self): # user=None, password=None, project=None):
288 if self.token: # and self.user == user and self.password == password and self.project == project:
289 return
290 # self.user = user
291 # self.password = password
292 # self.project = project
tiernoff6485d2018-11-28 17:19:46 +0000293 r = self.test("Obtain token", "POST", "/admin/v1/tokens", headers_json,
tiernoc32ba4a2018-05-24 18:06:41 +0200294 {"username": self.user, "password": self.password, "project_id": self.project},
tiernocd54a4a2018-09-12 16:40:35 +0200295 (200, 201), r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000296 if not r:
297 return
tiernoc32ba4a2018-05-24 18:06:41 +0200298 response = r.json()
299 self.token = response["id"]
300 self.set_header({"Authorization": "Bearer {}".format(self.token)})
301
tiernocd54a4a2018-09-12 16:40:35 +0200302 def remove_authorization(self):
303 if self.token:
tiernoff6485d2018-11-28 17:19:46 +0000304 self.test("Delete token", "DELETE", "/admin/v1/tokens/{}".format(self.token), headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200305 None, (200, 201, 204), None, None)
306 self.token = None
307 self.unset_header("Authorization")
308
tiernoc32ba4a2018-05-24 18:06:41 +0200309 def get_create_vim(self, test_osm):
310 if self.vim_id:
311 return self.vim_id
312 self.get_autorization()
313 if test_osm:
314 vim_name = os.environ.get("OSMNBITEST_VIM_NAME")
315 if not vim_name:
316 raise TestException(
317 "Needed to define OSMNBITEST_VIM_XXX variables to create a real VIM for deployment")
318 else:
319 vim_name = "fakeVim"
320 # Get VIM
tiernoff6485d2018-11-28 17:19:46 +0000321 r = self.test("Get VIM ID", "GET", "/admin/v1/vim_accounts?name={}".format(vim_name), headers_json,
tiernoc32ba4a2018-05-24 18:06:41 +0200322 None, 200, r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000323 if not r:
324 return
tiernoc32ba4a2018-05-24 18:06:41 +0200325 vims = r.json()
326 if vims:
327 return vims[0]["_id"]
328 # Add VIM
329 if test_osm:
330 # check needed environ parameters:
331 if not os.environ.get("OSMNBITEST_VIM_URL") or not os.environ.get("OSMNBITEST_VIM_TENANT"):
332 raise TestException("Env OSMNBITEST_VIM_URL and OSMNBITEST_VIM_TENANT are needed for create a real VIM"
333 " to deploy on whit the --test-osm option")
334 vim_data = "{{schema_version: '1.0', name: '{}', vim_type: {}, vim_url: '{}', vim_tenant_name: '{}', "\
335 "vim_user: {}, vim_password: {}".format(vim_name,
336 os.environ.get("OSMNBITEST_VIM_TYPE", "openstack"),
337 os.environ.get("OSMNBITEST_VIM_URL"),
338 os.environ.get("OSMNBITEST_VIM_TENANT"),
339 os.environ.get("OSMNBITEST_VIM_USER"),
340 os.environ.get("OSMNBITEST_VIM_PASSWORD"))
341 if os.environ.get("OSMNBITEST_VIM_CONFIG"):
342 vim_data += " ,config: {}".format(os.environ.get("OSMNBITEST_VIM_CONFIG"))
343 vim_data += "}"
344 else:
345 vim_data = "{schema_version: '1.0', name: fakeVim, vim_type: openstack, vim_url: 'http://10.11.12.13/fake'"\
346 ", vim_tenant_name: 'vimtenant', vim_user: vimuser, vim_password: vimpassword}"
tiernoff6485d2018-11-28 17:19:46 +0000347 self.test("Create VIM", "POST", "/admin/v1/vim_accounts", headers_yaml, vim_data,
348 (201), {"Location": "/admin/v1/vim_accounts/", "Content-Type": "application/yaml"}, "yaml")
349 return self.last_id
350
351 def print_results(self):
352 print("\n\n\n--------------------------------------------")
353 print("TEST RESULTS: Total: {}, Passed: {}, Failed: {}".format(self.passed_tests + self.failed_tests,
354 self.passed_tests, self.failed_tests))
355 print("--------------------------------------------")
356
357 def wait_until_delete(self, url_op, timeout_delete):
358 """
359 Make a pooling until topic is not present, because of deleted
360 :param url_op:
361 :param timeout_delete:
362 :return:
363 """
364 description = "Wait to topic being deleted"
365 test_description = "Test {}{} {} {} {}".format(self.test_name, self.step, description, "GET", url_op)
366 logger.warning(test_description)
367 self.step += 1
368
369 wait = timeout_delete
370 while wait >= 0:
tierno55ba2e62018-12-11 17:22:22 +0000371 r = self.test(description, "GET", url_op, headers_yaml, None, (200, 404), None, r_header_yaml, "yaml",
372 pooling=True)
tiernoff6485d2018-11-28 17:19:46 +0000373 if not r:
374 return
375 if r.status_code == 404:
376 self.passed_tests += 1
377 break
378 elif r.status_code == 200:
379 wait -= 5
380 sleep(5)
381 else:
382 raise TestException("Topic is not deleted after {} seconds".format(timeout_delete))
383 self.failed_tests += 1
384
385 def wait_operation_ready(self, ns_nsi, opp_id, timeout, expected_fail=False):
386 """
387 Wait until nslcmop or nsilcmop finished
388 :param ns_nsi: "ns" o "nsi"
389 :param opp_id: Id o fthe operation
390 :param timeout:
391 :param expected_fail:
392 :return: None. Updates passed/failed_tests
393 """
394 if ns_nsi == "ns":
395 url_op = "/nslcm/v1/ns_lcm_op_occs/{}".format(opp_id)
396 else:
397 url_op = "/nsilcm/v1/nsi_lcm_op_occs/{}".format(opp_id)
398 description = "Wait to {} lcm operation complete".format(ns_nsi)
399 test_description = "Test {}{} {} {} {}".format(self.test_name, self.step, description, "GET", url_op)
400 logger.warning(test_description)
401 self.step += 1
402 wait = timeout
403 while wait >= 0:
404 r = self.test(description, "GET", url_op, headers_json, None,
405 200, r_header_json, "json", pooling=True)
406 if not r:
407 return
408 nslcmop = r.json()
409 if "COMPLETED" in nslcmop["operationState"]:
410 if expected_fail:
tiernobee085c2018-12-12 17:03:04 +0000411 logger.error("NS terminate has success, expecting failing: {}".format(nslcmop["detailed-status"]))
tiernoff6485d2018-11-28 17:19:46 +0000412 self.failed_tests += 1
413 else:
414 self.passed_tests += 1
415 break
416 elif "FAILED" in nslcmop["operationState"]:
417 if not expected_fail:
418 logger.error("NS terminate has failed: {}".format(nslcmop["detailed-status"]))
tiernobee085c2018-12-12 17:03:04 +0000419 self.failed_tests += 1
tiernoff6485d2018-11-28 17:19:46 +0000420 else:
421 self.passed_tests += 1
422 break
423
424 print(".", end="", file=stderr)
425 wait -= 10
426 sleep(10)
427 else:
428 self.failed_tests += 1
429 logger.error("NS instantiate is not terminate after {} seconds".format(timeout))
430 return
431 print("", file=stderr)
tiernoc32ba4a2018-05-24 18:06:41 +0200432
433
434class TestNonAuthorized:
tiernobee085c2018-12-12 17:03:04 +0000435 description = "Test invalid URLs. methods and no authorization"
tiernoc32ba4a2018-05-24 18:06:41 +0200436
437 @staticmethod
tiernocd54a4a2018-09-12 16:40:35 +0200438 def run(engine, test_osm, manual_check, test_params=None):
tiernoff6485d2018-11-28 17:19:46 +0000439 engine.set_test_name("NonAuth")
tiernocd54a4a2018-09-12 16:40:35 +0200440 engine.remove_authorization()
tiernoc32ba4a2018-05-24 18:06:41 +0200441 test_not_authorized_list = (
tiernoff6485d2018-11-28 17:19:46 +0000442 ("Invalid token", "GET", "/admin/v1/users", headers_json, None, 401, r_header_json, "json"),
443 ("Invalid URL", "POST", "/admin/v1/nonexist", headers_yaml, None, 405, r_header_yaml, "yaml"),
444 ("Invalid version", "DELETE", "/admin/v2/users", headers_yaml, None, 405, r_header_yaml, "yaml"),
tiernoc32ba4a2018-05-24 18:06:41 +0200445 )
446 for t in test_not_authorized_list:
447 engine.test(*t)
448
449
tiernocd54a4a2018-09-12 16:40:35 +0200450class TestUsersProjects:
451 description = "test project and user creation"
452
453 @staticmethod
454 def run(engine, test_osm, manual_check, test_params=None):
tiernoff6485d2018-11-28 17:19:46 +0000455 engine.set_test_name("UserProject")
tiernocd54a4a2018-09-12 16:40:35 +0200456 engine.get_autorization()
tiernoff6485d2018-11-28 17:19:46 +0000457 engine.test("Create project non admin", "POST", "/admin/v1/projects", headers_json, {"name": "P1"},
tiernocd54a4a2018-09-12 16:40:35 +0200458 (201, 204), {"Location": "/admin/v1/projects/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000459 engine.test("Create project admin", "POST", "/admin/v1/projects", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200460 {"name": "Padmin", "admin": True}, (201, 204),
461 {"Location": "/admin/v1/projects/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000462 engine.test("Create project bad format", "POST", "/admin/v1/projects", headers_json, {"name": 1}, 422,
tiernocd54a4a2018-09-12 16:40:35 +0200463 r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000464 engine.test("Create user with bad project", "POST", "/admin/v1/users", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200465 {"username": "U1", "projects": ["P1", "P2", "Padmin"], "password": "pw1"}, 409,
466 r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000467 engine.test("Create user with bad project and force", "POST", "/admin/v1/users?FORCE=True", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200468 {"username": "U1", "projects": ["P1", "P2", "Padmin"], "password": "pw1"}, 201,
469 {"Location": "/admin/v1/users/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000470 engine.test("Create user 2", "POST", "/admin/v1/users", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200471 {"username": "U2", "projects": ["P1"], "password": "pw2"}, 201,
472 {"Location": "/admin/v1/users/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000473 engine.test("Edit user U1, delete P2 project", "PATCH", "/admin/v1/users/U1", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200474 {"projects": {"$'P2'": None}}, 204, None, None)
tiernoff6485d2018-11-28 17:19:46 +0000475 res = engine.test("Check user U1, contains the right projects", "GET", "/admin/v1/users/U1",
tiernocd54a4a2018-09-12 16:40:35 +0200476 headers_json, None, 200, None, json)
tiernoff6485d2018-11-28 17:19:46 +0000477 if res:
478 u1 = res.json()
479 # print(u1)
480 expected_projects = ["P1", "Padmin"]
481 if u1["projects"] != expected_projects:
482 logger.error("User content projects '{}' different than expected '{}'. Edition has not done"
483 " properly".format(u1["projects"], expected_projects))
484 engine.failed_tests += 1
tiernocd54a4a2018-09-12 16:40:35 +0200485
tiernoff6485d2018-11-28 17:19:46 +0000486 engine.test("Edit user U1, set Padmin as default project", "PUT", "/admin/v1/users/U1", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200487 {"projects": {"$'Padmin'": None, "$+[0]": "Padmin"}}, 204, None, None)
tiernoff6485d2018-11-28 17:19:46 +0000488 res = engine.test("Check user U1, contains the right projects", "GET", "/admin/v1/users/U1",
tiernocd54a4a2018-09-12 16:40:35 +0200489 headers_json, None, 200, None, json)
tiernoff6485d2018-11-28 17:19:46 +0000490 if res:
491 u1 = res.json()
492 # print(u1)
493 expected_projects = ["Padmin", "P1"]
494 if u1["projects"] != expected_projects:
495 logger.error("User content projects '{}' different than expected '{}'. Edition has not done"
496 " properly".format(u1["projects"], expected_projects))
497 engine.failed_tests += 1
tiernocd54a4a2018-09-12 16:40:35 +0200498
tiernoff6485d2018-11-28 17:19:46 +0000499 engine.test("Edit user U1, change password", "PATCH", "/admin/v1/users/U1", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200500 {"password": "pw1_new"}, 204, None, None)
501
tiernoff6485d2018-11-28 17:19:46 +0000502 engine.test("Change to project P1 non existing", "POST", "/admin/v1/tokens/", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200503 {"project_id": "P1"}, 401, r_header_json, "json")
504
tiernoff6485d2018-11-28 17:19:46 +0000505 res = engine.test("Change to user U1 project P1", "POST", "/admin/v1/tokens", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200506 {"username": "U1", "password": "pw1_new", "project_id": "P1"}, (200, 201),
507 r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000508 if res:
509 response = res.json()
510 engine.set_header({"Authorization": "Bearer {}".format(response["id"])})
tiernocd54a4a2018-09-12 16:40:35 +0200511
tiernoff6485d2018-11-28 17:19:46 +0000512 engine.test("Edit user projects non admin", "PUT", "/admin/v1/users/U1", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200513 {"projects": {"$'P1'": None}}, 401, r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000514 engine.test("Add new project non admin", "POST", "/admin/v1/projects", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200515 {"name": "P2"}, 401, r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000516 engine.test("Add new user non admin", "POST", "/admin/v1/users", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200517 {"username": "U3", "projects": ["P1"], "password": "pw3"}, 401,
518 r_header_json, "json")
519
tiernoff6485d2018-11-28 17:19:46 +0000520 res = engine.test("Change to user U1 project Padmin", "POST", "/admin/v1/tokens", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200521 {"project_id": "Padmin"}, (200, 201), r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000522 if res:
523 response = res.json()
524 engine.set_header({"Authorization": "Bearer {}".format(response["id"])})
tiernocd54a4a2018-09-12 16:40:35 +0200525
tiernoff6485d2018-11-28 17:19:46 +0000526 engine.test("Add new project admin", "POST", "/admin/v1/projects", headers_json, {"name": "P2"},
tiernocd54a4a2018-09-12 16:40:35 +0200527 (201, 204), {"Location": "/admin/v1/projects/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000528 engine.test("Add new user U3 admin", "POST", "/admin/v1/users",
tiernocd54a4a2018-09-12 16:40:35 +0200529 headers_json, {"username": "U3", "projects": ["P2"], "password": "pw3"}, (201, 204),
530 {"Location": "/admin/v1/users/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000531 engine.test("Edit user projects admin", "PUT", "/admin/v1/users/U3", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200532 {"projects": ["P2"]}, 204, None, None)
533
tiernoff6485d2018-11-28 17:19:46 +0000534 engine.test("Delete project P2 conflict", "DELETE", "/admin/v1/projects/P2", headers_json, None, 409,
tiernocd54a4a2018-09-12 16:40:35 +0200535 r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000536 engine.test("Delete project P2 forcing", "DELETE", "/admin/v1/projects/P2?FORCE=True", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200537 None, 204, None, None)
538
tiernoff6485d2018-11-28 17:19:46 +0000539 engine.test("Delete user U1. Conflict deleting own user", "DELETE", "/admin/v1/users/U1", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200540 None, 409, r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000541 engine.test("Delete user U2", "DELETE", "/admin/v1/users/U2", headers_json, None, 204, None, None)
542 engine.test("Delete user U3", "DELETE", "/admin/v1/users/U3", headers_json, None, 204, None, None)
tiernocd54a4a2018-09-12 16:40:35 +0200543 # change to admin
544 engine.remove_authorization() # To force get authorization
545 engine.get_autorization()
tiernoff6485d2018-11-28 17:19:46 +0000546 engine.test("Delete user U1", "DELETE", "/admin/v1/users/U1", headers_json, None, 204, None, None)
547 engine.test("Delete project P1", "DELETE", "/admin/v1/projects/P1", headers_json, None, 204, None, None)
548 engine.test("Delete project Padmin", "DELETE", "/admin/v1/projects/Padmin", headers_json, None, 204,
tiernocd54a4a2018-09-12 16:40:35 +0200549 None, None)
550
551
tiernoc32ba4a2018-05-24 18:06:41 +0200552class TestFakeVim:
553 description = "Creates/edit/delete fake VIMs and SDN controllers"
554
555 def __init__(self):
556 self.vim = {
557 "schema_version": "1.0",
558 "schema_type": "No idea",
559 "name": "myVim",
560 "description": "Descriptor name",
561 "vim_type": "openstack",
562 "vim_url": "http://localhost:/vim",
563 "vim_tenant_name": "vimTenant",
564 "vim_user": "user",
565 "vim_password": "password",
566 "config": {"config_param": 1}
567 }
568 self.sdn = {
569 "name": "sdn-name",
570 "description": "sdn-description",
571 "dpid": "50:50:52:54:00:94:21:21",
572 "ip": "192.168.15.17",
573 "port": 8080,
574 "type": "opendaylight",
575 "version": "3.5.6",
576 "user": "user",
577 "password": "passwd"
578 }
579 self.port_mapping = [
580 {"compute_node": "compute node 1",
581 "ports": [{"pci": "0000:81:00.0", "switch_port": "port-2/1", "switch_mac": "52:54:00:94:21:21"},
582 {"pci": "0000:81:00.1", "switch_port": "port-2/2", "switch_mac": "52:54:00:94:21:22"}
583 ]},
584 {"compute_node": "compute node 2",
585 "ports": [{"pci": "0000:81:00.0", "switch_port": "port-2/3", "switch_mac": "52:54:00:94:21:23"},
586 {"pci": "0000:81:00.1", "switch_port": "port-2/4", "switch_mac": "52:54:00:94:21:24"}
587 ]}
588 ]
589
tiernocd54a4a2018-09-12 16:40:35 +0200590 def run(self, engine, test_osm, manual_check, test_params=None):
tiernoc32ba4a2018-05-24 18:06:41 +0200591
592 vim_bad = self.vim.copy()
593 vim_bad.pop("name")
594
tiernoff6485d2018-11-28 17:19:46 +0000595 engine.set_test_name("FakeVim")
tiernoc32ba4a2018-05-24 18:06:41 +0200596 engine.get_autorization()
tiernoff6485d2018-11-28 17:19:46 +0000597 engine.test("Create VIM", "POST", "/admin/v1/vim_accounts", headers_json, self.vim, (201, 204),
tiernoc32ba4a2018-05-24 18:06:41 +0200598 {"Location": "/admin/v1/vim_accounts/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000599 vim_id = engine.last_id
600 engine.test("Create VIM without name, bad schema", "POST", "/admin/v1/vim_accounts", headers_json,
tiernoc32ba4a2018-05-24 18:06:41 +0200601 vim_bad, 422, None, headers_json)
tiernoff6485d2018-11-28 17:19:46 +0000602 engine.test("Create VIM name repeated", "POST", "/admin/v1/vim_accounts", headers_json, self.vim,
tiernoc32ba4a2018-05-24 18:06:41 +0200603 409, None, headers_json)
tiernoff6485d2018-11-28 17:19:46 +0000604 engine.test("Show VIMs", "GET", "/admin/v1/vim_accounts", headers_yaml, None, 200, r_header_yaml,
tiernoc32ba4a2018-05-24 18:06:41 +0200605 "yaml")
tiernoff6485d2018-11-28 17:19:46 +0000606 engine.test("Show VIM", "GET", "/admin/v1/vim_accounts/{}".format(vim_id), headers_yaml, None, 200,
tiernoc32ba4a2018-05-24 18:06:41 +0200607 r_header_yaml, "yaml")
608 if not test_osm:
609 # delete with FORCE
tiernoff6485d2018-11-28 17:19:46 +0000610 engine.test("Delete VIM", "DELETE", "/admin/v1/vim_accounts/{}?FORCE=True".format(vim_id), headers_yaml,
tiernoc32ba4a2018-05-24 18:06:41 +0200611 None, 202, None, 0)
tiernoff6485d2018-11-28 17:19:46 +0000612 engine.test("Check VIM is deleted", "GET", "/admin/v1/vim_accounts/{}".format(vim_id), headers_yaml, None,
tiernoc32ba4a2018-05-24 18:06:41 +0200613 404, r_header_yaml, "yaml")
614 else:
615 # delete and wait until is really deleted
tiernoff6485d2018-11-28 17:19:46 +0000616 engine.test("Delete VIM", "DELETE", "/admin/v1/vim_accounts/{}".format(vim_id), headers_yaml, None, 202,
tiernoc32ba4a2018-05-24 18:06:41 +0200617 None, 0)
tiernoff6485d2018-11-28 17:19:46 +0000618 engine.wait_until_delete("/admin/v1/vim_accounts/{}".format(vim_id), timeout)
tiernoc32ba4a2018-05-24 18:06:41 +0200619
620
621class TestVIMSDN(TestFakeVim):
622 description = "Creates VIM with SDN editing SDN controllers and port_mapping"
623
624 def __init__(self):
625 TestFakeVim.__init__(self)
tierno55ba2e62018-12-11 17:22:22 +0000626 self.wim = {
627 "schema_version": "1.0",
628 "schema_type": "No idea",
629 "name": "myWim",
630 "description": "Descriptor name",
631 "wim_type": "odl",
632 "wim_url": "http://localhost:/wim",
633 "user": "user",
634 "password": "password",
635 "config": {"config_param": 1}
636 }
tiernoc32ba4a2018-05-24 18:06:41 +0200637
tiernocd54a4a2018-09-12 16:40:35 +0200638 def run(self, engine, test_osm, manual_check, test_params=None):
tiernoff6485d2018-11-28 17:19:46 +0000639 engine.set_test_name("VimSdn")
tiernoc32ba4a2018-05-24 18:06:41 +0200640 engine.get_autorization()
641 # Added SDN
tiernoff6485d2018-11-28 17:19:46 +0000642 engine.test("Create SDN", "POST", "/admin/v1/sdns", headers_json, self.sdn, (201, 204),
tiernoc32ba4a2018-05-24 18:06:41 +0200643 {"Location": "/admin/v1/sdns/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000644 sdnc_id = engine.last_id
tiernocd54a4a2018-09-12 16:40:35 +0200645 # sleep(5)
tiernoc32ba4a2018-05-24 18:06:41 +0200646 # Edit SDN
tiernoff6485d2018-11-28 17:19:46 +0000647 engine.test("Edit SDN", "PATCH", "/admin/v1/sdns/{}".format(sdnc_id), headers_json, {"name": "new_sdn_name"},
tiernocd54a4a2018-09-12 16:40:35 +0200648 204, None, None)
649 # sleep(5)
tiernoc32ba4a2018-05-24 18:06:41 +0200650 # VIM with SDN
tiernoff6485d2018-11-28 17:19:46 +0000651 self.vim["config"]["sdn-controller"] = sdnc_id
tiernoc32ba4a2018-05-24 18:06:41 +0200652 self.vim["config"]["sdn-port-mapping"] = self.port_mapping
tiernoff6485d2018-11-28 17:19:46 +0000653 engine.test("Create VIM", "POST", "/admin/v1/vim_accounts", headers_json, self.vim, (200, 204, 201),
tiernoc32ba4a2018-05-24 18:06:41 +0200654 {"Location": "/admin/v1/vim_accounts/", "Content-Type": "application/json"}, "json"),
655
tiernoff6485d2018-11-28 17:19:46 +0000656 vim_id = engine.last_id
tiernoc32ba4a2018-05-24 18:06:41 +0200657 self.port_mapping[0]["compute_node"] = "compute node XX"
tiernoff6485d2018-11-28 17:19:46 +0000658 engine.test("Edit VIM change port-mapping", "PUT", "/admin/v1/vim_accounts/{}".format(vim_id), headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200659 {"config": {"sdn-port-mapping": self.port_mapping}}, 204, None, None)
tiernoff6485d2018-11-28 17:19:46 +0000660 engine.test("Edit VIM remove port-mapping", "PUT", "/admin/v1/vim_accounts/{}".format(vim_id), headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200661 {"config": {"sdn-port-mapping": None}}, 204, None, None)
662
tierno55ba2e62018-12-11 17:22:22 +0000663 engine.test("Create WIM", "POST", "/admin/v1/wim_accounts", headers_json, self.wim, (200, 204, 201),
664 {"Location": "/admin/v1/wim_accounts/", "Content-Type": "application/json"}, "json"),
665 wim_id = engine.last_id
666
tiernocd54a4a2018-09-12 16:40:35 +0200667 if not test_osm:
668 # delete with FORCE
tiernoff6485d2018-11-28 17:19:46 +0000669 engine.test("Delete VIM remove port-mapping", "DELETE",
670 "/admin/v1/vim_accounts/{}?FORCE=True".format(vim_id), headers_json, None, 202, None, 0)
671 engine.test("Delete SDNC", "DELETE", "/admin/v1/sdns/{}?FORCE=True".format(sdnc_id), headers_json, None,
tiernocd54a4a2018-09-12 16:40:35 +0200672 202, None, 0)
673
tierno55ba2e62018-12-11 17:22:22 +0000674 engine.test("Delete WIM", "DELETE",
675 "/admin/v1/wim_accounts/{}?FORCE=True".format(wim_id), headers_json, None, 202, None, 0)
tiernoff6485d2018-11-28 17:19:46 +0000676 engine.test("Check VIM is deleted", "GET", "/admin/v1/vim_accounts/{}".format(vim_id), headers_yaml,
tiernocd54a4a2018-09-12 16:40:35 +0200677 None, 404, r_header_yaml, "yaml")
tiernoff6485d2018-11-28 17:19:46 +0000678 engine.test("Check SDN is deleted", "GET", "/admin/v1/sdns/{}".format(sdnc_id), headers_yaml, None,
tiernocd54a4a2018-09-12 16:40:35 +0200679 404, r_header_yaml, "yaml")
tierno55ba2e62018-12-11 17:22:22 +0000680 engine.test("Check WIM is deleted", "GET", "/admin/v1/wim_accounts/{}".format(wim_id), headers_yaml,
681 None, 404, r_header_yaml, "yaml")
tiernocd54a4a2018-09-12 16:40:35 +0200682 else:
tierno55ba2e62018-12-11 17:22:22 +0000683 if manual_check:
684 input('VIM, SDN, WIM has been deployed. Perform manual check and press enter to resume')
tiernocd54a4a2018-09-12 16:40:35 +0200685 # delete and wait until is really deleted
tiernoff6485d2018-11-28 17:19:46 +0000686 engine.test("Delete VIM remove port-mapping", "DELETE", "/admin/v1/vim_accounts/{}".format(vim_id),
tiernocd54a4a2018-09-12 16:40:35 +0200687 headers_json, None, (202, 201, 204), None, 0)
tiernoff6485d2018-11-28 17:19:46 +0000688 engine.test("Delete SDN", "DELETE", "/admin/v1/sdns/{}".format(sdnc_id), headers_json, None,
tiernocd54a4a2018-09-12 16:40:35 +0200689 (202, 201, 204), None, 0)
tierno55ba2e62018-12-11 17:22:22 +0000690 engine.test("Delete VIM", "DELETE", "/admin/v1/wim_accounts/{}".format(wim_id),
691 headers_json, None, (202, 201, 204), None, 0)
tiernoff6485d2018-11-28 17:19:46 +0000692 engine.wait_until_delete("/admin/v1/vim_accounts/{}".format(vim_id), timeout)
693 engine.wait_until_delete("/admin/v1/sdns/{}".format(sdnc_id), timeout)
tierno55ba2e62018-12-11 17:22:22 +0000694 engine.wait_until_delete("/admin/v1/wim_accounts/{}".format(wim_id), timeout)
tiernoc32ba4a2018-05-24 18:06:41 +0200695
696
697class TestDeploy:
698 description = "Base class for downloading descriptors from ETSI, onboard and deploy in real VIM"
699
700 def __init__(self):
tiernoff6485d2018-11-28 17:19:46 +0000701 self.test_name = "DEPLOY"
tiernoc32ba4a2018-05-24 18:06:41 +0200702 self.nsd_id = None
703 self.vim_id = None
gcalvino337ec512018-07-30 10:30:13 +0200704 self.ns_id = None
tiernocc103432018-10-19 14:10:35 +0200705 self.vnfds_id = []
tiernoc32ba4a2018-05-24 18:06:41 +0200706 self.descriptor_url = "https://osm-download.etsi.org/ftp/osm-3.0-three/2nd-hackfest/packages/"
707 self.vnfd_filenames = ("cirros_vnf.tar.gz",)
708 self.nsd_filename = "cirros_2vnf_ns.tar.gz"
tierno36ec8602018-11-02 17:27:11 +0100709 self.descriptor_edit = None
tiernoc32ba4a2018-05-24 18:06:41 +0200710 self.uses_configuration = False
tiernobee085c2018-12-12 17:03:04 +0000711 self.users = {}
712 self.passwords = {}
713 self.commands = {}
gcalvino337ec512018-07-30 10:30:13 +0200714 self.keys = {}
715 self.timeout = 120
tierno36ec8602018-11-02 17:27:11 +0100716 self.qforce = ""
tiernobee085c2018-12-12 17:03:04 +0000717 self.ns_params = None
tiernoc32ba4a2018-05-24 18:06:41 +0200718
719 def create_descriptors(self, engine):
gcalvino337ec512018-07-30 10:30:13 +0200720 temp_dir = os.path.dirname(os.path.abspath(__file__)) + "/temp/"
tiernoc32ba4a2018-05-24 18:06:41 +0200721 if not os.path.exists(temp_dir):
722 os.makedirs(temp_dir)
tierno36ec8602018-11-02 17:27:11 +0100723 for vnfd_index, vnfd_filename in enumerate(self.vnfd_filenames):
tiernoc32ba4a2018-05-24 18:06:41 +0200724 if "/" in vnfd_filename:
725 vnfd_filename_path = vnfd_filename
726 if not os.path.exists(vnfd_filename_path):
727 raise TestException("File '{}' does not exist".format(vnfd_filename_path))
728 else:
729 vnfd_filename_path = temp_dir + vnfd_filename
730 if not os.path.exists(vnfd_filename_path):
731 with open(vnfd_filename_path, "wb") as file:
732 response = requests.get(self.descriptor_url + vnfd_filename)
733 if response.status_code >= 300:
734 raise TestException("Error downloading descriptor from '{}': {}".format(
735 self.descriptor_url + vnfd_filename, response.status_code))
736 file.write(response.content)
737 if vnfd_filename_path.endswith(".yaml"):
738 headers = headers_yaml
739 else:
740 headers = headers_zip_yaml
tiernoff6485d2018-11-28 17:19:46 +0000741 if randint(0, 1) == 0:
tiernoc32ba4a2018-05-24 18:06:41 +0200742 # vnfd CREATE AND UPLOAD in one step:
tiernoff6485d2018-11-28 17:19:46 +0000743 engine.test("Onboard VNFD in one step", "POST",
tierno36ec8602018-11-02 17:27:11 +0100744 "/vnfpkgm/v1/vnf_packages_content" + self.qforce, headers, "@b" + vnfd_filename_path, 201,
tiernof717cbe2018-12-03 16:35:42 +0000745 r_headers_yaml_location_vnfd,
tierno36ec8602018-11-02 17:27:11 +0100746 "yaml")
tiernoff6485d2018-11-28 17:19:46 +0000747 self.vnfds_id.append(engine.last_id)
tiernoc32ba4a2018-05-24 18:06:41 +0200748 else:
749 # vnfd CREATE AND UPLOAD ZIP
tiernoff6485d2018-11-28 17:19:46 +0000750 engine.test("Onboard VNFD step 1", "POST", "/vnfpkgm/v1/vnf_packages",
tiernoc32ba4a2018-05-24 18:06:41 +0200751 headers_json, None, 201,
752 {"Location": "/vnfpkgm/v1/vnf_packages/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000753 self.vnfds_id.append(engine.last_id)
754 engine.test("Onboard VNFD step 2 as ZIP", "PUT",
tierno36ec8602018-11-02 17:27:11 +0100755 "/vnfpkgm/v1/vnf_packages/<>/package_content" + self.qforce,
tiernoc32ba4a2018-05-24 18:06:41 +0200756 headers, "@b" + vnfd_filename_path, 204, None, 0)
tiernoc32ba4a2018-05-24 18:06:41 +0200757
tierno36ec8602018-11-02 17:27:11 +0100758 if self.descriptor_edit:
759 if "vnfd{}".format(vnfd_index) in self.descriptor_edit:
760 # Modify VNFD
tiernoff6485d2018-11-28 17:19:46 +0000761 engine.test("Edit VNFD ", "PATCH",
tierno36ec8602018-11-02 17:27:11 +0100762 "/vnfpkgm/v1/vnf_packages/{}".format(self.vnfds_id[-1]),
763 headers_yaml, self.descriptor_edit["vnfd{}".format(vnfd_index)], 204, None, None)
tierno36ec8602018-11-02 17:27:11 +0100764
tiernoc32ba4a2018-05-24 18:06:41 +0200765 if "/" in self.nsd_filename:
766 nsd_filename_path = self.nsd_filename
767 if not os.path.exists(nsd_filename_path):
768 raise TestException("File '{}' does not exist".format(nsd_filename_path))
769 else:
770 nsd_filename_path = temp_dir + self.nsd_filename
771 if not os.path.exists(nsd_filename_path):
772 with open(nsd_filename_path, "wb") as file:
773 response = requests.get(self.descriptor_url + self.nsd_filename)
774 if response.status_code >= 300:
775 raise TestException("Error downloading descriptor from '{}': {}".format(
776 self.descriptor_url + self.nsd_filename, response.status_code))
777 file.write(response.content)
778 if nsd_filename_path.endswith(".yaml"):
779 headers = headers_yaml
780 else:
781 headers = headers_zip_yaml
782
tiernoff6485d2018-11-28 17:19:46 +0000783 if randint(0, 1) == 0:
tiernoc32ba4a2018-05-24 18:06:41 +0200784 # nsd CREATE AND UPLOAD in one step:
tiernoff6485d2018-11-28 17:19:46 +0000785 engine.test("Onboard NSD in one step", "POST",
tierno36ec8602018-11-02 17:27:11 +0100786 "/nsd/v1/ns_descriptors_content" + self.qforce, headers, "@b" + nsd_filename_path, 201,
tiernof717cbe2018-12-03 16:35:42 +0000787 r_headers_yaml_location_nsd, yaml)
tiernoff6485d2018-11-28 17:19:46 +0000788 self.nsd_id = engine.last_id
tiernoc32ba4a2018-05-24 18:06:41 +0200789 else:
790 # nsd CREATE AND UPLOAD ZIP
tiernoff6485d2018-11-28 17:19:46 +0000791 engine.test("Onboard NSD step 1", "POST", "/nsd/v1/ns_descriptors",
tiernoc32ba4a2018-05-24 18:06:41 +0200792 headers_json, None, 201,
793 {"Location": "/nsd/v1/ns_descriptors/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000794 self.nsd_id = engine.last_id
795 engine.test("Onboard NSD step 2 as ZIP", "PUT",
tierno36ec8602018-11-02 17:27:11 +0100796 "/nsd/v1/ns_descriptors/<>/nsd_content" + self.qforce,
tiernoc32ba4a2018-05-24 18:06:41 +0200797 headers, "@b" + nsd_filename_path, 204, None, 0)
tierno36ec8602018-11-02 17:27:11 +0100798
799 if self.descriptor_edit and "nsd" in self.descriptor_edit:
800 # Modify NSD
tiernoff6485d2018-11-28 17:19:46 +0000801 engine.test("Edit NSD ", "PATCH",
tierno36ec8602018-11-02 17:27:11 +0100802 "/nsd/v1/ns_descriptors/{}".format(self.nsd_id),
803 headers_yaml, self.descriptor_edit["nsd"], 204, None, None)
tiernoc32ba4a2018-05-24 18:06:41 +0200804
805 def delete_descriptors(self, engine):
806 # delete descriptors
tiernoff6485d2018-11-28 17:19:46 +0000807 engine.test("Delete NSSD SOL005", "DELETE",
tierno36ec8602018-11-02 17:27:11 +0100808 "/nsd/v1/ns_descriptors/{}".format(self.nsd_id),
tiernoc32ba4a2018-05-24 18:06:41 +0200809 headers_yaml, None, 204, None, 0)
tierno36ec8602018-11-02 17:27:11 +0100810 for vnfd_id in self.vnfds_id:
tiernoff6485d2018-11-28 17:19:46 +0000811 engine.test("Delete VNFD SOL005", "DELETE",
tierno36ec8602018-11-02 17:27:11 +0100812 "/vnfpkgm/v1/vnf_packages/{}".format(vnfd_id), headers_yaml, None, 204, None, 0)
tiernoc32ba4a2018-05-24 18:06:41 +0200813
814 def instantiate(self, engine, ns_data):
815 ns_data_text = yaml.safe_dump(ns_data, default_flow_style=True, width=256)
816 # create NS Two steps
tiernoff6485d2018-11-28 17:19:46 +0000817 r = engine.test("Create NS step 1", "POST", "/nslcm/v1/ns_instances",
tiernoc32ba4a2018-05-24 18:06:41 +0200818 headers_yaml, ns_data_text, 201,
819 {"Location": "nslcm/v1/ns_instances/", "Content-Type": "application/yaml"}, "yaml")
tiernoff6485d2018-11-28 17:19:46 +0000820 if not r:
821 return
822 self.ns_id = engine.last_id
823 engine.test("Instantiate NS step 2", "POST",
824 "/nslcm/v1/ns_instances/{}/instantiate".format(self.ns_id), headers_yaml, ns_data_text,
tiernof717cbe2018-12-03 16:35:42 +0000825 201, r_headers_yaml_location_nslcmop, "yaml")
tiernoff6485d2018-11-28 17:19:46 +0000826 nslcmop_id = engine.last_id
tiernoc32ba4a2018-05-24 18:06:41 +0200827
828 if test_osm:
829 # Wait until status is Ok
tiernoff6485d2018-11-28 17:19:46 +0000830 timeout = timeout_configure if self.uses_configuration else timeout_deploy
831 engine.wait_operation_ready("ns", nslcmop_id, timeout)
tiernoc32ba4a2018-05-24 18:06:41 +0200832
833 def terminate(self, engine):
834 # remove deployment
835 if test_osm:
tiernoff6485d2018-11-28 17:19:46 +0000836 engine.test("Terminate NS", "POST", "/nslcm/v1/ns_instances/{}/terminate".format(self.ns_id), headers_yaml,
tiernof717cbe2018-12-03 16:35:42 +0000837 None, 201, r_headers_yaml_location_nslcmop, "yaml")
tiernoff6485d2018-11-28 17:19:46 +0000838 nslcmop2_id = engine.last_id
tiernoc32ba4a2018-05-24 18:06:41 +0200839 # Wait until status is Ok
tiernoff6485d2018-11-28 17:19:46 +0000840 engine.wait_operation_ready("ns", nslcmop2_id, timeout_deploy)
tiernoc32ba4a2018-05-24 18:06:41 +0200841
tiernoff6485d2018-11-28 17:19:46 +0000842 engine.test("Delete NS", "DELETE", "/nslcm/v1/ns_instances/{}".format(self.ns_id), headers_yaml, None,
843 204, None, 0)
tiernoc32ba4a2018-05-24 18:06:41 +0200844 else:
tiernoff6485d2018-11-28 17:19:46 +0000845 engine.test("Delete NS with FORCE", "DELETE", "/nslcm/v1/ns_instances/{}?FORCE=True".format(self.ns_id),
846 headers_yaml, None, 204, None, 0)
tiernoc32ba4a2018-05-24 18:06:41 +0200847
848 # check all it is deleted
tiernoff6485d2018-11-28 17:19:46 +0000849 engine.test("Check NS is deleted", "GET", "/nslcm/v1/ns_instances/{}".format(self.ns_id), headers_yaml, None,
850 404, None, "yaml")
851 r = engine.test("Check NSLCMOPs are deleted", "GET",
852 "/nslcm/v1/ns_lcm_op_occs?nsInstanceId={}".format(self.ns_id), headers_json, None,
tiernoc32ba4a2018-05-24 18:06:41 +0200853 200, None, "json")
tiernoff6485d2018-11-28 17:19:46 +0000854 if not r:
855 return
tiernoc32ba4a2018-05-24 18:06:41 +0200856 nslcmops = r.json()
857 if not isinstance(nslcmops, list) or nslcmops:
tiernoff6485d2018-11-28 17:19:46 +0000858 raise TestException("NS {} deleted but with ns_lcm_op_occ active: {}".format(self.ns_id, nslcmops))
tiernoc32ba4a2018-05-24 18:06:41 +0200859
gcalvino337ec512018-07-30 10:30:13 +0200860 def test_ns(self, engine, test_osm, commands=None, users=None, passwds=None, keys=None, timeout=0):
861
tiernoff6485d2018-11-28 17:19:46 +0000862 r = engine.test("GET VNFR IDs", "GET",
gcalvino337ec512018-07-30 10:30:13 +0200863 "/nslcm/v1/ns_instances/{}".format(self.ns_id), headers_json, None,
864 200, r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000865 if not r:
866 return
gcalvino337ec512018-07-30 10:30:13 +0200867 ns_data = r.json()
868
869 vnfr_list = ns_data['constituent-vnfr-ref']
870 time = 0
tiernobee085c2018-12-12 17:03:04 +0000871 _commands = commands if commands is not None else self.commands
872 _users = users if users is not None else self.users
873 _passwds = passwds if passwds is not None else self.passwords
874 _keys = keys if keys is not None else self.keys
875 _timeout = timeout if timeout != 0 else self.timeout
gcalvino337ec512018-07-30 10:30:13 +0200876
877 for vnfr_id in vnfr_list:
tiernoff6485d2018-11-28 17:19:46 +0000878 r = engine.test("Get VNFR to get IP_ADDRESS", "GET",
gcalvino337ec512018-07-30 10:30:13 +0200879 "/nslcm/v1/vnfrs/{}".format(vnfr_id), headers_json, None,
880 200, r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000881 if not r:
882 continue
gcalvino337ec512018-07-30 10:30:13 +0200883 vnfr_data = r.json()
884
tiernoff6485d2018-11-28 17:19:46 +0000885 vnf_index = str(vnfr_data["member-vnf-index-ref"])
tiernobee085c2018-12-12 17:03:04 +0000886 if not _commands.get(vnf_index):
tiernoff6485d2018-11-28 17:19:46 +0000887 continue
gcalvino337ec512018-07-30 10:30:13 +0200888 if vnfr_data.get("ip-address"):
tiernobee085c2018-12-12 17:03:04 +0000889 description = "Exec command='{}' at VNFR={} IP={}".format(_commands.get(vnf_index)[0], vnf_index,
tiernoff6485d2018-11-28 17:19:46 +0000890 vnfr_data['ip-address'])
891 engine.step += 1
892 test_description = "{}{} {}".format(engine.test_name, engine.step, description)
gcalvino337ec512018-07-30 10:30:13 +0200893 logger.warning(test_description)
tiernobee085c2018-12-12 17:03:04 +0000894 while _timeout >= time:
gcalvino337ec512018-07-30 10:30:13 +0200895 result, message = self.do_checks([vnfr_data["ip-address"]],
896 vnf_index=vnfr_data["member-vnf-index-ref"],
tiernobee085c2018-12-12 17:03:04 +0000897 commands=_commands.get(vnf_index), user=_users.get(vnf_index),
898 passwd=_passwds.get(vnf_index), key=_keys.get(vnf_index))
gcalvino337ec512018-07-30 10:30:13 +0200899 if result == 1:
tiernoff6485d2018-11-28 17:19:46 +0000900 engine.passed_tests += 1
901 logger.debug(message)
gcalvino337ec512018-07-30 10:30:13 +0200902 break
903 elif result == 0:
904 time += 20
905 sleep(20)
906 elif result == -1:
tiernoff6485d2018-11-28 17:19:46 +0000907 engine.failed_tests += 1
908 logger.error(message)
gcalvino337ec512018-07-30 10:30:13 +0200909 break
910 else:
911 time -= 20
tiernoff6485d2018-11-28 17:19:46 +0000912 engine.failed_tests += 1
913 logger.error(message)
gcalvino337ec512018-07-30 10:30:13 +0200914 else:
tiernoff6485d2018-11-28 17:19:46 +0000915 engine.failed_tests += 1
916 logger.error("VNFR {} has not mgmt address. Check failed".format(vnfr_id))
gcalvino337ec512018-07-30 10:30:13 +0200917
918 def do_checks(self, ip, vnf_index, commands=[], user=None, passwd=None, key=None):
919 try:
920 import urllib3
921 from pssh.clients import ParallelSSHClient
922 from pssh.utils import load_private_key
923 from ssh2 import exceptions as ssh2Exception
924 except ImportError as e:
tierno36ec8602018-11-02 17:27:11 +0100925 logger.critical("Package <pssh> or/and <urllib3> is not installed. Please add them with 'pip3 install "
926 "parallel-ssh urllib3': {}".format(e))
tiernoff6485d2018-11-28 17:19:46 +0000927 return -1, "install needed packages 'pip3 install parallel-ssh urllib3'"
gcalvino337ec512018-07-30 10:30:13 +0200928 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
929 try:
930 p_host = os.environ.get("PROXY_HOST")
931 p_user = os.environ.get("PROXY_USER")
932 p_password = os.environ.get("PROXY_PASSWD")
933
934 if key:
935 pkey = load_private_key(key)
936 else:
937 pkey = None
938
939 client = ParallelSSHClient(ip, user=user, password=passwd, pkey=pkey, proxy_host=p_host,
940 proxy_user=p_user, proxy_password=p_password, timeout=10, num_retries=0)
941 for cmd in commands:
942 output = client.run_command(cmd)
943 client.join(output)
944 if output[ip[0]].exit_code:
tiernobee085c2018-12-12 17:03:04 +0000945 return -1, "VNFR {} command '{}' returns error: '{}'".format(ip[0], cmd,
946 "\n".join(output[ip[0]].stderr))
gcalvino337ec512018-07-30 10:30:13 +0200947 else:
tiernobee085c2018-12-12 17:03:04 +0000948 return 1, "VNFR {} command '{}' successful".format(ip[0], cmd)
gcalvino337ec512018-07-30 10:30:13 +0200949 except (ssh2Exception.ChannelFailure, ssh2Exception.SocketDisconnectError, ssh2Exception.SocketTimeout,
950 ssh2Exception.SocketRecvError) as e:
951 return 0, "Timeout accessing the VNFR {}: {}".format(ip[0], str(e))
952 except Exception as e:
953 return -1, "ERROR checking the VNFR {}: {}".format(ip[0], str(e))
tiernoc32ba4a2018-05-24 18:06:41 +0200954
tiernobee085c2018-12-12 17:03:04 +0000955 def additional_operations(self, engine, test_osm, manual_check):
tiernoc32ba4a2018-05-24 18:06:41 +0200956 pass
957
958 def run(self, engine, test_osm, manual_check, test_params=None):
tiernoff6485d2018-11-28 17:19:46 +0000959 engine.set_test_name(self.test_name)
tiernoc32ba4a2018-05-24 18:06:41 +0200960 engine.get_autorization()
961 nsname = os.environ.get("OSMNBITEST_NS_NAME", "OSMNBITEST")
962 if test_params:
963 if "vnfd-files" in test_params:
964 self.vnfd_filenames = test_params["vnfd-files"].split(",")
965 if "nsd-file" in test_params:
966 self.nsd_filename = test_params["nsd-file"]
967 if test_params.get("ns-name"):
968 nsname = test_params["ns-name"]
969 self.create_descriptors(engine)
970
971 # create real VIM if not exist
972 self.vim_id = engine.get_create_vim(test_osm)
973 ns_data = {"nsDescription": "default description", "nsName": nsname, "nsdId": self.nsd_id,
974 "vimAccountId": self.vim_id}
tiernobee085c2018-12-12 17:03:04 +0000975 if self.ns_params:
976 ns_data.update(self.ns_params)
tiernoc32ba4a2018-05-24 18:06:41 +0200977 if test_params and test_params.get("ns-config"):
978 if isinstance(test_params["ns-config"], str):
979 ns_data.update(yaml.load(test_params["ns-config"]))
980 else:
981 ns_data.update(test_params["ns-config"])
982 self.instantiate(engine, ns_data)
983
984 if manual_check:
985 input('NS has been deployed. Perform manual check and press enter to resume')
tiernobee085c2018-12-12 17:03:04 +0000986 if test_osm and self.commands:
987 self.test_ns(engine, test_osm)
988 self.additional_operations(engine, test_osm, manual_check)
tiernoc32ba4a2018-05-24 18:06:41 +0200989 self.terminate(engine)
990 self.delete_descriptors(engine)
991
992
993class TestDeployHackfestCirros(TestDeploy):
994 description = "Load and deploy Hackfest cirros_2vnf_ns example"
995
996 def __init__(self):
997 super().__init__()
tiernoff6485d2018-11-28 17:19:46 +0000998 self.test_name = "CIRROS"
tiernoc32ba4a2018-05-24 18:06:41 +0200999 self.vnfd_filenames = ("cirros_vnf.tar.gz",)
1000 self.nsd_filename = "cirros_2vnf_ns.tar.gz"
tiernobee085c2018-12-12 17:03:04 +00001001 self.commands = {'1': ['ls -lrt', ], '2': ['ls -lrt', ]}
1002 self.users = {'1': "cirros", '2': "cirros"}
1003 self.passwords = {'1': "cubswin:)", '2': "cubswin:)"}
tiernoc32ba4a2018-05-24 18:06:41 +02001004
tierno932499c2019-01-28 17:28:10 +00001005 def terminate(self, engine):
1006 # Make a delete in one step, overriding the normal two step of TestDeploy that launched terminate and delete
1007 if test_osm:
1008 engine.test("Terminate and delete NS in one step", "DELETE", "/nslcm/v1/ns_instances_content/{}".
1009 format(self.ns_id), headers_yaml, None, 202, None, "yaml")
1010
1011 engine .wait_until_delete("/nslcm/v1/ns_instances/{}".format(self.ns_id), timeout_deploy)
1012 else:
1013 engine.test("Delete NS with FORCE", "DELETE", "/nslcm/v1/ns_instances/{}?FORCE=True".format(self.ns_id),
1014 headers_yaml, None, 204, None, 0)
1015
1016 # check all it is deleted
1017 engine.test("Check NS is deleted", "GET", "/nslcm/v1/ns_instances/{}".format(self.ns_id), headers_yaml, None,
1018 404, None, "yaml")
1019 r = engine.test("Check NSLCMOPs are deleted", "GET",
1020 "/nslcm/v1/ns_lcm_op_occs?nsInstanceId={}".format(self.ns_id), headers_json, None,
1021 200, None, "json")
1022 if not r:
1023 return
1024 nslcmops = r.json()
1025 if not isinstance(nslcmops, list) or nslcmops:
1026 raise TestException("NS {} deleted but with ns_lcm_op_occ active: {}".format(self.ns_id, nslcmops))
1027
tiernoc32ba4a2018-05-24 18:06:41 +02001028
tiernocc103432018-10-19 14:10:35 +02001029class TestDeployHackfest1(TestDeploy):
1030 description = "Load and deploy Hackfest_1_vnfd example"
1031
1032 def __init__(self):
1033 super().__init__()
tiernoff6485d2018-11-28 17:19:46 +00001034 self.test_name = "HACKFEST1-"
tiernocc103432018-10-19 14:10:35 +02001035 self.vnfd_filenames = ("hackfest_1_vnfd.tar.gz",)
1036 self.nsd_filename = "hackfest_1_nsd.tar.gz"
tiernobee085c2018-12-12 17:03:04 +00001037 # self.commands = {'1': ['ls -lrt', ], '2': ['ls -lrt', ]}
1038 # self.users = {'1': "cirros", '2': "cirros"}
1039 # self.passwords = {'1': "cubswin:)", '2': "cubswin:)"}
tiernocc103432018-10-19 14:10:35 +02001040
1041
1042class TestDeployHackfestCirrosScaling(TestDeploy):
1043 description = "Load and deploy Hackfest cirros_2vnf_ns example with scaling modifications"
1044
1045 def __init__(self):
1046 super().__init__()
tiernoff6485d2018-11-28 17:19:46 +00001047 self.test_name = "CIRROS-SCALE"
tiernocc103432018-10-19 14:10:35 +02001048 self.vnfd_filenames = ("cirros_vnf.tar.gz",)
1049 self.nsd_filename = "cirros_2vnf_ns.tar.gz"
1050
1051 def create_descriptors(self, engine):
1052 super().create_descriptors(engine)
1053 # Modify VNFD to add scaling and count=2
tiernoff6485d2018-11-28 17:19:46 +00001054 self.descriptor_edit = {
1055 "vnfd0": {
1056 "vdu": {
1057 "$id: 'cirros_vnfd-VM'": {"count": 2}
1058 },
1059 "scaling-group-descriptor": [{
1060 "name": "scale_cirros",
1061 "max-instance-count": 2,
1062 "vdu": [{
1063 "vdu-id-ref": "cirros_vnfd-VM",
1064 "count": 2
1065 }]
1066 }]
1067 }
1068 }
tiernocc103432018-10-19 14:10:35 +02001069
tiernobee085c2018-12-12 17:03:04 +00001070 def additional_operations(self, engine, test_osm, manual_check):
tiernocc103432018-10-19 14:10:35 +02001071 if not test_osm:
1072 return
1073 # 2 perform scale out twice
1074 payload = '{scaleType: SCALE_VNF, scaleVnfData: {scaleVnfType: SCALE_OUT, scaleByStepData: ' \
1075 '{scaling-group-descriptor: scale_cirros, member-vnf-index: "1"}}}'
1076 for i in range(0, 2):
tiernoff6485d2018-11-28 17:19:46 +00001077 engine.test("Execute scale action over NS", "POST",
1078 "/nslcm/v1/ns_instances/{}/scale".format(self.ns_id), headers_yaml, payload,
tiernof717cbe2018-12-03 16:35:42 +00001079 201, r_headers_yaml_location_nslcmop, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001080 nslcmop2_scale_out = engine.last_id
1081 engine.wait_operation_ready("ns", nslcmop2_scale_out, timeout_deploy)
tiernocc103432018-10-19 14:10:35 +02001082 if manual_check:
1083 input('NS scale out done. Check that two more vdus are there')
1084 # TODO check automatic
1085
1086 # 2 perform scale in
1087 payload = '{scaleType: SCALE_VNF, scaleVnfData: {scaleVnfType: SCALE_IN, scaleByStepData: ' \
1088 '{scaling-group-descriptor: scale_cirros, member-vnf-index: "1"}}}'
1089 for i in range(0, 2):
tiernoff6485d2018-11-28 17:19:46 +00001090 engine.test("Execute scale IN action over NS", "POST",
1091 "/nslcm/v1/ns_instances/{}/scale".format(self.ns_id), headers_yaml, payload,
tiernof717cbe2018-12-03 16:35:42 +00001092 201, r_headers_yaml_location_nslcmop, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001093 nslcmop2_scale_in = engine.last_id
1094 engine.wait_operation_ready("ns", nslcmop2_scale_in, timeout_deploy)
tiernocc103432018-10-19 14:10:35 +02001095 if manual_check:
1096 input('NS scale in done. Check that two less vdus are there')
1097 # TODO check automatic
1098
1099 # perform scale in that must fail as reached limit
tiernoff6485d2018-11-28 17:19:46 +00001100 engine.test("Execute scale IN out of limit action over NS", "POST",
1101 "/nslcm/v1/ns_instances/{}/scale".format(self.ns_id), headers_yaml, payload,
tiernof717cbe2018-12-03 16:35:42 +00001102 201, r_headers_yaml_location_nslcmop, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001103 nslcmop2_scale_in = engine.last_id
1104 engine.wait_operation_ready("ns", nslcmop2_scale_in, timeout_deploy, expected_fail=True)
tiernocc103432018-10-19 14:10:35 +02001105
1106
tiernoc32ba4a2018-05-24 18:06:41 +02001107class TestDeployIpMac(TestDeploy):
1108 description = "Load and deploy descriptor examples setting mac, ip address at descriptor and instantiate params"
1109
1110 def __init__(self):
1111 super().__init__()
tiernoff6485d2018-11-28 17:19:46 +00001112 self.test_name = "SetIpMac"
tiernoc32ba4a2018-05-24 18:06:41 +02001113 self.vnfd_filenames = ("vnfd_2vdu_set_ip_mac2.yaml", "vnfd_2vdu_set_ip_mac.yaml")
1114 self.nsd_filename = "scenario_2vdu_set_ip_mac.yaml"
1115 self.descriptor_url = \
1116 "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 +00001117 self.commands = {'1': ['ls -lrt', ], '2': ['ls -lrt', ]}
1118 self.users = {'1': "osm", '2': "osm"}
1119 self.passwords = {'1': "osm4u", '2': "osm4u"}
gcalvino337ec512018-07-30 10:30:13 +02001120 self.timeout = 360
tiernoc32ba4a2018-05-24 18:06:41 +02001121
1122 def run(self, engine, test_osm, manual_check, test_params=None):
1123 # super().run(engine, test_osm, manual_check, test_params)
1124 # run again setting IPs with instantiate parameters
1125 instantiation_params = {
1126 "vnf": [
1127 {
1128 "member-vnf-index": "1",
1129 "internal-vld": [
1130 {
1131 "name": "internal_vld1", # net_internal
1132 "ip-profile": {
1133 "ip-version": "ipv4",
1134 "subnet-address": "10.9.8.0/24",
1135 "dhcp-params": {"count": 100, "start-address": "10.9.8.100"}
1136 },
1137 "internal-connection-point": [
1138 {
1139 "id-ref": "eth2",
1140 "ip-address": "10.9.8.2",
1141 },
1142 {
1143 "id-ref": "eth3",
1144 "ip-address": "10.9.8.3",
1145 }
1146 ]
1147 },
1148 ],
1149
1150 "vdu": [
1151 {
1152 "id": "VM1",
1153 "interface": [
tierno7ce1db92018-07-25 12:50:52 +02001154 # {
1155 # "name": "iface11",
1156 # "floating-ip-required": True,
1157 # },
tiernoc32ba4a2018-05-24 18:06:41 +02001158 {
1159 "name": "iface13",
1160 "mac-address": "52:33:44:55:66:13"
1161 },
1162 ],
1163 },
1164 {
1165 "id": "VM2",
1166 "interface": [
1167 {
1168 "name": "iface21",
gcalvino337ec512018-07-30 10:30:13 +02001169 "ip-address": "10.31.31.22",
tiernoc32ba4a2018-05-24 18:06:41 +02001170 "mac-address": "52:33:44:55:66:21"
1171 },
1172 ],
1173 },
1174 ]
1175 },
1176 ]
1177 }
gcalvino337ec512018-07-30 10:30:13 +02001178
tiernoc32ba4a2018-05-24 18:06:41 +02001179 super().run(engine, test_osm, manual_check, test_params={"ns-config": instantiation_params})
1180
1181
1182class TestDeployHackfest4(TestDeploy):
1183 description = "Load and deploy Hackfest 4 example."
1184
1185 def __init__(self):
1186 super().__init__()
tiernoff6485d2018-11-28 17:19:46 +00001187 self.test_name = "HACKFEST4-"
tiernoc32ba4a2018-05-24 18:06:41 +02001188 self.vnfd_filenames = ("hackfest_4_vnfd.tar.gz",)
1189 self.nsd_filename = "hackfest_4_nsd.tar.gz"
1190 self.uses_configuration = True
tiernobee085c2018-12-12 17:03:04 +00001191 self.commands = {'1': ['ls -lrt', ], '2': ['ls -lrt', ]}
1192 self.users = {'1': "ubuntu", '2': "ubuntu"}
1193 self.passwords = {'1': "osm4u", '2': "osm4u"}
tiernoc32ba4a2018-05-24 18:06:41 +02001194 # Modify VNFD to add scaling
tierno932499c2019-01-28 17:28:10 +00001195 # self.descriptor_edit = {
1196 # "vnfd0": {
1197 # 'vnf-configuration': {
1198 # 'config-primitive': [{
1199 # 'name': 'touch',
1200 # 'parameter': [{
1201 # 'name': 'filename',
1202 # 'data-type': 'STRING',
1203 # 'default-value': '/home/ubuntu/touched'
1204 # }]
1205 # }]
1206 # },
1207 # 'scaling-group-descriptor': [{
1208 # 'name': 'scale_dataVM',
1209 # 'scaling-policy': [{
1210 # 'threshold-time': 0,
1211 # 'name': 'auto_cpu_util_above_threshold',
1212 # 'scaling-type': 'automatic',
1213 # 'scaling-criteria': [{
1214 # 'name': 'cpu_util_above_threshold',
1215 # 'vnf-monitoring-param-ref': 'all_aaa_cpu_util',
1216 # 'scale-out-relational-operation': 'GE',
1217 # 'scale-in-threshold': 15,
1218 # 'scale-out-threshold': 60,
1219 # 'scale-in-relational-operation': 'LE'
1220 # }],
1221 # 'cooldown-time': 60
1222 # }],
1223 # 'max-instance-count': 10,
1224 # 'scaling-config-action': [
1225 # {'vnf-config-primitive-name-ref': 'touch',
1226 # 'trigger': 'post-scale-out'},
1227 # {'vnf-config-primitive-name-ref': 'touch',
1228 # 'trigger': 'pre-scale-in'}
1229 # ],
1230 # 'vdu': [{
1231 # 'vdu-id-ref': 'dataVM',
1232 # 'count': 1
1233 # }]
1234 # }]
1235 # }
1236 # }
tiernoc32ba4a2018-05-24 18:06:41 +02001237
tiernoc32ba4a2018-05-24 18:06:41 +02001238
1239class TestDeployHackfest3Charmed(TestDeploy):
tiernobee085c2018-12-12 17:03:04 +00001240 description = "Load and deploy Hackfest 3charmed_ns example"
tiernoc32ba4a2018-05-24 18:06:41 +02001241
1242 def __init__(self):
1243 super().__init__()
tiernoff6485d2018-11-28 17:19:46 +00001244 self.test_name = "HACKFEST3-"
tiernoc32ba4a2018-05-24 18:06:41 +02001245 self.vnfd_filenames = ("hackfest_3charmed_vnfd.tar.gz",)
1246 self.nsd_filename = "hackfest_3charmed_nsd.tar.gz"
1247 self.uses_configuration = True
tiernobee085c2018-12-12 17:03:04 +00001248 self.commands = {'1': ['ls -lrt /home/ubuntu/first-touch'], '2': ['ls -lrt /home/ubuntu/first-touch']}
1249 self.users = {'1': "ubuntu", '2': "ubuntu"}
1250 self.passwords = {'1': "osm4u", '2': "osm4u"}
tiernoc32ba4a2018-05-24 18:06:41 +02001251
tiernobee085c2018-12-12 17:03:04 +00001252 def additional_operations(self, engine, test_osm, manual_check):
tiernoc32ba4a2018-05-24 18:06:41 +02001253 if not test_osm:
1254 return
1255 # 1 perform action
1256 payload = '{member_vnf_index: "2", primitive: touch, primitive_params: { filename: /home/ubuntu/OSMTESTNBI }}'
tiernoff6485d2018-11-28 17:19:46 +00001257 engine.test("Exec service primitive over NS", "POST",
1258 "/nslcm/v1/ns_instances/{}/action".format(self.ns_id), headers_yaml, payload,
tiernof717cbe2018-12-03 16:35:42 +00001259 201, r_headers_yaml_location_nslcmop, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001260 nslcmop2_action = engine.last_id
tiernoc32ba4a2018-05-24 18:06:41 +02001261 # Wait until status is Ok
tiernoff6485d2018-11-28 17:19:46 +00001262 engine.wait_operation_ready("ns", nslcmop2_action, timeout_deploy)
tiernoc32ba4a2018-05-24 18:06:41 +02001263 if manual_check:
1264 input('NS service primitive has been executed. Check that file /home/ubuntu/OSMTESTNBI is present at '
1265 'TODO_PUT_IP')
tiernoff6485d2018-11-28 17:19:46 +00001266 if test_osm:
tiernobee085c2018-12-12 17:03:04 +00001267 commands = {'1': [''], '2': ['ls -lrt /home/ubuntu/OSMTESTNBI', ]}
1268 self.test_ns(engine, test_osm, commands=commands)
tiernoc32ba4a2018-05-24 18:06:41 +02001269
1270 # # 2 perform scale out
1271 # payload = '{scaleType: SCALE_VNF, scaleVnfData: {scaleVnfType: SCALE_OUT, scaleByStepData: ' \
1272 # '{scaling-group-descriptor: scale_dataVM, member-vnf-index: "1"}}}'
tiernoff6485d2018-11-28 17:19:46 +00001273 # engine.test("Execute scale action over NS", "POST",
1274 # "/nslcm/v1/ns_instances/{}/scale".format(self.ns_id), headers_yaml, payload,
tiernof717cbe2018-12-03 16:35:42 +00001275 # 201, r_headers_yaml_location_nslcmop, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001276 # nslcmop2_scale_out = engine.last_id
1277 # engine.wait_operation_ready("ns", nslcmop2_scale_out, timeout_deploy)
tiernoc32ba4a2018-05-24 18:06:41 +02001278 # if manual_check:
1279 # input('NS scale out done. Check that file /home/ubuntu/touched is present and new VM is created')
1280 # # TODO check automatic
1281 #
1282 # # 2 perform scale in
1283 # payload = '{scaleType: SCALE_VNF, scaleVnfData: {scaleVnfType: SCALE_IN, scaleByStepData: ' \
1284 # '{scaling-group-descriptor: scale_dataVM, member-vnf-index: "1"}}}'
tiernoff6485d2018-11-28 17:19:46 +00001285 # engine.test("Execute scale action over NS", "POST",
1286 # "/nslcm/v1/ns_instances/{}/scale".format(self.ns_id), headers_yaml, payload,
tiernof717cbe2018-12-03 16:35:42 +00001287 # 201, r_headers_yaml_location_nslcmop, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001288 # nslcmop2_scale_in = engine.last_id
1289 # engine.wait_operation_ready("ns", nslcmop2_scale_in, timeout_deploy)
tiernoc32ba4a2018-05-24 18:06:41 +02001290 # if manual_check:
1291 # input('NS scale in done. Check that file /home/ubuntu/touched is updated and new VM is deleted')
1292 # # TODO check automatic
1293
tiernof27c79b2018-03-12 17:08:42 +01001294
tiernoff6485d2018-11-28 17:19:46 +00001295class TestDeployHackfest3Charmed2(TestDeployHackfest3Charmed):
1296 description = "Load and deploy Hackfest 3charmed_ns example modified version of descriptors to have dots in " \
tiernobee085c2018-12-12 17:03:04 +00001297 "ids and member-vnf-index."
tiernoff6485d2018-11-28 17:19:46 +00001298
1299 def __init__(self):
1300 super().__init__()
tiernobee085c2018-12-12 17:03:04 +00001301 self.test_name = "HACKFEST3v2-"
tiernoff6485d2018-11-28 17:19:46 +00001302 self.qforce = "?FORCE=True"
1303 self.descriptor_edit = {
1304 "vnfd0": {
1305 "vdu": {
1306 "$[0]": {
1307 "interface": {"$[0]": {"external-connection-point-ref": "pdu-mgmt"}}
1308 },
1309 "$[1]": None
1310 },
1311 "vnf-configuration": None,
1312 "connection-point": {
1313 "$[0]": {
1314 "id": "pdu-mgmt",
1315 "name": "pdu-mgmt",
1316 "short-name": "pdu-mgmt"
1317 },
1318 "$[1]": None
1319 },
1320 "mgmt-interface": {"cp": "pdu-mgmt"},
1321 "description": "A vnf single vdu to be used as PDU",
1322 "id": "vdu-as-pdu",
1323 "internal-vld": {
1324 "$[0]": {
1325 "id": "pdu_internal",
1326 "name": "pdu_internal",
1327 "internal-connection-point": {"$[1]": None},
1328 "short-name": "pdu_internal",
1329 "type": "ELAN"
1330 }
1331 }
1332 },
1333
1334 # Modify NSD accordingly
1335 "nsd": {
1336 "constituent-vnfd": {
1337 "$[0]": {"vnfd-id-ref": "vdu-as-pdu"},
1338 "$[1]": None,
1339 },
1340 "description": "A nsd to deploy the vnf to act as as PDU",
1341 "id": "nsd-as-pdu",
1342 "name": "nsd-as-pdu",
1343 "short-name": "nsd-as-pdu",
1344 "vld": {
1345 "$[0]": {
1346 "id": "mgmt_pdu",
1347 "name": "mgmt_pdu",
1348 "short-name": "mgmt_pdu",
1349 "vnfd-connection-point-ref": {
1350 "$[0]": {
1351 "vnfd-connection-point-ref": "pdu-mgmt",
1352 "vnfd-id-ref": "vdu-as-pdu",
1353 },
1354 "$[1]": None
1355 },
1356 "type": "ELAN"
1357 },
1358 "$[1]": None,
1359 }
1360 }
1361 }
1362
1363
tiernobee085c2018-12-12 17:03:04 +00001364class TestDeployHackfest3Charmed3(TestDeployHackfest3Charmed):
1365 description = "Load and deploy Hackfest 3charmed_ns example modified version to test scaling and NS parameters"
1366
1367 def __init__(self):
1368 super().__init__()
1369 self.test_name = "HACKFEST3v3-"
tiernoa1c1b532019-01-16 14:12:22 +00001370 self.commands = {'1': ['ls -lrt /home/ubuntu/first-touch-1'], '2': ['ls -lrt /home/ubuntu/first-touch-2']}
tiernobee085c2018-12-12 17:03:04 +00001371 self.descriptor_edit = {
1372 "vnfd0": yaml.load(
1373 """
1374 scaling-group-descriptor:
1375 - name: "scale_dataVM"
1376 max-instance-count: 10
1377 scaling-policy:
1378 - name: "auto_cpu_util_above_threshold"
1379 scaling-type: "automatic"
1380 threshold-time: 0
1381 cooldown-time: 60
1382 scaling-criteria:
1383 - name: "cpu_util_above_threshold"
1384 scale-in-threshold: 15
1385 scale-in-relational-operation: "LE"
1386 scale-out-threshold: 60
1387 scale-out-relational-operation: "GE"
1388 vnf-monitoring-param-ref: "monitor1"
1389 vdu:
1390 - vdu-id-ref: dataVM
1391 count: 1
1392 scaling-config-action:
1393 - trigger: post-scale-out
1394 vnf-config-primitive-name-ref: touch
1395 - trigger: pre-scale-in
1396 vnf-config-primitive-name-ref: touch
1397 vdu:
1398 "$id: dataVM":
1399 monitoring-param:
1400 - id: "dataVM_cpu_util"
1401 nfvi-metric: "cpu_utilization"
1402
1403 monitoring-param:
1404 - id: "monitor1"
1405 name: "monitor1"
1406 aggregation-type: AVERAGE
1407 vdu-monitoring-param:
1408 vdu-ref: "dataVM"
1409 vdu-monitoring-param-ref: "dataVM_cpu_util"
1410 vnf-configuration:
1411 initial-config-primitive:
1412 "$[1]":
1413 parameter:
1414 "$[0]":
1415 value: "<touch-filename>" # default-value: /home/ubuntu/first-touch
tiernoa1c1b532019-01-16 14:12:22 +00001416 config-primitive:
1417 "$[0]":
1418 parameter:
1419 "$[0]":
1420 default-value: "<touch-filename2>"
tiernobee085c2018-12-12 17:03:04 +00001421 """)
1422 }
1423 self.ns_params = {
1424 "additionalParamsForVnf": [
1425 {"member-vnf-index": "1", "additionalParams": {"touch-filename": "/home/ubuntu/first-touch-1",
tiernoa1c1b532019-01-16 14:12:22 +00001426 "touch-filename2": "/home/ubuntu/second-touch-1"}},
1427 {"member-vnf-index": "2", "additionalParams": {"touch-filename": "/home/ubuntu/first-touch-2",
tiernobee085c2018-12-12 17:03:04 +00001428 "touch-filename2": "/home/ubuntu/second-touch-2"}},
1429 ]
1430 }
1431
1432 def additional_operations(self, engine, test_osm, manual_check):
1433 super().additional_operations(engine, test_osm, manual_check)
1434 if not test_osm:
1435 return
1436
1437 # 2 perform scale out
1438 payload = '{scaleType: SCALE_VNF, scaleVnfData: {scaleVnfType: SCALE_OUT, scaleByStepData: ' \
1439 '{scaling-group-descriptor: scale_dataVM, member-vnf-index: "1"}}}'
1440 engine.test("Execute scale action over NS", "POST",
1441 "/nslcm/v1/ns_instances/{}/scale".format(self.ns_id), headers_yaml, payload,
1442 201, r_headers_yaml_location_nslcmop, "yaml")
1443 nslcmop2_scale_out = engine.last_id
1444 engine.wait_operation_ready("ns", nslcmop2_scale_out, timeout_deploy)
1445 if manual_check:
tiernoa1c1b532019-01-16 14:12:22 +00001446 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 +00001447 if test_osm:
tiernoa1c1b532019-01-16 14:12:22 +00001448 commands = {'1': ['ls -lrt /home/ubuntu/second-touch-1', ]}
tiernobee085c2018-12-12 17:03:04 +00001449 self.test_ns(engine, test_osm, commands=commands)
1450 # TODO check automatic connection to scaled VM
1451
1452 # 2 perform scale in
1453 payload = '{scaleType: SCALE_VNF, scaleVnfData: {scaleVnfType: SCALE_IN, scaleByStepData: ' \
1454 '{scaling-group-descriptor: scale_dataVM, member-vnf-index: "1"}}}'
1455 engine.test("Execute scale action over NS", "POST",
1456 "/nslcm/v1/ns_instances/{}/scale".format(self.ns_id), headers_yaml, payload,
1457 201, r_headers_yaml_location_nslcmop, "yaml")
1458 nslcmop2_scale_in = engine.last_id
1459 engine.wait_operation_ready("ns", nslcmop2_scale_in, timeout_deploy)
1460 if manual_check:
tiernoa1c1b532019-01-16 14:12:22 +00001461 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 +00001462 # TODO check automatic
1463
1464
1465class TestDeploySimpleCharm(TestDeploy):
1466 description = "Deploy hackfest-4 hackfest_simplecharm example"
1467
1468 def __init__(self):
1469 super().__init__()
1470 self.test_name = "HACKFEST-SIMPLE"
1471 self.descriptor_url = "https://osm-download.etsi.org/ftp/osm-4.0-four/4th-hackfest/packages/"
1472 self.vnfd_filenames = ("hackfest_simplecharm_vnf.tar.gz",)
1473 self.nsd_filename = "hackfest_simplecharm_ns.tar.gz"
1474 self.uses_configuration = True
1475 self.commands = {'1': [''], '2': ['ls -lrt /home/ubuntu/first-touch', ]}
1476 self.users = {'1': "ubuntu", '2': "ubuntu"}
1477 self.passwords = {'1': "osm4u", '2': "osm4u"}
1478
1479
1480class TestDeploySimpleCharm2(TestDeploySimpleCharm):
1481 description = "Deploy hackfest-4 hackfest_simplecharm example changing naming to contain dots on ids and " \
1482 "vnf-member-index"
1483
1484 def __init__(self):
1485 super().__init__()
1486 self.test_name = "HACKFEST-SIMPLE2-"
1487 self.qforce = "?FORCE=True"
1488 self.descriptor_edit = {
1489 "vnfd0": {
1490 "id": "hackfest.simplecharm.vnf"
1491 },
1492
1493 "nsd": {
1494 "id": "hackfest.simplecharm.ns",
1495 "constituent-vnfd": {
1496 "$[0]": {"vnfd-id-ref": "hackfest.simplecharm.vnf", "member-vnf-index": "$1"},
1497 "$[1]": {"vnfd-id-ref": "hackfest.simplecharm.vnf", "member-vnf-index": "$2"},
1498 },
1499 "vld": {
1500 "$[0]": {
1501 "vnfd-connection-point-ref": {"$[0]": {"member-vnf-index-ref": "$1",
1502 "vnfd-id-ref": "hackfest.simplecharm.vnf"},
1503 "$[1]": {"member-vnf-index-ref": "$2",
1504 "vnfd-id-ref": "hackfest.simplecharm.vnf"}},
1505 },
1506 "$[1]": {
1507 "vnfd-connection-point-ref": {"$[0]": {"member-vnf-index-ref": "$1",
1508 "vnfd-id-ref": "hackfest.simplecharm.vnf"},
1509 "$[1]": {"member-vnf-index-ref": "$2",
1510 "vnfd-id-ref": "hackfest.simplecharm.vnf"}},
1511 },
1512 }
1513 }
1514 }
1515
1516
tierno36ec8602018-11-02 17:27:11 +01001517class TestDeploySingleVdu(TestDeployHackfest3Charmed):
1518 description = "Generate a single VDU base on editing Hackfest3Charmed descriptors and deploy"
1519
1520 def __init__(self):
1521 super().__init__()
tiernoff6485d2018-11-28 17:19:46 +00001522 self.test_name = "SingleVDU"
tierno36ec8602018-11-02 17:27:11 +01001523 self.qforce = "?FORCE=True"
1524 self.descriptor_edit = {
1525 # Modify VNFD to remove one VDU
1526 "vnfd0": {
1527 "vdu": {
1528 "$[0]": {
1529 "interface": {"$[0]": {"external-connection-point-ref": "pdu-mgmt"}}
1530 },
1531 "$[1]": None
1532 },
1533 "vnf-configuration": None,
1534 "connection-point": {
1535 "$[0]": {
1536 "id": "pdu-mgmt",
1537 "name": "pdu-mgmt",
1538 "short-name": "pdu-mgmt"
1539 },
1540 "$[1]": None
1541 },
1542 "mgmt-interface": {"cp": "pdu-mgmt"},
1543 "description": "A vnf single vdu to be used as PDU",
1544 "id": "vdu-as-pdu",
1545 "internal-vld": {
1546 "$[0]": {
1547 "id": "pdu_internal",
1548 "name": "pdu_internal",
1549 "internal-connection-point": {"$[1]": None},
1550 "short-name": "pdu_internal",
1551 "type": "ELAN"
1552 }
1553 }
1554 },
1555
1556 # Modify NSD accordingly
1557 "nsd": {
1558 "constituent-vnfd": {
1559 "$[0]": {"vnfd-id-ref": "vdu-as-pdu"},
1560 "$[1]": None,
1561 },
1562 "description": "A nsd to deploy the vnf to act as as PDU",
1563 "id": "nsd-as-pdu",
1564 "name": "nsd-as-pdu",
1565 "short-name": "nsd-as-pdu",
1566 "vld": {
1567 "$[0]": {
1568 "id": "mgmt_pdu",
1569 "name": "mgmt_pdu",
1570 "short-name": "mgmt_pdu",
1571 "vnfd-connection-point-ref": {
1572 "$[0]": {
1573 "vnfd-connection-point-ref": "pdu-mgmt",
1574 "vnfd-id-ref": "vdu-as-pdu",
1575 },
1576 "$[1]": None
1577 },
1578 "type": "ELAN"
1579 },
1580 "$[1]": None,
1581 }
1582 }
1583 }
1584
1585
1586class TestDeployHnfd(TestDeployHackfest3Charmed):
1587 description = "Generate a HNFD base on editing Hackfest3Charmed descriptors and deploy"
1588
1589 def __init__(self):
1590 super().__init__()
tiernoff6485d2018-11-28 17:19:46 +00001591 self.test_name = "HNFD"
tierno36ec8602018-11-02 17:27:11 +01001592 self.pduDeploy = TestDeploySingleVdu()
1593 self.pdu_interface_0 = {}
1594 self.pdu_interface_1 = {}
1595
1596 self.pdu_id = None
1597 # self.vnf_to_pdu = """
1598 # vdu:
1599 # "$[0]":
1600 # pdu-type: PDU-TYPE-1
1601 # interface:
1602 # "$[0]":
1603 # name: mgmt-iface
1604 # "$[1]":
1605 # name: pdu-iface-internal
1606 # id: hfn1
1607 # description: HFND, one PDU + One VDU
1608 # name: hfn1
1609 # short-name: hfn1
1610 #
1611 # """
1612
1613 self.pdu_descriptor = {
1614 "name": "my-PDU",
1615 "type": "PDU-TYPE-1",
1616 "vim_accounts": "to-override",
1617 "interfaces": [
1618 {
1619 "name": "mgmt-iface",
1620 "mgmt": True,
1621 "type": "overlay",
1622 "ip-address": "to override",
1623 "mac-address": "mac_address",
1624 "vim-network-name": "mgmt",
1625 },
1626 {
1627 "name": "pdu-iface-internal",
1628 "mgmt": False,
1629 "type": "overlay",
1630 "ip-address": "to override",
1631 "mac-address": "mac_address",
1632 "vim-network-name": "pdu_internal", # OSMNBITEST-PDU-pdu_internal
1633 },
1634 ]
1635 }
1636 self.vnfd_filenames = ("hackfest_3charmed_vnfd.tar.gz", "hackfest_3charmed_vnfd.tar.gz")
1637
1638 self.descriptor_edit = {
1639 "vnfd0": {
1640 "id": "hfnd1",
1641 "name": "hfn1",
1642 "short-name": "hfn1",
1643 "vdu": {
1644 "$[0]": {
1645 "pdu-type": "PDU-TYPE-1",
1646 "interface": {
1647 "$[0]": {"name": "mgmt-iface"},
1648 "$[1]": {"name": "pdu-iface-internal"},
1649 }
1650 }
1651 }
1652 },
1653 "nsd": {
1654 "constituent-vnfd": {
1655 "$[1]": {"vnfd-id-ref": "hfnd1"}
tiernoff6485d2018-11-28 17:19:46 +00001656 },
1657 "vld": {
1658 "$[0]": {"vnfd-connection-point-ref": {"$[1]": {"vnfd-id-ref": "hfnd1"}}},
1659 "$[1]": {"vnfd-connection-point-ref": {"$[1]": {"vnfd-id-ref": "hfnd1"}}}
tierno36ec8602018-11-02 17:27:11 +01001660 }
1661 }
1662 }
1663
1664 def create_descriptors(self, engine):
1665 super().create_descriptors(engine)
1666
1667 # Create PDU
1668 self.pdu_descriptor["interfaces"][0].update(self.pdu_interface_0)
1669 self.pdu_descriptor["interfaces"][1].update(self.pdu_interface_1)
1670 self.pdu_descriptor["vim_accounts"] = [self.vim_id]
1671 # TODO get vim-network-name from vnfr.vld.name
1672 self.pdu_descriptor["interfaces"][1]["vim-network-name"] = "{}-{}-{}".format(
1673 os.environ.get("OSMNBITEST_NS_NAME", "OSMNBITEST"),
1674 "PDU", self.pdu_descriptor["interfaces"][1]["vim-network-name"])
tiernoff6485d2018-11-28 17:19:46 +00001675 engine.test("Onboard PDU descriptor", "POST", "/pdu/v1/pdu_descriptors",
tierno36ec8602018-11-02 17:27:11 +01001676 {"Location": "/pdu/v1/pdu_descriptors/", "Content-Type": "application/yaml"}, self.pdu_descriptor,
1677 201, r_header_yaml, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001678 self.pdu_id = engine.last_id
tierno36ec8602018-11-02 17:27:11 +01001679
1680 def run(self, engine, test_osm, manual_check, test_params=None):
1681 engine.get_autorization()
tiernoff6485d2018-11-28 17:19:46 +00001682 engine.set_test_name(self.test_name)
tierno36ec8602018-11-02 17:27:11 +01001683 nsname = os.environ.get("OSMNBITEST_NS_NAME", "OSMNBITEST")
1684
1685 # create real VIM if not exist
1686 self.vim_id = engine.get_create_vim(test_osm)
tiernoff6485d2018-11-28 17:19:46 +00001687 # instantiate PDU
tierno36ec8602018-11-02 17:27:11 +01001688 self.pduDeploy.create_descriptors(engine)
1689 self.pduDeploy.instantiate(engine, {"nsDescription": "to be used as PDU", "nsName": nsname + "-PDU",
1690 "nsdId": self.pduDeploy.nsd_id, "vimAccountId": self.vim_id})
1691 if manual_check:
1692 input('VNF to be used as PDU has been deployed. Perform manual check and press enter to resume')
tiernoff6485d2018-11-28 17:19:46 +00001693 if test_osm:
tiernobee085c2018-12-12 17:03:04 +00001694 self.pduDeploy.test_ns(engine, test_osm)
tierno36ec8602018-11-02 17:27:11 +01001695
1696 if test_osm:
tiernoff6485d2018-11-28 17:19:46 +00001697 r = engine.test("Get VNFR to obtain IP_ADDRESS", "GET",
tierno36ec8602018-11-02 17:27:11 +01001698 "/nslcm/v1/vnfrs?nsr-id-ref={}".format(self.pduDeploy.ns_id), headers_json, None,
1699 200, r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +00001700 if not r:
1701 return
tierno36ec8602018-11-02 17:27:11 +01001702 vnfr_data = r.json()
1703 # print(vnfr_data)
1704
1705 self.pdu_interface_0["ip-address"] = vnfr_data[0]["vdur"][0]["interfaces"][0].get("ip-address")
1706 self.pdu_interface_1["ip-address"] = vnfr_data[0]["vdur"][0]["interfaces"][1].get("ip-address")
1707 self.pdu_interface_0["mac-address"] = vnfr_data[0]["vdur"][0]["interfaces"][0].get("mac-address")
1708 self.pdu_interface_1["mac-address"] = vnfr_data[0]["vdur"][0]["interfaces"][1].get("mac-address")
1709 if not self.pdu_interface_0["ip-address"]:
1710 raise TestException("Vnfr has not managment ip address")
1711 else:
1712 self.pdu_interface_0["ip-address"] = "192.168.10.10"
1713 self.pdu_interface_1["ip-address"] = "192.168.11.10"
1714 self.pdu_interface_0["mac-address"] = "52:33:44:55:66:13"
1715 self.pdu_interface_1["mac-address"] = "52:33:44:55:66:14"
1716
1717 self.create_descriptors(engine)
1718
1719 ns_data = {"nsDescription": "default description", "nsName": nsname, "nsdId": self.nsd_id,
1720 "vimAccountId": self.vim_id}
1721 if test_params and test_params.get("ns-config"):
1722 if isinstance(test_params["ns-config"], str):
1723 ns_data.update(yaml.load(test_params["ns-config"]))
1724 else:
1725 ns_data.update(test_params["ns-config"])
1726
1727 self.instantiate(engine, ns_data)
1728 if manual_check:
1729 input('NS has been deployed. Perform manual check and press enter to resume')
tiernoff6485d2018-11-28 17:19:46 +00001730 if test_osm:
tiernobee085c2018-12-12 17:03:04 +00001731 self.test_ns(engine, test_osm)
1732 self.additional_operations(engine, test_osm, manual_check)
tierno36ec8602018-11-02 17:27:11 +01001733 self.terminate(engine)
1734 self.pduDeploy.terminate(engine)
1735 self.delete_descriptors(engine)
1736 self.pduDeploy.delete_descriptors(engine)
1737
tierno36ec8602018-11-02 17:27:11 +01001738 def delete_descriptors(self, engine):
1739 super().delete_descriptors(engine)
1740 # delete pdu
tiernoff6485d2018-11-28 17:19:46 +00001741 engine.test("Delete PDU SOL005", "DELETE",
tierno36ec8602018-11-02 17:27:11 +01001742 "/pdu/v1/pdu_descriptors/{}".format(self.pdu_id),
1743 headers_yaml, None, 204, None, 0)
1744
1745
tierno49e42062018-10-24 12:50:53 +02001746class TestDescriptors:
1747 description = "Test VNFD, NSD, PDU descriptors CRUD and dependencies"
1748
1749 def __init__(self):
tierno49e42062018-10-24 12:50:53 +02001750 self.vnfd_filename = "hackfest_3charmed_vnfd.tar.gz"
1751 self.nsd_filename = "hackfest_3charmed_nsd.tar.gz"
1752 self.descriptor_url = "https://osm-download.etsi.org/ftp/osm-3.0-three/2nd-hackfest/packages/"
1753 self.vnfd_id = None
1754 self.nsd_id = None
tiernof717cbe2018-12-03 16:35:42 +00001755 self.vnfd_empty = """vnfd:vnfd-catalog:
1756 vnfd:
1757 - name: prova
1758 short-name: prova
1759 id: prova
1760 """
1761 self.vnfd_prova = """vnfd:vnfd-catalog:
1762 vnfd:
1763 - connection-point:
1764 - name: cp_0h8m
1765 type: VPORT
1766 id: prova
1767 name: prova
1768 short-name: prova
1769 vdu:
1770 - id: vdu_z4bm
1771 image: ubuntu
1772 interface:
1773 - external-connection-point-ref: cp_0h8m
1774 name: eth0
1775 virtual-interface:
1776 type: VIRTIO
1777 name: vdu_z4bm
1778 version: '1.0'
1779 """
tierno49e42062018-10-24 12:50:53 +02001780
1781 def run(self, engine, test_osm, manual_check, test_params=None):
tiernoff6485d2018-11-28 17:19:46 +00001782 engine.set_test_name("Descriptors")
tierno49e42062018-10-24 12:50:53 +02001783 engine.get_autorization()
1784 temp_dir = os.path.dirname(os.path.abspath(__file__)) + "/temp/"
1785 if not os.path.exists(temp_dir):
1786 os.makedirs(temp_dir)
1787
1788 # download files
1789 for filename in (self.vnfd_filename, self.nsd_filename):
1790 filename_path = temp_dir + filename
1791 if not os.path.exists(filename_path):
1792 with open(filename_path, "wb") as file:
1793 response = requests.get(self.descriptor_url + filename)
1794 if response.status_code >= 300:
1795 raise TestException("Error downloading descriptor from '{}': {}".format(
1796 self.descriptor_url + filename, response.status_code))
1797 file.write(response.content)
1798
1799 vnfd_filename_path = temp_dir + self.vnfd_filename
1800 nsd_filename_path = temp_dir + self.nsd_filename
1801
tiernof717cbe2018-12-03 16:35:42 +00001802 engine.test("Onboard empty VNFD in one step", "POST", "/vnfpkgm/v1/vnf_packages_content", headers_yaml,
1803 self.vnfd_empty, 201, r_headers_yaml_location_vnfd, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001804 self.vnfd_id = engine.last_id
tierno49e42062018-10-24 12:50:53 +02001805
tiernof717cbe2018-12-03 16:35:42 +00001806 # test bug 605
1807 engine.test("Upload invalid VNFD ", "PUT", "/vnfpkgm/v1/vnf_packages/{}/package_content".format(self.vnfd_id),
1808 headers_yaml, self.vnfd_prova, 422, r_header_yaml, "yaml")
1809
1810 engine.test("Upload VNFD {}".format(self.vnfd_filename), "PUT",
1811 "/vnfpkgm/v1/vnf_packages/{}/package_content".format(self.vnfd_id), headers_zip_yaml,
1812 "@b" + vnfd_filename_path, 204, None, 0)
1813
gcalvino95f94c22019-01-10 13:03:30 +01001814 queries = ["mgmt-interface.cp=mgmt", "vdu.0.interface.0.external-connection-point-ref=mgmt",
1815 "vdu.0.interface.1.internal-connection-point-ref=internal",
1816 "internal-vld.0.internal-connection-point.0.id-ref=internal"]
1817 for query in queries:
1818 engine.test("Upload invalid VNFD ", "PUT",
1819 "/vnfpkgm/v1/vnf_packages/{}/package_content?{}".format(self.vnfd_id, query),
1820 headers_zip_yaml, "@b" + vnfd_filename_path, 422, r_header_yaml, "yaml")
1821
tiernof717cbe2018-12-03 16:35:42 +00001822 # test bug 605
1823 engine.test("Upload invalid VNFD ", "PUT", "/vnfpkgm/v1/vnf_packages/{}/package_content".format(self.vnfd_id),
1824 headers_yaml, self.vnfd_prova, 422, r_header_yaml, "yaml")
1825
tierno49e42062018-10-24 12:50:53 +02001826 # get vnfd descriptor
tiernof717cbe2018-12-03 16:35:42 +00001827 engine.test("Get VNFD descriptor", "GET", "/vnfpkgm/v1/vnf_packages/{}".format(self.vnfd_id),
1828 headers_yaml, None, 200, r_header_yaml, "yaml")
tierno49e42062018-10-24 12:50:53 +02001829
1830 # get vnfd file descriptor
tiernof717cbe2018-12-03 16:35:42 +00001831 engine.test("Get VNFD file descriptor", "GET", "/vnfpkgm/v1/vnf_packages/{}/vnfd".format(self.vnfd_id),
1832 headers_text, None, 200, r_header_text, "text", temp_dir+"vnfd-yaml")
tierno49e42062018-10-24 12:50:53 +02001833 # TODO compare files: diff vnfd-yaml hackfest_3charmed_vnfd/hackfest_3charmed_vnfd.yaml
1834
1835 # get vnfd zip file package
tiernoff6485d2018-11-28 17:19:46 +00001836 engine.test("Get VNFD zip package", "GET",
tierno49e42062018-10-24 12:50:53 +02001837 "/vnfpkgm/v1/vnf_packages/{}/package_content".format(self.vnfd_id), headers_zip, None, 200,
1838 r_header_zip, "zip", temp_dir+"vnfd-zip")
tierno49e42062018-10-24 12:50:53 +02001839 # TODO compare files: diff vnfd-zip hackfest_3charmed_vnfd.tar.gz
1840
1841 # get vnfd artifact
tiernoff6485d2018-11-28 17:19:46 +00001842 engine.test("Get VNFD artifact package", "GET",
tierno49e42062018-10-24 12:50:53 +02001843 "/vnfpkgm/v1/vnf_packages/{}/artifacts/icons/osm.png".format(self.vnfd_id), headers_zip, None, 200,
1844 r_header_octect, "octet-string", temp_dir+"vnfd-icon")
tierno49e42062018-10-24 12:50:53 +02001845 # TODO compare files: diff vnfd-icon hackfest_3charmed_vnfd/icons/osm.png
1846
1847 # nsd CREATE AND UPLOAD in one step:
tiernof717cbe2018-12-03 16:35:42 +00001848 engine.test("Onboard NSD in one step", "POST", "/nsd/v1/ns_descriptors_content", headers_zip_yaml,
1849 "@b" + nsd_filename_path, 201, r_headers_yaml_location_nsd, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001850 self.nsd_id = engine.last_id
tierno49e42062018-10-24 12:50:53 +02001851
gcalvino95f94c22019-01-10 13:03:30 +01001852 queries = ["vld.0.vnfd-connection-point-ref.0.vnfd-id-ref=hf"]
1853 for query in queries:
1854 engine.test("Upload invalid NSD ", "PUT",
1855 "/nsd/v1/ns_descriptors/{}/nsd_content?{}".format(self.nsd_id, query),
1856 headers_zip_yaml, "@b" + nsd_filename_path, 422, r_header_yaml, "yaml")
1857
tierno49e42062018-10-24 12:50:53 +02001858 # get nsd descriptor
tiernof717cbe2018-12-03 16:35:42 +00001859 engine.test("Get NSD descriptor", "GET", "/nsd/v1/ns_descriptors/{}".format(self.nsd_id), headers_yaml,
1860 None, 200, r_header_yaml, "yaml")
tierno49e42062018-10-24 12:50:53 +02001861
1862 # get nsd file descriptor
tiernof717cbe2018-12-03 16:35:42 +00001863 engine.test("Get NSD file descriptor", "GET", "/nsd/v1/ns_descriptors/{}/nsd".format(self.nsd_id), headers_text,
1864 None, 200, r_header_text, "text", temp_dir+"nsd-yaml")
tierno49e42062018-10-24 12:50:53 +02001865 # TODO compare files: diff nsd-yaml hackfest_3charmed_nsd/hackfest_3charmed_nsd.yaml
1866
1867 # get nsd zip file package
tiernof717cbe2018-12-03 16:35:42 +00001868 engine.test("Get NSD zip package", "GET", "/nsd/v1/ns_descriptors/{}/nsd_content".format(self.nsd_id),
1869 headers_zip, None, 200, r_header_zip, "zip", temp_dir+"nsd-zip")
tierno49e42062018-10-24 12:50:53 +02001870 # TODO compare files: diff nsd-zip hackfest_3charmed_nsd.tar.gz
1871
1872 # get nsd artifact
tiernoff6485d2018-11-28 17:19:46 +00001873 engine.test("Get NSD artifact package", "GET",
tierno49e42062018-10-24 12:50:53 +02001874 "/nsd/v1/ns_descriptors/{}/artifacts/icons/osm.png".format(self.nsd_id), headers_zip, None, 200,
1875 r_header_octect, "octet-string", temp_dir+"nsd-icon")
tierno49e42062018-10-24 12:50:53 +02001876 # TODO compare files: diff nsd-icon hackfest_3charmed_nsd/icons/osm.png
1877
1878 # vnfd DELETE
tiernof717cbe2018-12-03 16:35:42 +00001879 test_rest.test("Delete VNFD conflict", "DELETE", "/vnfpkgm/v1/vnf_packages/{}".format(self.vnfd_id),
1880 headers_yaml, None, 409, None, None)
tierno49e42062018-10-24 12:50:53 +02001881
tiernof717cbe2018-12-03 16:35:42 +00001882 test_rest.test("Delete VNFD force", "DELETE", "/vnfpkgm/v1/vnf_packages/{}?FORCE=TRUE".format(self.vnfd_id),
1883 headers_yaml, None, 204, None, 0)
tierno49e42062018-10-24 12:50:53 +02001884
1885 # nsd DELETE
tiernof717cbe2018-12-03 16:35:42 +00001886 test_rest.test("Delete NSD", "DELETE", "/nsd/v1/ns_descriptors/{}".format(self.nsd_id), headers_yaml, None, 204,
1887 None, 0)
tierno49e42062018-10-24 12:50:53 +02001888
1889
Felipe Vicense36ab852018-11-23 14:12:09 +01001890class TestNetSliceTemplates:
Felipe Vicensb57758d2018-10-16 16:00:20 +02001891 description = "Upload a NST to OSM"
1892
1893 def __init__(self):
Felipe Vicensc8bbaaa2018-12-01 04:42:40 +01001894 self.nst_filenames = ("@./cirros_slice/cirros_slice_vld.yaml")
Felipe Vicensb57758d2018-10-16 16:00:20 +02001895
1896 def run(self, engine, test_osm, manual_check, test_params=None):
1897 # nst CREATE
tiernoff6485d2018-11-28 17:19:46 +00001898 engine.set_test_name("NST")
Felipe Vicensb57758d2018-10-16 16:00:20 +02001899 engine.get_autorization()
tiernoff6485d2018-11-28 17:19:46 +00001900 engine.test("Onboard NST", "POST", "/nst/v1/netslice_templates_content", headers_yaml, self.nst_filenames,
tiernof717cbe2018-12-03 16:35:42 +00001901 201, r_headers_yaml_location_nst, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001902 nst_id = engine.last_id
Felipe Vicensb57758d2018-10-16 16:00:20 +02001903
1904 # nstd SHOW OSM format
tiernoff6485d2018-11-28 17:19:46 +00001905 engine.test("Show NSTD OSM format", "GET", "/nst/v1/netslice_templates/{}".format(nst_id), headers_json, None,
1906 200, r_header_json, "json")
Felipe Vicensb57758d2018-10-16 16:00:20 +02001907
1908 # nstd DELETE
tiernoff6485d2018-11-28 17:19:46 +00001909 engine.test("Delete NSTD", "DELETE", "/nst/v1/netslice_templates/{}".format(nst_id), headers_json, None,
1910 204, None, 0)
Felipe Vicensb57758d2018-10-16 16:00:20 +02001911
1912
Felipe Vicense36ab852018-11-23 14:12:09 +01001913class TestNetSliceInstances:
1914 description = "Upload a NST to OSM"
1915
1916 def __init__(self):
tiernoff6485d2018-11-28 17:19:46 +00001917 self.vim_id = None
Felipe Vicense36ab852018-11-23 14:12:09 +01001918 self.nst_filenames = ("@./cirros_slice/cirros_slice.yaml")
1919
1920 def run(self, engine, test_osm, manual_check, test_params=None):
1921 # nst CREATE
tiernoff6485d2018-11-28 17:19:46 +00001922 engine.set_test_name("NSI")
Felipe Vicense36ab852018-11-23 14:12:09 +01001923 engine.get_autorization()
tiernoff6485d2018-11-28 17:19:46 +00001924 engine.test("Onboard NST", "POST", "/nst/v1/netslice_templates_content", headers_yaml, self.nst_filenames, 201,
tiernof717cbe2018-12-03 16:35:42 +00001925 r_headers_yaml_location_nst, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001926 nst_id = engine.last_id
Felipe Vicense36ab852018-11-23 14:12:09 +01001927
1928 # nsi CREATE
tiernoff6485d2018-11-28 17:19:46 +00001929 self.vim_id = engine.get_create_vim(test_osm)
1930
tierno9e5eea32018-11-29 09:42:09 +00001931 ns_data = {"nsiDescription": "default description", "nsiName": "my_slice", "nstId": nst_id,
Felipe Vicense36ab852018-11-23 14:12:09 +01001932 "vimAccountId": self.vim_id}
1933 ns_data_text = yaml.safe_dump(ns_data, default_flow_style=True, width=256)
1934
tiernoff6485d2018-11-28 17:19:46 +00001935 engine.test("Onboard NSI", "POST", "/nsilcm/v1/netslice_instances_content", headers_yaml, ns_data_text, 201,
tiernof717cbe2018-12-03 16:35:42 +00001936 r_headers_yaml_location_nst, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001937 nsi_id = engine.last_id
Felipe Vicense36ab852018-11-23 14:12:09 +01001938
1939 # TODO: Improve the wait with a polling if NSI was deployed
1940 wait = 120
1941 sleep(wait)
1942
1943 # Check deployment
tiernoff6485d2018-11-28 17:19:46 +00001944 engine.test("Wait until NSI is deployed", "GET", "/nsilcm/v1/netslice_instances_content/{}".format(nsi_id),
1945 headers_json, None, 200, r_header_json, "json")
Felipe Vicense36ab852018-11-23 14:12:09 +01001946
1947 # nsi DELETE
tiernoff6485d2018-11-28 17:19:46 +00001948 engine.test("Delete NSI", "DELETE", "/nsilcm/v1/netslice_instances_content/{}".format(nsi_id), headers_json,
1949 None, 202, r_header_json, "json")
Felipe Vicense36ab852018-11-23 14:12:09 +01001950
1951 sleep(60)
1952
1953 # nstd DELETE
tiernoff6485d2018-11-28 17:19:46 +00001954 engine.test("Delete NSTD", "DELETE", "/nst/v1/netslice_templates/{}".format(nst_id), headers_json, None,
1955 204, None, 0)
Felipe Vicense36ab852018-11-23 14:12:09 +01001956
1957
tiernof27c79b2018-03-12 17:08:42 +01001958if __name__ == "__main__":
1959 global logger
1960 test = ""
tierno0f98af52018-03-19 10:28:22 +01001961
1962 # Disable warnings from self-signed certificates.
1963 requests.packages.urllib3.disable_warnings()
tiernof27c79b2018-03-12 17:08:42 +01001964 try:
1965 logging.basicConfig(format="%(levelname)s %(message)s", level=logging.ERROR)
1966 logger = logging.getLogger('NBI')
1967 # load parameters and configuration
1968 opts, args = getopt.getopt(sys.argv[1:], "hvu:p:",
tiernoc32ba4a2018-05-24 18:06:41 +02001969 ["url=", "user=", "password=", "help", "version", "verbose", "no-verbose",
1970 "project=", "insecure", "timeout", "timeout-deploy", "timeout-configure",
tiernoff6485d2018-11-28 17:19:46 +00001971 "test=", "list", "test-osm", "manual-check", "params=", 'fail-fast'])
tiernof27c79b2018-03-12 17:08:42 +01001972 url = "https://localhost:9999/osm"
1973 user = password = project = "admin"
tiernoc32ba4a2018-05-24 18:06:41 +02001974 test_osm = False
1975 manual_check = False
tiernof27c79b2018-03-12 17:08:42 +01001976 verbose = 0
1977 verify = True
tiernoff6485d2018-11-28 17:19:46 +00001978 fail_fast = False
tiernoc32ba4a2018-05-24 18:06:41 +02001979 test_classes = {
1980 "NonAuthorized": TestNonAuthorized,
1981 "FakeVIM": TestFakeVim,
tiernocd54a4a2018-09-12 16:40:35 +02001982 "TestUsersProjects": TestUsersProjects,
tiernoc32ba4a2018-05-24 18:06:41 +02001983 "VIM-SDN": TestVIMSDN,
1984 "Deploy-Custom": TestDeploy,
1985 "Deploy-Hackfest-Cirros": TestDeployHackfestCirros,
tiernocc103432018-10-19 14:10:35 +02001986 "Deploy-Hackfest-Cirros-Scaling": TestDeployHackfestCirrosScaling,
tiernoc32ba4a2018-05-24 18:06:41 +02001987 "Deploy-Hackfest-3Charmed": TestDeployHackfest3Charmed,
tiernobee085c2018-12-12 17:03:04 +00001988 "Deploy-Hackfest-3Charmed2": TestDeployHackfest3Charmed2,
1989 "Deploy-Hackfest-3Charmed3": TestDeployHackfest3Charmed3,
tiernoc32ba4a2018-05-24 18:06:41 +02001990 "Deploy-Hackfest-4": TestDeployHackfest4,
1991 "Deploy-CirrosMacIp": TestDeployIpMac,
tierno49e42062018-10-24 12:50:53 +02001992 "TestDescriptors": TestDescriptors,
tiernocc103432018-10-19 14:10:35 +02001993 "TestDeployHackfest1": TestDeployHackfest1,
gcalvino337ec512018-07-30 10:30:13 +02001994 # "Deploy-MultiVIM": TestDeployMultiVIM,
tierno36ec8602018-11-02 17:27:11 +01001995 "DeploySingleVdu": TestDeploySingleVdu,
1996 "DeployHnfd": TestDeployHnfd,
tiernoff6485d2018-11-28 17:19:46 +00001997 # "Upload-Slice-Template": TestNetSliceTemplates,
1998 # "Deploy-Slice-Instance": TestNetSliceInstances,
1999 "TestDeploySimpleCharm": TestDeploySimpleCharm,
2000 "TestDeploySimpleCharm2": TestDeploySimpleCharm2,
tiernoc32ba4a2018-05-24 18:06:41 +02002001 }
2002 test_to_do = []
2003 test_params = {}
tiernof27c79b2018-03-12 17:08:42 +01002004
2005 for o, a in opts:
tiernoc32ba4a2018-05-24 18:06:41 +02002006 # print("parameter:", o, a)
tiernof27c79b2018-03-12 17:08:42 +01002007 if o == "--version":
tierno2236d202018-05-16 19:05:16 +02002008 print("test version " + __version__ + ' ' + version_date)
tiernoc32ba4a2018-05-24 18:06:41 +02002009 exit()
2010 elif o == "--list":
tiernobee085c2018-12-12 17:03:04 +00002011 for test, test_class in sorted(test_classes.items()):
2012 print("{:32} {}".format(test + ":", test_class.description))
tiernoc32ba4a2018-05-24 18:06:41 +02002013 exit()
tiernof27c79b2018-03-12 17:08:42 +01002014 elif o in ("-v", "--verbose"):
2015 verbose += 1
tierno2236d202018-05-16 19:05:16 +02002016 elif o == "no-verbose":
tiernof27c79b2018-03-12 17:08:42 +01002017 verbose = -1
2018 elif o in ("-h", "--help"):
2019 usage()
2020 sys.exit()
tiernoc32ba4a2018-05-24 18:06:41 +02002021 elif o == "--test-osm":
2022 test_osm = True
2023 elif o == "--manual-check":
2024 manual_check = True
tierno2236d202018-05-16 19:05:16 +02002025 elif o == "--url":
tiernof27c79b2018-03-12 17:08:42 +01002026 url = a
2027 elif o in ("-u", "--user"):
2028 user = a
2029 elif o in ("-p", "--password"):
2030 password = a
tierno2236d202018-05-16 19:05:16 +02002031 elif o == "--project":
tiernof27c79b2018-03-12 17:08:42 +01002032 project = a
tiernoff6485d2018-11-28 17:19:46 +00002033 elif o == "--fail-fast":
2034 fail_fast = True
tiernoc32ba4a2018-05-24 18:06:41 +02002035 elif o == "--test":
2036 # print("asdfadf", o, a, a.split(","))
2037 for _test in a.split(","):
2038 if _test not in test_classes:
2039 print("Invalid test name '{}'. Use option '--list' to show available tests".format(_test),
2040 file=sys.stderr)
2041 exit(1)
2042 test_to_do.append(_test)
2043 elif o == "--params":
2044 param_key, _, param_value = a.partition("=")
2045 text_index = len(test_to_do)
2046 if text_index not in test_params:
2047 test_params[text_index] = {}
2048 test_params[text_index][param_key] = param_value
tierno2236d202018-05-16 19:05:16 +02002049 elif o == "--insecure":
tiernof27c79b2018-03-12 17:08:42 +01002050 verify = False
tiernoc32ba4a2018-05-24 18:06:41 +02002051 elif o == "--timeout":
2052 timeout = int(a)
2053 elif o == "--timeout-deploy":
2054 timeout_deploy = int(a)
2055 elif o == "--timeout-configure":
2056 timeout_configure = int(a)
tiernof27c79b2018-03-12 17:08:42 +01002057 else:
2058 assert False, "Unhandled option"
2059 if verbose == 0:
2060 logger.setLevel(logging.WARNING)
2061 elif verbose > 1:
2062 logger.setLevel(logging.DEBUG)
2063 else:
2064 logger.setLevel(logging.ERROR)
2065
tiernoc32ba4a2018-05-24 18:06:41 +02002066 test_rest = TestRest(url, user=user, password=password, project=project)
2067 # print("tests to do:", test_to_do)
2068 if test_to_do:
2069 text_index = 0
2070 for test in test_to_do:
tiernoff6485d2018-11-28 17:19:46 +00002071 if fail_fast and test_rest.failed_tests:
2072 break
tiernoc32ba4a2018-05-24 18:06:41 +02002073 text_index += 1
2074 test_class = test_classes[test]
2075 test_class().run(test_rest, test_osm, manual_check, test_params.get(text_index))
2076 else:
2077 for test, test_class in test_classes.items():
tiernoff6485d2018-11-28 17:19:46 +00002078 if fail_fast and test_rest.failed_tests:
2079 break
tiernoc32ba4a2018-05-24 18:06:41 +02002080 test_class().run(test_rest, test_osm, manual_check, test_params.get(0))
tiernoff6485d2018-11-28 17:19:46 +00002081 test_rest.print_results()
2082 exit(1 if test_rest.failed_tests else 0)
tiernof27c79b2018-03-12 17:08:42 +01002083
tiernoc32ba4a2018-05-24 18:06:41 +02002084 except TestException as e:
2085 logger.error(test + "Test {} Exception: {}".format(test, str(e)))
2086 exit(1)
2087 except getopt.GetoptError as e:
2088 logger.error(e)
2089 print(e, file=sys.stderr)
2090 exit(1)
tiernof27c79b2018-03-12 17:08:42 +01002091 except Exception as e:
tiernoc32ba4a2018-05-24 18:06:41 +02002092 logger.critical(test + " Exception: " + str(e), exc_info=True)