blob: 6f30cfeae719ac92197d4edec452f6f9c1a7bdb5 [file] [log] [blame]
tiernof27c79b2018-03-12 17:08:42 +01001#! /usr/bin/python3
2# -*- coding: utf-8 -*-
3
tiernod125caf2018-11-22 16:05:54 +00004# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13# implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
tiernof27c79b2018-03-12 17:08:42 +010017import getopt
18import sys
19import requests
tiernof27c79b2018-03-12 17:08:42 +010020import json
21import logging
22import yaml
tierno2236d202018-05-16 19:05:16 +020023# import json
tiernoc32ba4a2018-05-24 18:06:41 +020024# import tarfile
25from time import sleep
tiernoff6485d2018-11-28 17:19:46 +000026from random import randint
tiernoc32ba4a2018-05-24 18:06:41 +020027import os
tiernoff6485d2018-11-28 17:19:46 +000028from sys import stderr
tiernof27c79b2018-03-12 17:08:42 +010029
30__author__ = "Alfonso Tierno, alfonso.tiernosepulveda@telefonica.com"
31__date__ = "$2018-03-01$"
gcalvino337ec512018-07-30 10:30:13 +020032__version__ = "0.3"
33version_date = "Oct 2018"
tiernof27c79b2018-03-12 17:08:42 +010034
35
36def usage():
37 print("Usage: ", sys.argv[0], "[options]")
tiernoc32ba4a2018-05-24 18:06:41 +020038 print(" Performs system tests over running NBI. It can be used for real OSM test using option '--test-osm'")
tiernoff6485d2018-11-28 17:19:46 +000039 print(" If this is the case env variables 'OSMNBITEST_VIM_NAME' must be supplied to create a VIM if not exist "
tiernoc32ba4a2018-05-24 18:06:41 +020040 "where deployment is done")
41 print("OPTIONS")
tiernof27c79b2018-03-12 17:08:42 +010042 print(" -h|--help: shows this help")
tiernoc32ba4a2018-05-24 18:06:41 +020043 print(" --insecure: Allows non trusted https NBI server")
44 print(" --list: list available tests")
45 print(" --manual-check: Deployment tests stop after deployed to allow manual inspection. Only make sense with "
46 "'--test-osm'")
47 print(" -p|--password PASSWORD: NBI access password. 'admin' by default")
48 print(" ---project PROJECT: NBI access project. 'admin' by default")
49 print(" --test TEST[,...]: Execute only a test or a comma separated list of tests")
50 print(" --params key=val: params to the previous test. key can be vnfd-files, nsd-file, ns-name, ns-config")
51 print(" --test-osm: If missing this test is intended for NBI only, no other OSM components are expected. Use "
52 "this flag to test the system. LCM and RO components are expected to be up and running")
53 print(" --timeout TIMEOUT: General NBI timeout, by default {}s".format(timeout))
54 print(" --timeout-deploy TIMEOUT: Timeout used for getting NS deployed, by default {}s".format(timeout_deploy))
55 print(" --timeout-configure TIMEOUT: Timeout used for getting NS deployed and configured,"
56 " by default {}s".format(timeout_configure))
57 print(" -u|--user USERNAME: NBI access username. 'admin' by default")
58 print(" --url URL: complete NBI server URL. 'https//localhost:9999/osm' by default")
tiernof27c79b2018-03-12 17:08:42 +010059 print(" -v|--verbose print debug information, can be used several times")
tiernoc32ba4a2018-05-24 18:06:41 +020060 print(" --no-verbose remove verbosity")
61 print(" --version: prints current version")
62 print("ENV variables used for real deployment tests with option osm-test.")
63 print(" export OSMNBITEST_VIM_NAME=vim-name")
64 print(" export OSMNBITEST_VIM_URL=vim-url")
65 print(" export OSMNBITEST_VIM_TYPE=vim-type")
66 print(" export OSMNBITEST_VIM_TENANT=vim-tenant")
67 print(" export OSMNBITEST_VIM_USER=vim-user")
68 print(" export OSMNBITEST_VIM_PASSWORD=vim-password")
69 print(" export OSMNBITEST_VIM_CONFIG=\"vim-config\"")
70 print(" export OSMNBITEST_NS_NAME=\"vim-config\"")
tiernof27c79b2018-03-12 17:08:42 +010071 return
72
73
74r_header_json = {"Content-type": "application/json"}
tiernof717cbe2018-12-03 16:35:42 +000075headers_json = {"Content-type": "application/json", "Accept": "application/json"}
tiernof27c79b2018-03-12 17:08:42 +010076r_header_yaml = {"Content-type": "application/yaml"}
tiernof717cbe2018-12-03 16:35:42 +000077headers_yaml = {"Content-type": "application/yaml", "Accept": "application/yaml"}
tiernof27c79b2018-03-12 17:08:42 +010078r_header_text = {"Content-type": "text/plain"}
79r_header_octect = {"Content-type": "application/octet-stream"}
tiernof717cbe2018-12-03 16:35:42 +000080headers_text = {"Accept": "text/plain,application/yaml"}
tiernof27c79b2018-03-12 17:08:42 +010081r_header_zip = {"Content-type": "application/zip"}
tiernof717cbe2018-12-03 16:35:42 +000082headers_zip = {"Accept": "application/zip,application/yaml"}
83headers_zip_yaml = {"Accept": "application/yaml", "Content-type": "application/zip"}
84r_headers_yaml_location_vnfd = {"Location": "/vnfpkgm/v1/vnf_packages_content/", "Content-Type": "application/yaml"}
85r_headers_yaml_location_nsd = {"Location": "/nsd/v1/ns_descriptors_content/", "Content-Type": "application/yaml"}
86r_headers_yaml_location_nst = {"Location": "/nst/v1/netslice_templates_content", "Content-Type": "application/yaml"}
87r_headers_yaml_location_nslcmop = {"Location": "nslcm/v1/ns_lcm_op_occs/", "Content-Type": "application/yaml"}
Felipe Vicens09e65422019-01-22 15:06:46 +010088r_headers_yaml_location_nsilcmop = {"Location": "/osm/nsilcm/v1/nsi_lcm_op_occs/", "Content-Type": "application/yaml"}
tiernof27c79b2018-03-12 17:08:42 +010089
90# test ones authorized
91test_authorized_list = (
tierno2236d202018-05-16 19:05:16 +020092 ("AU1", "Invalid vnfd id", "GET", "/vnfpkgm/v1/vnf_packages/non-existing-id",
93 headers_json, None, 404, r_header_json, "json"),
94 ("AU2", "Invalid nsd id", "GET", "/nsd/v1/ns_descriptors/non-existing-id",
95 headers_yaml, None, 404, r_header_yaml, "yaml"),
96 ("AU3", "Invalid nsd id", "DELETE", "/nsd/v1/ns_descriptors_content/non-existing-id",
97 headers_yaml, None, 404, r_header_yaml, "yaml"),
tierno0f98af52018-03-19 10:28:22 +010098)
tiernoc32ba4a2018-05-24 18:06:41 +020099timeout = 120 # general timeout
100timeout_deploy = 60*10 # timeout for NS deploying without charms
101timeout_configure = 60*20 # timeout for NS deploying and configuring
tiernof27c79b2018-03-12 17:08:42 +0100102
tierno2236d202018-05-16 19:05:16 +0200103
tiernof27c79b2018-03-12 17:08:42 +0100104class TestException(Exception):
105 pass
106
107
108class TestRest:
tiernoc32ba4a2018-05-24 18:06:41 +0200109 def __init__(self, url_base, header_base=None, verify=False, user="admin", password="admin", project="admin"):
tiernof27c79b2018-03-12 17:08:42 +0100110 self.url_base = url_base
tiernoc32ba4a2018-05-24 18:06:41 +0200111 if header_base is None:
112 self.header_base = {}
113 else:
114 self.header_base = header_base.copy()
tiernof27c79b2018-03-12 17:08:42 +0100115 self.s = requests.session()
tiernoc32ba4a2018-05-24 18:06:41 +0200116 self.s.headers = self.header_base
tiernof27c79b2018-03-12 17:08:42 +0100117 self.verify = verify
tiernoc32ba4a2018-05-24 18:06:41 +0200118 self.token = False
119 self.user = user
120 self.password = password
121 self.project = project
122 self.vim_id = None
tierno0f98af52018-03-19 10:28:22 +0100123 # contains ID of tests obtained from Location response header. "" key contains last obtained id
tiernoff6485d2018-11-28 17:19:46 +0000124 self.last_id = ""
tierno36ec8602018-11-02 17:27:11 +0100125 self.test_name = None
tiernoff6485d2018-11-28 17:19:46 +0000126 self.step = 0 # number of subtest under test
127 self.passed_tests = 0
128 self.failed_tests = 0
tiernof27c79b2018-03-12 17:08:42 +0100129
tiernoff6485d2018-11-28 17:19:46 +0000130 def set_test_name(self, test_name):
131 self.test_name = test_name
132 self.step = 0
133 self.last_id = ""
delacruzramoc061f562019-04-05 11:00:02 +0200134
tiernof27c79b2018-03-12 17:08:42 +0100135 def set_header(self, header):
136 self.s.headers.update(header)
137
tierno36ec8602018-11-02 17:27:11 +0100138 def set_tet_name(self, test_name):
139 self.test_name = test_name
140
tiernocd54a4a2018-09-12 16:40:35 +0200141 def unset_header(self, key):
142 if key in self.s.headers:
143 del self.s.headers[key]
144
tiernoff6485d2018-11-28 17:19:46 +0000145 def test(self, description, method, url, headers, payload, expected_codes, expected_headers,
146 expected_payload, store_file=None, pooling=False):
tiernof27c79b2018-03-12 17:08:42 +0100147 """
tierno0f98af52018-03-19 10:28:22 +0100148 Performs an http request and check http code response. Exit if different than allowed. It get the returned id
149 that can be used by following test in the URL with {name} where name is the name of the test
tierno0f98af52018-03-19 10:28:22 +0100150 :param description: description of the test
tiernof27c79b2018-03-12 17:08:42 +0100151 :param method: HTTP method: GET,PUT,POST,DELETE,...
152 :param url: complete URL or relative URL
153 :param headers: request headers to add to the base headers
154 :param payload: Can be a dict, transformed to json, a text or a file if starts with '@'
155 :param expected_codes: expected response codes, can be int, int tuple or int range
156 :param expected_headers: expected response headers, dict with key values
tierno49e42062018-10-24 12:50:53 +0200157 :param expected_payload: expected payload, 0 if empty, 'yaml', 'json', 'text', 'zip', 'octet-stream'
158 :param store_file: filename to store content
tiernoff6485d2018-11-28 17:19:46 +0000159 :param pooling: if True do not count neither log this test. Because a pooling is done with many equal requests
tierno0f98af52018-03-19 10:28:22 +0100160 :return: requests response
tiernof27c79b2018-03-12 17:08:42 +0100161 """
tiernoc32ba4a2018-05-24 18:06:41 +0200162 r = None
tiernof27c79b2018-03-12 17:08:42 +0100163 try:
164 if not self.s:
165 self.s = requests.session()
tierno0f98af52018-03-19 10:28:22 +0100166 # URL
tiernof27c79b2018-03-12 17:08:42 +0100167 if not url:
168 url = self.url_base
169 elif not url.startswith("http"):
170 url = self.url_base + url
tierno0f98af52018-03-19 10:28:22 +0100171
tiernoff6485d2018-11-28 17:19:46 +0000172 # replace url <> with the last ID
173 url = url.replace("<>", self.last_id)
tiernof27c79b2018-03-12 17:08:42 +0100174 if payload:
175 if isinstance(payload, str):
176 if payload.startswith("@"):
177 mode = "r"
178 file_name = payload[1:]
179 if payload.startswith("@b"):
180 mode = "rb"
181 file_name = payload[2:]
182 with open(file_name, mode) as f:
183 payload = f.read()
184 elif isinstance(payload, dict):
185 payload = json.dumps(payload)
tierno2236d202018-05-16 19:05:16 +0200186
tiernoff6485d2018-11-28 17:19:46 +0000187 if not pooling:
188 test_description = "Test {}{} {} {} {}".format(self.test_name, self.step, description, method, url)
tiernoc32ba4a2018-05-24 18:06:41 +0200189 logger.warning(test_description)
tiernoff6485d2018-11-28 17:19:46 +0000190 self.step += 1
tiernof27c79b2018-03-12 17:08:42 +0100191 stream = False
tierno49e42062018-10-24 12:50:53 +0200192 if expected_payload in ("zip", "octet-string") or store_file:
193 stream = True
tiernobee085c2018-12-12 17:03:04 +0000194 __retry = 0
195 while True:
196 try:
197 r = getattr(self.s, method.lower())(url, data=payload, headers=headers, verify=self.verify,
198 stream=stream)
199 break
200 except requests.exceptions.ConnectionError as e:
201 if __retry == 2:
202 raise
203 logger.error("Exception {}. Retrying".format(e))
204 __retry += 1
205
tierno49e42062018-10-24 12:50:53 +0200206 if expected_payload in ("zip", "octet-string") or store_file:
207 logger.debug("RX {}".format(r.status_code))
208 else:
209 logger.debug("RX {}: {}".format(r.status_code, r.text))
tiernof27c79b2018-03-12 17:08:42 +0100210
211 # check response
212 if expected_codes:
213 if isinstance(expected_codes, int):
214 expected_codes = (expected_codes,)
215 if r.status_code not in expected_codes:
216 raise TestException(
217 "Got status {}. Expected {}. {}".format(r.status_code, expected_codes, r.text))
218
219 if expected_headers:
220 for header_key, header_val in expected_headers.items():
221 if header_key.lower() not in r.headers:
222 raise TestException("Header {} not present".format(header_key))
223 if header_val and header_val.lower() not in r.headers[header_key]:
224 raise TestException("Header {} does not contain {} but {}".format(header_key, header_val,
225 r.headers[header_key]))
226
227 if expected_payload is not None:
228 if expected_payload == 0 and len(r.content) > 0:
229 raise TestException("Expected empty payload")
230 elif expected_payload == "json":
231 try:
232 r.json()
233 except Exception as e:
234 raise TestException("Expected json response payload, but got Exception {}".format(e))
235 elif expected_payload == "yaml":
236 try:
237 yaml.safe_load(r.text)
238 except Exception as e:
239 raise TestException("Expected yaml response payload, but got Exception {}".format(e))
tierno49e42062018-10-24 12:50:53 +0200240 elif expected_payload in ("zip", "octet-string"):
tiernof27c79b2018-03-12 17:08:42 +0100241 if len(r.content) == 0:
242 raise TestException("Expected some response payload, but got empty")
243 # try:
244 # tar = tarfile.open(None, 'r:gz', fileobj=r.raw)
245 # for tarinfo in tar:
246 # tarname = tarinfo.name
247 # print(tarname)
248 # except Exception as e:
249 # raise TestException("Expected zip response payload, but got Exception {}".format(e))
250 elif expected_payload == "text":
251 if len(r.content) == 0:
252 raise TestException("Expected some response payload, but got empty")
tierno2236d202018-05-16 19:05:16 +0200253 # r.text
tierno49e42062018-10-24 12:50:53 +0200254 if store_file:
255 with open(store_file, 'wb') as fd:
256 for chunk in r.iter_content(chunk_size=128):
257 fd.write(chunk)
258
tierno0f98af52018-03-19 10:28:22 +0100259 location = r.headers.get("Location")
260 if location:
261 _id = location[location.rfind("/") + 1:]
262 if _id:
tiernoff6485d2018-11-28 17:19:46 +0000263 self.last_id = str(_id)
264 if not pooling:
265 self.passed_tests += 1
tiernof27c79b2018-03-12 17:08:42 +0100266 return r
267 except TestException as e:
tiernoff6485d2018-11-28 17:19:46 +0000268 self.failed_tests += 1
tiernoc32ba4a2018-05-24 18:06:41 +0200269 r_status_code = None
270 r_text = None
271 if r:
272 r_status_code = r.status_code
273 r_text = r.text
274 logger.error("{} \nRX code{}: {}".format(e, r_status_code, r_text))
tiernoff6485d2018-11-28 17:19:46 +0000275 return None
276 # exit(1)
tiernof27c79b2018-03-12 17:08:42 +0100277 except IOError as e:
tiernoff6485d2018-11-28 17:19:46 +0000278 if store_file:
279 logger.error("Cannot open file {}: {}".format(store_file, e))
280 else:
281 logger.error("Exception: {}".format(e), exc_info=True)
282 self.failed_tests += 1
283 return None
284 # exit(1)
tiernobee085c2018-12-12 17:03:04 +0000285 except requests.exceptions.RequestException as e:
286 logger.error("Exception: {}".format(e))
tiernof27c79b2018-03-12 17:08:42 +0100287
tiernoc32ba4a2018-05-24 18:06:41 +0200288 def get_autorization(self): # user=None, password=None, project=None):
289 if self.token: # and self.user == user and self.password == password and self.project == project:
290 return
291 # self.user = user
292 # self.password = password
293 # self.project = project
tiernoff6485d2018-11-28 17:19:46 +0000294 r = self.test("Obtain token", "POST", "/admin/v1/tokens", headers_json,
tiernoc32ba4a2018-05-24 18:06:41 +0200295 {"username": self.user, "password": self.password, "project_id": self.project},
tiernocd54a4a2018-09-12 16:40:35 +0200296 (200, 201), r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000297 if not r:
298 return
tiernoc32ba4a2018-05-24 18:06:41 +0200299 response = r.json()
300 self.token = response["id"]
301 self.set_header({"Authorization": "Bearer {}".format(self.token)})
302
tiernocd54a4a2018-09-12 16:40:35 +0200303 def remove_authorization(self):
304 if self.token:
tiernoff6485d2018-11-28 17:19:46 +0000305 self.test("Delete token", "DELETE", "/admin/v1/tokens/{}".format(self.token), headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200306 None, (200, 201, 204), None, None)
307 self.token = None
308 self.unset_header("Authorization")
309
tiernoc32ba4a2018-05-24 18:06:41 +0200310 def get_create_vim(self, test_osm):
311 if self.vim_id:
312 return self.vim_id
313 self.get_autorization()
314 if test_osm:
315 vim_name = os.environ.get("OSMNBITEST_VIM_NAME")
316 if not vim_name:
317 raise TestException(
318 "Needed to define OSMNBITEST_VIM_XXX variables to create a real VIM for deployment")
319 else:
320 vim_name = "fakeVim"
321 # Get VIM
tiernoff6485d2018-11-28 17:19:46 +0000322 r = self.test("Get VIM ID", "GET", "/admin/v1/vim_accounts?name={}".format(vim_name), headers_json,
tiernoc32ba4a2018-05-24 18:06:41 +0200323 None, 200, r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000324 if not r:
325 return
tiernoc32ba4a2018-05-24 18:06:41 +0200326 vims = r.json()
327 if vims:
328 return vims[0]["_id"]
329 # Add VIM
330 if test_osm:
331 # check needed environ parameters:
332 if not os.environ.get("OSMNBITEST_VIM_URL") or not os.environ.get("OSMNBITEST_VIM_TENANT"):
333 raise TestException("Env OSMNBITEST_VIM_URL and OSMNBITEST_VIM_TENANT are needed for create a real VIM"
334 " to deploy on whit the --test-osm option")
335 vim_data = "{{schema_version: '1.0', name: '{}', vim_type: {}, vim_url: '{}', vim_tenant_name: '{}', "\
336 "vim_user: {}, vim_password: {}".format(vim_name,
337 os.environ.get("OSMNBITEST_VIM_TYPE", "openstack"),
338 os.environ.get("OSMNBITEST_VIM_URL"),
339 os.environ.get("OSMNBITEST_VIM_TENANT"),
340 os.environ.get("OSMNBITEST_VIM_USER"),
341 os.environ.get("OSMNBITEST_VIM_PASSWORD"))
342 if os.environ.get("OSMNBITEST_VIM_CONFIG"):
343 vim_data += " ,config: {}".format(os.environ.get("OSMNBITEST_VIM_CONFIG"))
344 vim_data += "}"
345 else:
346 vim_data = "{schema_version: '1.0', name: fakeVim, vim_type: openstack, vim_url: 'http://10.11.12.13/fake'"\
347 ", vim_tenant_name: 'vimtenant', vim_user: vimuser, vim_password: vimpassword}"
tiernoff6485d2018-11-28 17:19:46 +0000348 self.test("Create VIM", "POST", "/admin/v1/vim_accounts", headers_yaml, vim_data,
349 (201), {"Location": "/admin/v1/vim_accounts/", "Content-Type": "application/yaml"}, "yaml")
350 return self.last_id
351
352 def print_results(self):
353 print("\n\n\n--------------------------------------------")
354 print("TEST RESULTS: Total: {}, Passed: {}, Failed: {}".format(self.passed_tests + self.failed_tests,
355 self.passed_tests, self.failed_tests))
356 print("--------------------------------------------")
357
358 def wait_until_delete(self, url_op, timeout_delete):
359 """
360 Make a pooling until topic is not present, because of deleted
361 :param url_op:
362 :param timeout_delete:
363 :return:
364 """
365 description = "Wait to topic being deleted"
366 test_description = "Test {}{} {} {} {}".format(self.test_name, self.step, description, "GET", url_op)
367 logger.warning(test_description)
368 self.step += 1
369
370 wait = timeout_delete
371 while wait >= 0:
tierno55ba2e62018-12-11 17:22:22 +0000372 r = self.test(description, "GET", url_op, headers_yaml, None, (200, 404), None, r_header_yaml, "yaml",
373 pooling=True)
tiernoff6485d2018-11-28 17:19:46 +0000374 if not r:
375 return
376 if r.status_code == 404:
377 self.passed_tests += 1
378 break
379 elif r.status_code == 200:
380 wait -= 5
381 sleep(5)
382 else:
383 raise TestException("Topic is not deleted after {} seconds".format(timeout_delete))
384 self.failed_tests += 1
385
386 def wait_operation_ready(self, ns_nsi, opp_id, timeout, expected_fail=False):
387 """
388 Wait until nslcmop or nsilcmop finished
389 :param ns_nsi: "ns" o "nsi"
390 :param opp_id: Id o fthe operation
391 :param timeout:
392 :param expected_fail:
393 :return: None. Updates passed/failed_tests
394 """
395 if ns_nsi == "ns":
396 url_op = "/nslcm/v1/ns_lcm_op_occs/{}".format(opp_id)
397 else:
398 url_op = "/nsilcm/v1/nsi_lcm_op_occs/{}".format(opp_id)
399 description = "Wait to {} lcm operation complete".format(ns_nsi)
400 test_description = "Test {}{} {} {} {}".format(self.test_name, self.step, description, "GET", url_op)
401 logger.warning(test_description)
402 self.step += 1
403 wait = timeout
404 while wait >= 0:
405 r = self.test(description, "GET", url_op, headers_json, None,
406 200, r_header_json, "json", pooling=True)
407 if not r:
408 return
409 nslcmop = r.json()
410 if "COMPLETED" in nslcmop["operationState"]:
411 if expected_fail:
tiernobee085c2018-12-12 17:03:04 +0000412 logger.error("NS terminate has success, expecting failing: {}".format(nslcmop["detailed-status"]))
tiernoff6485d2018-11-28 17:19:46 +0000413 self.failed_tests += 1
414 else:
415 self.passed_tests += 1
416 break
417 elif "FAILED" in nslcmop["operationState"]:
418 if not expected_fail:
419 logger.error("NS terminate has failed: {}".format(nslcmop["detailed-status"]))
tiernobee085c2018-12-12 17:03:04 +0000420 self.failed_tests += 1
tiernoff6485d2018-11-28 17:19:46 +0000421 else:
422 self.passed_tests += 1
423 break
424
425 print(".", end="", file=stderr)
426 wait -= 10
427 sleep(10)
428 else:
429 self.failed_tests += 1
430 logger.error("NS instantiate is not terminate after {} seconds".format(timeout))
431 return
432 print("", file=stderr)
tiernoc32ba4a2018-05-24 18:06:41 +0200433
434
435class TestNonAuthorized:
tiernobee085c2018-12-12 17:03:04 +0000436 description = "Test invalid URLs. methods and no authorization"
tiernoc32ba4a2018-05-24 18:06:41 +0200437
438 @staticmethod
tiernocd54a4a2018-09-12 16:40:35 +0200439 def run(engine, test_osm, manual_check, test_params=None):
tiernoff6485d2018-11-28 17:19:46 +0000440 engine.set_test_name("NonAuth")
tiernocd54a4a2018-09-12 16:40:35 +0200441 engine.remove_authorization()
tiernoc32ba4a2018-05-24 18:06:41 +0200442 test_not_authorized_list = (
tiernoff6485d2018-11-28 17:19:46 +0000443 ("Invalid token", "GET", "/admin/v1/users", headers_json, None, 401, r_header_json, "json"),
444 ("Invalid URL", "POST", "/admin/v1/nonexist", headers_yaml, None, 405, r_header_yaml, "yaml"),
445 ("Invalid version", "DELETE", "/admin/v2/users", headers_yaml, None, 405, r_header_yaml, "yaml"),
tiernoc32ba4a2018-05-24 18:06:41 +0200446 )
447 for t in test_not_authorized_list:
448 engine.test(*t)
449
450
tiernocd54a4a2018-09-12 16:40:35 +0200451class TestUsersProjects:
452 description = "test project and user creation"
453
454 @staticmethod
455 def run(engine, test_osm, manual_check, test_params=None):
tiernoff6485d2018-11-28 17:19:46 +0000456 engine.set_test_name("UserProject")
tiernocd54a4a2018-09-12 16:40:35 +0200457 engine.get_autorization()
tiernoff6485d2018-11-28 17:19:46 +0000458 engine.test("Create project non admin", "POST", "/admin/v1/projects", headers_json, {"name": "P1"},
tiernocd54a4a2018-09-12 16:40:35 +0200459 (201, 204), {"Location": "/admin/v1/projects/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000460 engine.test("Create project admin", "POST", "/admin/v1/projects", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200461 {"name": "Padmin", "admin": True}, (201, 204),
462 {"Location": "/admin/v1/projects/", "Content-Type": "application/json"}, "json")
delacruzramoc061f562019-04-05 11:00:02 +0200463 engine.test("Create project bad format", "POST", "/admin/v1/projects", headers_json, {"name": 1}, (400, 422),
tiernocd54a4a2018-09-12 16:40:35 +0200464 r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000465 engine.test("Create user with bad project", "POST", "/admin/v1/users", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200466 {"username": "U1", "projects": ["P1", "P2", "Padmin"], "password": "pw1"}, 409,
467 r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000468 engine.test("Create user with bad project and force", "POST", "/admin/v1/users?FORCE=True", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200469 {"username": "U1", "projects": ["P1", "P2", "Padmin"], "password": "pw1"}, 201,
470 {"Location": "/admin/v1/users/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000471 engine.test("Create user 2", "POST", "/admin/v1/users", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200472 {"username": "U2", "projects": ["P1"], "password": "pw2"}, 201,
473 {"Location": "/admin/v1/users/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000474 engine.test("Edit user U1, delete P2 project", "PATCH", "/admin/v1/users/U1", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200475 {"projects": {"$'P2'": None}}, 204, None, None)
tiernoff6485d2018-11-28 17:19:46 +0000476 res = engine.test("Check user U1, contains the right projects", "GET", "/admin/v1/users/U1",
tiernocd54a4a2018-09-12 16:40:35 +0200477 headers_json, None, 200, None, json)
tiernoff6485d2018-11-28 17:19:46 +0000478 if res:
479 u1 = res.json()
480 # print(u1)
481 expected_projects = ["P1", "Padmin"]
482 if u1["projects"] != expected_projects:
483 logger.error("User content projects '{}' different than expected '{}'. Edition has not done"
484 " properly".format(u1["projects"], expected_projects))
485 engine.failed_tests += 1
tiernocd54a4a2018-09-12 16:40:35 +0200486
tiernoff6485d2018-11-28 17:19:46 +0000487 engine.test("Edit user U1, set Padmin as default project", "PUT", "/admin/v1/users/U1", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200488 {"projects": {"$'Padmin'": None, "$+[0]": "Padmin"}}, 204, None, None)
tiernoff6485d2018-11-28 17:19:46 +0000489 res = engine.test("Check user U1, contains the right projects", "GET", "/admin/v1/users/U1",
tiernocd54a4a2018-09-12 16:40:35 +0200490 headers_json, None, 200, None, json)
tiernoff6485d2018-11-28 17:19:46 +0000491 if res:
492 u1 = res.json()
493 # print(u1)
494 expected_projects = ["Padmin", "P1"]
495 if u1["projects"] != expected_projects:
496 logger.error("User content projects '{}' different than expected '{}'. Edition has not done"
497 " properly".format(u1["projects"], expected_projects))
498 engine.failed_tests += 1
tiernocd54a4a2018-09-12 16:40:35 +0200499
tiernoff6485d2018-11-28 17:19:46 +0000500 engine.test("Edit user U1, change password", "PATCH", "/admin/v1/users/U1", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200501 {"password": "pw1_new"}, 204, None, None)
502
tiernoff6485d2018-11-28 17:19:46 +0000503 engine.test("Change to project P1 non existing", "POST", "/admin/v1/tokens/", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200504 {"project_id": "P1"}, 401, r_header_json, "json")
505
tiernoff6485d2018-11-28 17:19:46 +0000506 res = engine.test("Change to user U1 project P1", "POST", "/admin/v1/tokens", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200507 {"username": "U1", "password": "pw1_new", "project_id": "P1"}, (200, 201),
508 r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000509 if res:
510 response = res.json()
511 engine.set_header({"Authorization": "Bearer {}".format(response["id"])})
tiernocd54a4a2018-09-12 16:40:35 +0200512
tiernoff6485d2018-11-28 17:19:46 +0000513 engine.test("Edit user projects non admin", "PUT", "/admin/v1/users/U1", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200514 {"projects": {"$'P1'": None}}, 401, r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000515 engine.test("Add new project non admin", "POST", "/admin/v1/projects", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200516 {"name": "P2"}, 401, r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000517 engine.test("Add new user non admin", "POST", "/admin/v1/users", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200518 {"username": "U3", "projects": ["P1"], "password": "pw3"}, 401,
519 r_header_json, "json")
520
tiernoff6485d2018-11-28 17:19:46 +0000521 res = engine.test("Change to user U1 project Padmin", "POST", "/admin/v1/tokens", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200522 {"project_id": "Padmin"}, (200, 201), r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000523 if res:
524 response = res.json()
525 engine.set_header({"Authorization": "Bearer {}".format(response["id"])})
tiernocd54a4a2018-09-12 16:40:35 +0200526
tiernoff6485d2018-11-28 17:19:46 +0000527 engine.test("Add new project admin", "POST", "/admin/v1/projects", headers_json, {"name": "P2"},
tiernocd54a4a2018-09-12 16:40:35 +0200528 (201, 204), {"Location": "/admin/v1/projects/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000529 engine.test("Add new user U3 admin", "POST", "/admin/v1/users",
tiernocd54a4a2018-09-12 16:40:35 +0200530 headers_json, {"username": "U3", "projects": ["P2"], "password": "pw3"}, (201, 204),
531 {"Location": "/admin/v1/users/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000532 engine.test("Edit user projects admin", "PUT", "/admin/v1/users/U3", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200533 {"projects": ["P2"]}, 204, None, None)
534
tiernoff6485d2018-11-28 17:19:46 +0000535 engine.test("Delete project P2 conflict", "DELETE", "/admin/v1/projects/P2", headers_json, None, 409,
tiernocd54a4a2018-09-12 16:40:35 +0200536 r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000537 engine.test("Delete project P2 forcing", "DELETE", "/admin/v1/projects/P2?FORCE=True", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200538 None, 204, None, None)
539
tiernoff6485d2018-11-28 17:19:46 +0000540 engine.test("Delete user U1. Conflict deleting own user", "DELETE", "/admin/v1/users/U1", headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200541 None, 409, r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +0000542 engine.test("Delete user U2", "DELETE", "/admin/v1/users/U2", headers_json, None, 204, None, None)
543 engine.test("Delete user U3", "DELETE", "/admin/v1/users/U3", headers_json, None, 204, None, None)
tiernocd54a4a2018-09-12 16:40:35 +0200544 # change to admin
545 engine.remove_authorization() # To force get authorization
546 engine.get_autorization()
delacruzramoc061f562019-04-05 11:00:02 +0200547 engine.test("Delete user U1 by Name", "DELETE", "/admin/v1/users/U1", headers_json, None, 204, None, None)
548 engine.test("Delete project P1 by Name", "DELETE", "/admin/v1/projects/P1", headers_json, None, 204, None, None)
549 engine.test("Delete project Padmin by Name", "DELETE", "/admin/v1/projects/Padmin", headers_json, None, 204,
tiernocd54a4a2018-09-12 16:40:35 +0200550 None, None)
551
delacruzramoc061f562019-04-05 11:00:02 +0200552 # BEGIN New Tests - Addressing Projects/Users by Name/ID
553 res = engine.test("Create new project P1", "POST", "/admin/v1/projects", headers_json, {"name": "P1"},
554 201, {"Location": "/admin/v1/projects/", "Content-Type": "application/json"}, "json")
555 if res:
556 pid1 = res.json()["id"]
557 # print("# pid =", pid1)
558 res = engine.test("Create new project P2", "POST", "/admin/v1/projects", headers_json, {"name": "P2"},
559 201, {"Location": "/admin/v1/projects/", "Content-Type": "application/json"}, "json")
560 if res:
561 pid2 = res.json()["id"]
562 # print("# pid =", pid2)
563 res = engine.test("Create new user U1", "POST", "/admin/v1/users", headers_json,
564 {"username": "U1", "projects": ["P1"], "password": "pw1"}, 201,
565 {"Location": "/admin/v1/users/", "Content-Type": "application/json"}, "json")
566 if res:
567 uid1 = res.json()["id"]
568 # print("# uid =", uid1)
569 res = engine.test("Create new user U2", "POST", "/admin/v1/users", headers_json,
570 {"username": "U2", "projects": ["P2"], "password": "pw2"}, 201,
571 {"Location": "/admin/v1/users/", "Content-Type": "application/json"}, "json")
572 if res:
573 uid2 = res.json()["id"]
574 # print("# uid =", uid2)
575 engine.test("Get Project P1 by Name", "GET", "/admin/v1/projects/P1", headers_json, None, 200, None, "json")
576 engine.test("Get Project P1 by ID", "GET", "/admin/v1/projects/"+pid1, headers_json, None, 200, None, "json")
577 engine.test("Get User U1 by Name", "GET", "/admin/v1/users/U1", headers_json, None, 200, None, "json")
578 engine.test("Get User U1 by ID", "GET", "/admin/v1/users/"+uid1, headers_json, None, 200, None, "json")
579 engine.test("Rename Project P1 by Name", "PUT", "/admin/v1/projects/P1", headers_json,
580 {"name": "P3"}, 204, None, None)
581 engine.test("Rename Project P2 by ID", "PUT", "/admin/v1/projects/"+pid2, headers_json,
582 {"name": "P4"}, 204, None, None)
583 engine.test("Rename User U1 by Name", "PUT", "/admin/v1/users/U1", headers_json,
584 {"username": "U3"}, 204, None, None)
585 engine.test("Rename User U2 by ID", "PUT", "/admin/v1/users/"+uid2, headers_json,
586 {"username": "U4"}, 204, None, None)
587 engine.test("Get Project P1 by new Name", "GET", "/admin/v1/projects/P3", headers_json, None, 200, None, "json")
588 engine.test("Get User U1 by new Name", "GET", "/admin/v1/users/U3", headers_json, None, 200, None, "json")
589 engine.test("Delete User U1 by Name", "DELETE", "/admin/v1/users/U3", headers_json, None, 204, None, None)
590 engine.test("Delete User U2 by ID", "DELETE", "/admin/v1/users/"+uid2, headers_json, None, 204, None, None)
591 engine.test("Delete Project P1 by Name", "DELETE", "/admin/v1/projects/P3", headers_json, None, 204, None,
592 None)
593 engine.test("Delete Project P2 by ID", "DELETE", "/admin/v1/projects/"+pid2, headers_json, None, 204, None,
594 None)
595 # END New Tests - Addressing Projects/Users by Name
596 engine.remove_authorization() # To finish
597
tiernocd54a4a2018-09-12 16:40:35 +0200598
tierno65ca36d2019-02-12 19:27:52 +0100599class TestProjectsDescriptors:
600 description = "test descriptors visibility among projects"
601
602 @staticmethod
603 def run(engine, test_osm, manual_check, test_params=None):
604 vnfd_ids = []
605 engine.set_test_name("ProjectDescriptors")
606 engine.get_autorization()
607 engine.test("Create project Padmin", "POST", "/admin/v1/projects", headers_json,
608 {"name": "Padmin", "admin": True}, (201, 204),
609 {"Location": "/admin/v1/projects/", "Content-Type": "application/json"}, "json")
610 engine.test("Create project P2", "POST", "/admin/v1/projects", headers_json, {"name": "P2"},
611 (201, 204), {"Location": "/admin/v1/projects/", "Content-Type": "application/json"}, "json")
612 engine.test("Create project P3", "POST", "/admin/v1/projects", headers_json, {"name": "P3"},
613 (201, 204), {"Location": "/admin/v1/projects/", "Content-Type": "application/json"}, "json")
614
615 engine.test("Create user U1", "POST", "/admin/v1/users", headers_json,
616 {"username": "U1", "projects": ["Padmin", "P2", "P3"], "password": "pw1"}, 201,
617 {"Location": "/admin/v1/users/", "Content-Type": "application/json"}, "json")
618
619 engine.test("Onboard VNFD id1", "POST", "/vnfpkgm/v1/vnf_packages_content?id=id1", headers_yaml,
620 TestDescriptors.vnfd_empty, 201, r_headers_yaml_location_vnfd, "yaml")
621 vnfd_ids.append(engine.last_id)
622 engine.test("Onboard VNFD id2 PUBLIC", "POST", "/vnfpkgm/v1/vnf_packages_content?id=id2&PUBLIC=TRUE",
623 headers_yaml, TestDescriptors.vnfd_empty, 201, r_headers_yaml_location_vnfd, "yaml")
624 vnfd_ids.append(engine.last_id)
625 engine.test("Onboard VNFD id3", "POST", "/vnfpkgm/v1/vnf_packages_content?id=id3&PUBLIC=FALSE", headers_yaml,
626 TestDescriptors.vnfd_empty, 201, r_headers_yaml_location_vnfd, "yaml")
627 vnfd_ids.append(engine.last_id)
628
629 res = engine.test("Get VNFD descriptors", "GET", "/vnfpkgm/v1/vnf_packages?id=id1,id2,id3",
630 headers_json, None, 200, r_header_json, "json")
631 response = res.json()
632 if len(response) != 3:
633 logger.error("Only 3 vnfds should be present for project admin. {} listed".format(len(response)))
634 engine.failed_tests += 1
635
636 # Change to other project Padmin
637 res = engine.test("Change to user U1 project Padmin", "POST", "/admin/v1/tokens", headers_json,
638 {"username": "U1", "password": "pw1", "project_id": "Padmin"}, (200, 201),
639 r_header_json, "json")
640 if res:
641 response = res.json()
642 engine.set_header({"Authorization": "Bearer {}".format(response["id"])})
643
644 # list vnfds
645 res = engine.test("List VNFD descriptors for Padmin", "GET", "/vnfpkgm/v1/vnf_packages",
646 headers_json, None, 200, r_header_json, "json")
647 response = res.json()
648 if len(response) != 0:
649 logger.error("Only 0 vnfds should be present for project Padmin. {} listed".format(len(response)))
650 engine.failed_tests += 1
651
652 # list Public vnfds
653 res = engine.test("List VNFD public descriptors", "GET", "/vnfpkgm/v1/vnf_packages?PUBLIC=True",
654 headers_json, None, 200, r_header_json, "json")
655 response = res.json()
656 if len(response) != 1:
657 logger.error("Only 1 vnfds should be present for project Padmin. {} listed".format(len(response)))
658 engine.failed_tests += 1
659
660 # list vnfds belonging to project "admin"
661 res = engine.test("List VNFD of admin project", "GET", "/vnfpkgm/v1/vnf_packages?ADMIN=admin",
662 headers_json, None, 200, r_header_json, "json")
663 response = res.json()
664 if len(response) != 3:
665 logger.error("Only 3 vnfds should be present for project Padmin. {} listed".format(len(response)))
666 engine.failed_tests += 1
667
668 # Get Public vnfds
669 engine.test("Get VNFD public descriptors", "GET", "/vnfpkgm/v1/vnf_packages/{}".format(vnfd_ids[1]),
670 headers_json, None, 200, r_header_json, "json")
671 # Edit not owned vnfd
672 engine.test("Edit VNFD ", "PATCH", "/vnfpkgm/v1/vnf_packages/{}".format(vnfd_ids[0]),
673 headers_yaml, '{name: pepe}', 404, r_header_yaml, "yaml")
674
675 # Add to my catalog
676 engine.test("Add VNFD id2 to my catalog", "PATCH", "/vnfpkgm/v1/vnf_packages/{}?SET_PROJECT".
677 format(vnfd_ids[1]), headers_json, None, 204, None, 0)
678
679 # Add a new vnfd
680 engine.test("Onboard VNFD id4", "POST", "/vnfpkgm/v1/vnf_packages_content?id=id4", headers_yaml,
681 TestDescriptors.vnfd_empty, 201, r_headers_yaml_location_vnfd, "yaml")
682 vnfd_ids.append(engine.last_id)
683
684 # list vnfds
685 res = engine.test("List VNFD public descriptors", "GET", "/vnfpkgm/v1/vnf_packages",
686 headers_json, None, 200, r_header_json, "json")
687 response = res.json()
688 if len(response) != 2:
689 logger.error("Only 2 vnfds should be present for project Padmin. {} listed".format(len(response)))
690 engine.failed_tests += 1
691
692 if manual_check:
693 input('VNFDs have been omboarded. Perform manual check and press enter to resume')
694
695 test_rest.test("Delete VNFD id2", "DELETE", "/vnfpkgm/v1/vnf_packages/{}".format(vnfd_ids[1]),
696 headers_yaml, None, 204, None, 0)
697
698 # change to admin project
699 engine.remove_authorization() # To force get authorization
700 engine.get_autorization()
701 test_rest.test("Delete VNFD id1", "DELETE", "/vnfpkgm/v1/vnf_packages/{}".format(vnfd_ids[0]),
702 headers_yaml, None, 204, None, 0)
703 test_rest.test("Delete VNFD id2", "DELETE", "/vnfpkgm/v1/vnf_packages/{}".format(vnfd_ids[1]),
704 headers_yaml, None, 204, None, 0)
705 test_rest.test("Delete VNFD id3", "DELETE", "/vnfpkgm/v1/vnf_packages/{}".format(vnfd_ids[2]),
706 headers_yaml, None, 204, None, 0)
707 test_rest.test("Delete VNFD id4", "DELETE", "/vnfpkgm/v1/vnf_packages/{}".format(vnfd_ids[3]),
708 headers_yaml, None, 404, r_header_yaml, "yaml")
709 test_rest.test("Delete VNFD id4", "DELETE", "/vnfpkgm/v1/vnf_packages/{}?ADMIN".format(vnfd_ids[3]),
710 headers_yaml, None, 204, None, 0)
711 # Get Public vnfds
712 engine.test("Get VNFD deleted id1", "GET", "/vnfpkgm/v1/vnf_packages/{}?ADMIN".format(vnfd_ids[0]),
713 headers_json, None, 404, r_header_json, "json")
714 engine.test("Get VNFD deleted id2", "GET", "/vnfpkgm/v1/vnf_packages/{}?ADMIN".format(vnfd_ids[1]),
715 headers_json, None, 404, r_header_json, "json")
716 engine.test("Get VNFD deleted id3", "GET", "/vnfpkgm/v1/vnf_packages/{}?ADMIN".format(vnfd_ids[2]),
717 headers_json, None, 404, r_header_json, "json")
718 engine.test("Get VNFD deleted id4", "GET", "/vnfpkgm/v1/vnf_packages/{}?ADMIN".format(vnfd_ids[3]),
719 headers_json, None, 404, r_header_json, "json")
720
721 engine.test("Delete user U1", "DELETE", "/admin/v1/users/U1", headers_json, None, 204, None, None)
722 engine.test("Delete project Padmin", "DELETE", "/admin/v1/projects/Padmin", headers_json, None, 204, None, None)
723 engine.test("Delete project P2", "DELETE", "/admin/v1/projects/P2", headers_json, None, 204, None, None)
724 engine.test("Delete project P3", "DELETE", "/admin/v1/projects/P3", headers_json, None, 204, None, None)
725
726
tiernoc32ba4a2018-05-24 18:06:41 +0200727class TestFakeVim:
728 description = "Creates/edit/delete fake VIMs and SDN controllers"
729
730 def __init__(self):
731 self.vim = {
732 "schema_version": "1.0",
733 "schema_type": "No idea",
734 "name": "myVim",
735 "description": "Descriptor name",
736 "vim_type": "openstack",
737 "vim_url": "http://localhost:/vim",
738 "vim_tenant_name": "vimTenant",
739 "vim_user": "user",
740 "vim_password": "password",
741 "config": {"config_param": 1}
742 }
743 self.sdn = {
744 "name": "sdn-name",
745 "description": "sdn-description",
746 "dpid": "50:50:52:54:00:94:21:21",
747 "ip": "192.168.15.17",
748 "port": 8080,
749 "type": "opendaylight",
750 "version": "3.5.6",
751 "user": "user",
752 "password": "passwd"
753 }
754 self.port_mapping = [
755 {"compute_node": "compute node 1",
756 "ports": [{"pci": "0000:81:00.0", "switch_port": "port-2/1", "switch_mac": "52:54:00:94:21:21"},
757 {"pci": "0000:81:00.1", "switch_port": "port-2/2", "switch_mac": "52:54:00:94:21:22"}
758 ]},
759 {"compute_node": "compute node 2",
760 "ports": [{"pci": "0000:81:00.0", "switch_port": "port-2/3", "switch_mac": "52:54:00:94:21:23"},
761 {"pci": "0000:81:00.1", "switch_port": "port-2/4", "switch_mac": "52:54:00:94:21:24"}
762 ]}
763 ]
764
tiernocd54a4a2018-09-12 16:40:35 +0200765 def run(self, engine, test_osm, manual_check, test_params=None):
tiernoc32ba4a2018-05-24 18:06:41 +0200766
767 vim_bad = self.vim.copy()
768 vim_bad.pop("name")
769
tiernoff6485d2018-11-28 17:19:46 +0000770 engine.set_test_name("FakeVim")
tiernoc32ba4a2018-05-24 18:06:41 +0200771 engine.get_autorization()
tiernoff6485d2018-11-28 17:19:46 +0000772 engine.test("Create VIM", "POST", "/admin/v1/vim_accounts", headers_json, self.vim, (201, 204),
tiernoc32ba4a2018-05-24 18:06:41 +0200773 {"Location": "/admin/v1/vim_accounts/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000774 vim_id = engine.last_id
775 engine.test("Create VIM without name, bad schema", "POST", "/admin/v1/vim_accounts", headers_json,
tiernoc32ba4a2018-05-24 18:06:41 +0200776 vim_bad, 422, None, headers_json)
tiernoff6485d2018-11-28 17:19:46 +0000777 engine.test("Create VIM name repeated", "POST", "/admin/v1/vim_accounts", headers_json, self.vim,
tiernoc32ba4a2018-05-24 18:06:41 +0200778 409, None, headers_json)
tiernoff6485d2018-11-28 17:19:46 +0000779 engine.test("Show VIMs", "GET", "/admin/v1/vim_accounts", headers_yaml, None, 200, r_header_yaml,
tiernoc32ba4a2018-05-24 18:06:41 +0200780 "yaml")
tiernoff6485d2018-11-28 17:19:46 +0000781 engine.test("Show VIM", "GET", "/admin/v1/vim_accounts/{}".format(vim_id), headers_yaml, None, 200,
tiernoc32ba4a2018-05-24 18:06:41 +0200782 r_header_yaml, "yaml")
783 if not test_osm:
784 # delete with FORCE
tiernoff6485d2018-11-28 17:19:46 +0000785 engine.test("Delete VIM", "DELETE", "/admin/v1/vim_accounts/{}?FORCE=True".format(vim_id), headers_yaml,
tiernoc32ba4a2018-05-24 18:06:41 +0200786 None, 202, None, 0)
tiernoff6485d2018-11-28 17:19:46 +0000787 engine.test("Check VIM is deleted", "GET", "/admin/v1/vim_accounts/{}".format(vim_id), headers_yaml, None,
tiernoc32ba4a2018-05-24 18:06:41 +0200788 404, r_header_yaml, "yaml")
789 else:
790 # delete and wait until is really deleted
tiernoff6485d2018-11-28 17:19:46 +0000791 engine.test("Delete VIM", "DELETE", "/admin/v1/vim_accounts/{}".format(vim_id), headers_yaml, None, 202,
tiernoc32ba4a2018-05-24 18:06:41 +0200792 None, 0)
tiernoff6485d2018-11-28 17:19:46 +0000793 engine.wait_until_delete("/admin/v1/vim_accounts/{}".format(vim_id), timeout)
tiernoc32ba4a2018-05-24 18:06:41 +0200794
795
796class TestVIMSDN(TestFakeVim):
797 description = "Creates VIM with SDN editing SDN controllers and port_mapping"
798
799 def __init__(self):
800 TestFakeVim.__init__(self)
tierno55ba2e62018-12-11 17:22:22 +0000801 self.wim = {
802 "schema_version": "1.0",
803 "schema_type": "No idea",
804 "name": "myWim",
805 "description": "Descriptor name",
806 "wim_type": "odl",
807 "wim_url": "http://localhost:/wim",
808 "user": "user",
809 "password": "password",
810 "config": {"config_param": 1}
811 }
tiernoc32ba4a2018-05-24 18:06:41 +0200812
tiernocd54a4a2018-09-12 16:40:35 +0200813 def run(self, engine, test_osm, manual_check, test_params=None):
tiernoff6485d2018-11-28 17:19:46 +0000814 engine.set_test_name("VimSdn")
tiernoc32ba4a2018-05-24 18:06:41 +0200815 engine.get_autorization()
816 # Added SDN
tiernoff6485d2018-11-28 17:19:46 +0000817 engine.test("Create SDN", "POST", "/admin/v1/sdns", headers_json, self.sdn, (201, 204),
tiernoc32ba4a2018-05-24 18:06:41 +0200818 {"Location": "/admin/v1/sdns/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000819 sdnc_id = engine.last_id
tiernocd54a4a2018-09-12 16:40:35 +0200820 # sleep(5)
tiernoc32ba4a2018-05-24 18:06:41 +0200821 # Edit SDN
tiernoff6485d2018-11-28 17:19:46 +0000822 engine.test("Edit SDN", "PATCH", "/admin/v1/sdns/{}".format(sdnc_id), headers_json, {"name": "new_sdn_name"},
tiernocd54a4a2018-09-12 16:40:35 +0200823 204, None, None)
824 # sleep(5)
tiernoc32ba4a2018-05-24 18:06:41 +0200825 # VIM with SDN
tiernoff6485d2018-11-28 17:19:46 +0000826 self.vim["config"]["sdn-controller"] = sdnc_id
tiernoc32ba4a2018-05-24 18:06:41 +0200827 self.vim["config"]["sdn-port-mapping"] = self.port_mapping
tiernoff6485d2018-11-28 17:19:46 +0000828 engine.test("Create VIM", "POST", "/admin/v1/vim_accounts", headers_json, self.vim, (200, 204, 201),
tiernoc32ba4a2018-05-24 18:06:41 +0200829 {"Location": "/admin/v1/vim_accounts/", "Content-Type": "application/json"}, "json"),
830
tiernoff6485d2018-11-28 17:19:46 +0000831 vim_id = engine.last_id
tiernoc32ba4a2018-05-24 18:06:41 +0200832 self.port_mapping[0]["compute_node"] = "compute node XX"
tiernoff6485d2018-11-28 17:19:46 +0000833 engine.test("Edit VIM change port-mapping", "PUT", "/admin/v1/vim_accounts/{}".format(vim_id), headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200834 {"config": {"sdn-port-mapping": self.port_mapping}}, 204, None, None)
tiernoff6485d2018-11-28 17:19:46 +0000835 engine.test("Edit VIM remove port-mapping", "PUT", "/admin/v1/vim_accounts/{}".format(vim_id), headers_json,
tiernocd54a4a2018-09-12 16:40:35 +0200836 {"config": {"sdn-port-mapping": None}}, 204, None, None)
837
tierno55ba2e62018-12-11 17:22:22 +0000838 engine.test("Create WIM", "POST", "/admin/v1/wim_accounts", headers_json, self.wim, (200, 204, 201),
839 {"Location": "/admin/v1/wim_accounts/", "Content-Type": "application/json"}, "json"),
840 wim_id = engine.last_id
841
tiernocd54a4a2018-09-12 16:40:35 +0200842 if not test_osm:
843 # delete with FORCE
tiernoff6485d2018-11-28 17:19:46 +0000844 engine.test("Delete VIM remove port-mapping", "DELETE",
845 "/admin/v1/vim_accounts/{}?FORCE=True".format(vim_id), headers_json, None, 202, None, 0)
846 engine.test("Delete SDNC", "DELETE", "/admin/v1/sdns/{}?FORCE=True".format(sdnc_id), headers_json, None,
tiernocd54a4a2018-09-12 16:40:35 +0200847 202, None, 0)
848
tierno55ba2e62018-12-11 17:22:22 +0000849 engine.test("Delete WIM", "DELETE",
850 "/admin/v1/wim_accounts/{}?FORCE=True".format(wim_id), headers_json, None, 202, None, 0)
tiernoff6485d2018-11-28 17:19:46 +0000851 engine.test("Check VIM is deleted", "GET", "/admin/v1/vim_accounts/{}".format(vim_id), headers_yaml,
tiernocd54a4a2018-09-12 16:40:35 +0200852 None, 404, r_header_yaml, "yaml")
tiernoff6485d2018-11-28 17:19:46 +0000853 engine.test("Check SDN is deleted", "GET", "/admin/v1/sdns/{}".format(sdnc_id), headers_yaml, None,
tiernocd54a4a2018-09-12 16:40:35 +0200854 404, r_header_yaml, "yaml")
tierno55ba2e62018-12-11 17:22:22 +0000855 engine.test("Check WIM is deleted", "GET", "/admin/v1/wim_accounts/{}".format(wim_id), headers_yaml,
856 None, 404, r_header_yaml, "yaml")
tiernocd54a4a2018-09-12 16:40:35 +0200857 else:
tierno55ba2e62018-12-11 17:22:22 +0000858 if manual_check:
859 input('VIM, SDN, WIM has been deployed. Perform manual check and press enter to resume')
tiernocd54a4a2018-09-12 16:40:35 +0200860 # delete and wait until is really deleted
tiernoff6485d2018-11-28 17:19:46 +0000861 engine.test("Delete VIM remove port-mapping", "DELETE", "/admin/v1/vim_accounts/{}".format(vim_id),
tiernocd54a4a2018-09-12 16:40:35 +0200862 headers_json, None, (202, 201, 204), None, 0)
tiernoff6485d2018-11-28 17:19:46 +0000863 engine.test("Delete SDN", "DELETE", "/admin/v1/sdns/{}".format(sdnc_id), headers_json, None,
tiernocd54a4a2018-09-12 16:40:35 +0200864 (202, 201, 204), None, 0)
tierno55ba2e62018-12-11 17:22:22 +0000865 engine.test("Delete VIM", "DELETE", "/admin/v1/wim_accounts/{}".format(wim_id),
866 headers_json, None, (202, 201, 204), None, 0)
tiernoff6485d2018-11-28 17:19:46 +0000867 engine.wait_until_delete("/admin/v1/vim_accounts/{}".format(vim_id), timeout)
868 engine.wait_until_delete("/admin/v1/sdns/{}".format(sdnc_id), timeout)
tierno55ba2e62018-12-11 17:22:22 +0000869 engine.wait_until_delete("/admin/v1/wim_accounts/{}".format(wim_id), timeout)
tiernoc32ba4a2018-05-24 18:06:41 +0200870
871
872class TestDeploy:
873 description = "Base class for downloading descriptors from ETSI, onboard and deploy in real VIM"
874
875 def __init__(self):
tiernoff6485d2018-11-28 17:19:46 +0000876 self.test_name = "DEPLOY"
tiernoc32ba4a2018-05-24 18:06:41 +0200877 self.nsd_id = None
878 self.vim_id = None
gcalvino337ec512018-07-30 10:30:13 +0200879 self.ns_id = None
tiernocc103432018-10-19 14:10:35 +0200880 self.vnfds_id = []
tiernoc32ba4a2018-05-24 18:06:41 +0200881 self.descriptor_url = "https://osm-download.etsi.org/ftp/osm-3.0-three/2nd-hackfest/packages/"
882 self.vnfd_filenames = ("cirros_vnf.tar.gz",)
883 self.nsd_filename = "cirros_2vnf_ns.tar.gz"
tierno36ec8602018-11-02 17:27:11 +0100884 self.descriptor_edit = None
tiernoc32ba4a2018-05-24 18:06:41 +0200885 self.uses_configuration = False
tiernobee085c2018-12-12 17:03:04 +0000886 self.users = {}
887 self.passwords = {}
888 self.commands = {}
gcalvino337ec512018-07-30 10:30:13 +0200889 self.keys = {}
890 self.timeout = 120
tierno36ec8602018-11-02 17:27:11 +0100891 self.qforce = ""
tiernobee085c2018-12-12 17:03:04 +0000892 self.ns_params = None
kuuse587aeea2019-04-26 12:33:07 +0200893 self.vnfr_ip_list = {}
tiernoc32ba4a2018-05-24 18:06:41 +0200894
895 def create_descriptors(self, engine):
gcalvino337ec512018-07-30 10:30:13 +0200896 temp_dir = os.path.dirname(os.path.abspath(__file__)) + "/temp/"
tiernoc32ba4a2018-05-24 18:06:41 +0200897 if not os.path.exists(temp_dir):
898 os.makedirs(temp_dir)
tierno36ec8602018-11-02 17:27:11 +0100899 for vnfd_index, vnfd_filename in enumerate(self.vnfd_filenames):
tiernoc32ba4a2018-05-24 18:06:41 +0200900 if "/" in vnfd_filename:
901 vnfd_filename_path = vnfd_filename
902 if not os.path.exists(vnfd_filename_path):
903 raise TestException("File '{}' does not exist".format(vnfd_filename_path))
904 else:
905 vnfd_filename_path = temp_dir + vnfd_filename
906 if not os.path.exists(vnfd_filename_path):
907 with open(vnfd_filename_path, "wb") as file:
908 response = requests.get(self.descriptor_url + vnfd_filename)
909 if response.status_code >= 300:
910 raise TestException("Error downloading descriptor from '{}': {}".format(
911 self.descriptor_url + vnfd_filename, response.status_code))
912 file.write(response.content)
913 if vnfd_filename_path.endswith(".yaml"):
914 headers = headers_yaml
915 else:
916 headers = headers_zip_yaml
tiernoff6485d2018-11-28 17:19:46 +0000917 if randint(0, 1) == 0:
tiernoc32ba4a2018-05-24 18:06:41 +0200918 # vnfd CREATE AND UPLOAD in one step:
tiernoff6485d2018-11-28 17:19:46 +0000919 engine.test("Onboard VNFD in one step", "POST",
tierno36ec8602018-11-02 17:27:11 +0100920 "/vnfpkgm/v1/vnf_packages_content" + self.qforce, headers, "@b" + vnfd_filename_path, 201,
tiernof717cbe2018-12-03 16:35:42 +0000921 r_headers_yaml_location_vnfd,
tierno36ec8602018-11-02 17:27:11 +0100922 "yaml")
tiernoff6485d2018-11-28 17:19:46 +0000923 self.vnfds_id.append(engine.last_id)
tiernoc32ba4a2018-05-24 18:06:41 +0200924 else:
925 # vnfd CREATE AND UPLOAD ZIP
tiernoff6485d2018-11-28 17:19:46 +0000926 engine.test("Onboard VNFD step 1", "POST", "/vnfpkgm/v1/vnf_packages",
tiernoc32ba4a2018-05-24 18:06:41 +0200927 headers_json, None, 201,
928 {"Location": "/vnfpkgm/v1/vnf_packages/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000929 self.vnfds_id.append(engine.last_id)
930 engine.test("Onboard VNFD step 2 as ZIP", "PUT",
tierno36ec8602018-11-02 17:27:11 +0100931 "/vnfpkgm/v1/vnf_packages/<>/package_content" + self.qforce,
tiernoc32ba4a2018-05-24 18:06:41 +0200932 headers, "@b" + vnfd_filename_path, 204, None, 0)
tiernoc32ba4a2018-05-24 18:06:41 +0200933
tierno36ec8602018-11-02 17:27:11 +0100934 if self.descriptor_edit:
935 if "vnfd{}".format(vnfd_index) in self.descriptor_edit:
936 # Modify VNFD
tiernoff6485d2018-11-28 17:19:46 +0000937 engine.test("Edit VNFD ", "PATCH",
tierno36ec8602018-11-02 17:27:11 +0100938 "/vnfpkgm/v1/vnf_packages/{}".format(self.vnfds_id[-1]),
939 headers_yaml, self.descriptor_edit["vnfd{}".format(vnfd_index)], 204, None, None)
tierno36ec8602018-11-02 17:27:11 +0100940
tiernoc32ba4a2018-05-24 18:06:41 +0200941 if "/" in self.nsd_filename:
942 nsd_filename_path = self.nsd_filename
943 if not os.path.exists(nsd_filename_path):
944 raise TestException("File '{}' does not exist".format(nsd_filename_path))
945 else:
946 nsd_filename_path = temp_dir + self.nsd_filename
947 if not os.path.exists(nsd_filename_path):
948 with open(nsd_filename_path, "wb") as file:
949 response = requests.get(self.descriptor_url + self.nsd_filename)
950 if response.status_code >= 300:
951 raise TestException("Error downloading descriptor from '{}': {}".format(
952 self.descriptor_url + self.nsd_filename, response.status_code))
953 file.write(response.content)
954 if nsd_filename_path.endswith(".yaml"):
955 headers = headers_yaml
956 else:
957 headers = headers_zip_yaml
958
tiernoff6485d2018-11-28 17:19:46 +0000959 if randint(0, 1) == 0:
tiernoc32ba4a2018-05-24 18:06:41 +0200960 # nsd CREATE AND UPLOAD in one step:
tiernoff6485d2018-11-28 17:19:46 +0000961 engine.test("Onboard NSD in one step", "POST",
tierno36ec8602018-11-02 17:27:11 +0100962 "/nsd/v1/ns_descriptors_content" + self.qforce, headers, "@b" + nsd_filename_path, 201,
tiernof717cbe2018-12-03 16:35:42 +0000963 r_headers_yaml_location_nsd, yaml)
tiernoff6485d2018-11-28 17:19:46 +0000964 self.nsd_id = engine.last_id
tiernoc32ba4a2018-05-24 18:06:41 +0200965 else:
966 # nsd CREATE AND UPLOAD ZIP
tiernoff6485d2018-11-28 17:19:46 +0000967 engine.test("Onboard NSD step 1", "POST", "/nsd/v1/ns_descriptors",
tiernoc32ba4a2018-05-24 18:06:41 +0200968 headers_json, None, 201,
969 {"Location": "/nsd/v1/ns_descriptors/", "Content-Type": "application/json"}, "json")
tiernoff6485d2018-11-28 17:19:46 +0000970 self.nsd_id = engine.last_id
971 engine.test("Onboard NSD step 2 as ZIP", "PUT",
tierno36ec8602018-11-02 17:27:11 +0100972 "/nsd/v1/ns_descriptors/<>/nsd_content" + self.qforce,
tiernoc32ba4a2018-05-24 18:06:41 +0200973 headers, "@b" + nsd_filename_path, 204, None, 0)
tierno36ec8602018-11-02 17:27:11 +0100974
975 if self.descriptor_edit and "nsd" in self.descriptor_edit:
976 # Modify NSD
tiernoff6485d2018-11-28 17:19:46 +0000977 engine.test("Edit NSD ", "PATCH",
tierno36ec8602018-11-02 17:27:11 +0100978 "/nsd/v1/ns_descriptors/{}".format(self.nsd_id),
979 headers_yaml, self.descriptor_edit["nsd"], 204, None, None)
tiernoc32ba4a2018-05-24 18:06:41 +0200980
981 def delete_descriptors(self, engine):
982 # delete descriptors
tiernoff6485d2018-11-28 17:19:46 +0000983 engine.test("Delete NSSD SOL005", "DELETE",
tierno36ec8602018-11-02 17:27:11 +0100984 "/nsd/v1/ns_descriptors/{}".format(self.nsd_id),
tiernoc32ba4a2018-05-24 18:06:41 +0200985 headers_yaml, None, 204, None, 0)
tierno36ec8602018-11-02 17:27:11 +0100986 for vnfd_id in self.vnfds_id:
tiernoff6485d2018-11-28 17:19:46 +0000987 engine.test("Delete VNFD SOL005", "DELETE",
tierno36ec8602018-11-02 17:27:11 +0100988 "/vnfpkgm/v1/vnf_packages/{}".format(vnfd_id), headers_yaml, None, 204, None, 0)
tiernoc32ba4a2018-05-24 18:06:41 +0200989
990 def instantiate(self, engine, ns_data):
991 ns_data_text = yaml.safe_dump(ns_data, default_flow_style=True, width=256)
992 # create NS Two steps
tiernoff6485d2018-11-28 17:19:46 +0000993 r = engine.test("Create NS step 1", "POST", "/nslcm/v1/ns_instances",
tiernoc32ba4a2018-05-24 18:06:41 +0200994 headers_yaml, ns_data_text, 201,
995 {"Location": "nslcm/v1/ns_instances/", "Content-Type": "application/yaml"}, "yaml")
tiernoff6485d2018-11-28 17:19:46 +0000996 if not r:
997 return
998 self.ns_id = engine.last_id
999 engine.test("Instantiate NS step 2", "POST",
1000 "/nslcm/v1/ns_instances/{}/instantiate".format(self.ns_id), headers_yaml, ns_data_text,
tiernof717cbe2018-12-03 16:35:42 +00001001 201, r_headers_yaml_location_nslcmop, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001002 nslcmop_id = engine.last_id
tiernoc32ba4a2018-05-24 18:06:41 +02001003
1004 if test_osm:
1005 # Wait until status is Ok
tiernoff6485d2018-11-28 17:19:46 +00001006 timeout = timeout_configure if self.uses_configuration else timeout_deploy
1007 engine.wait_operation_ready("ns", nslcmop_id, timeout)
tiernoc32ba4a2018-05-24 18:06:41 +02001008
1009 def terminate(self, engine):
1010 # remove deployment
1011 if test_osm:
tiernoff6485d2018-11-28 17:19:46 +00001012 engine.test("Terminate NS", "POST", "/nslcm/v1/ns_instances/{}/terminate".format(self.ns_id), headers_yaml,
tiernof717cbe2018-12-03 16:35:42 +00001013 None, 201, r_headers_yaml_location_nslcmop, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001014 nslcmop2_id = engine.last_id
tiernoc32ba4a2018-05-24 18:06:41 +02001015 # Wait until status is Ok
tiernoff6485d2018-11-28 17:19:46 +00001016 engine.wait_operation_ready("ns", nslcmop2_id, timeout_deploy)
tiernoc32ba4a2018-05-24 18:06:41 +02001017
tiernoff6485d2018-11-28 17:19:46 +00001018 engine.test("Delete NS", "DELETE", "/nslcm/v1/ns_instances/{}".format(self.ns_id), headers_yaml, None,
1019 204, None, 0)
tiernoc32ba4a2018-05-24 18:06:41 +02001020 else:
tiernoff6485d2018-11-28 17:19:46 +00001021 engine.test("Delete NS with FORCE", "DELETE", "/nslcm/v1/ns_instances/{}?FORCE=True".format(self.ns_id),
1022 headers_yaml, None, 204, None, 0)
tiernoc32ba4a2018-05-24 18:06:41 +02001023
1024 # check all it is deleted
tiernoff6485d2018-11-28 17:19:46 +00001025 engine.test("Check NS is deleted", "GET", "/nslcm/v1/ns_instances/{}".format(self.ns_id), headers_yaml, None,
1026 404, None, "yaml")
1027 r = engine.test("Check NSLCMOPs are deleted", "GET",
1028 "/nslcm/v1/ns_lcm_op_occs?nsInstanceId={}".format(self.ns_id), headers_json, None,
tiernoc32ba4a2018-05-24 18:06:41 +02001029 200, None, "json")
tiernoff6485d2018-11-28 17:19:46 +00001030 if not r:
1031 return
tiernoc32ba4a2018-05-24 18:06:41 +02001032 nslcmops = r.json()
1033 if not isinstance(nslcmops, list) or nslcmops:
tiernoff6485d2018-11-28 17:19:46 +00001034 raise TestException("NS {} deleted but with ns_lcm_op_occ active: {}".format(self.ns_id, nslcmops))
tiernoc32ba4a2018-05-24 18:06:41 +02001035
gcalvino337ec512018-07-30 10:30:13 +02001036 def test_ns(self, engine, test_osm, commands=None, users=None, passwds=None, keys=None, timeout=0):
1037
tiernoff6485d2018-11-28 17:19:46 +00001038 r = engine.test("GET VNFR IDs", "GET",
gcalvino337ec512018-07-30 10:30:13 +02001039 "/nslcm/v1/ns_instances/{}".format(self.ns_id), headers_json, None,
1040 200, r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +00001041 if not r:
1042 return
gcalvino337ec512018-07-30 10:30:13 +02001043 ns_data = r.json()
1044
1045 vnfr_list = ns_data['constituent-vnfr-ref']
1046 time = 0
tiernobee085c2018-12-12 17:03:04 +00001047 _commands = commands if commands is not None else self.commands
1048 _users = users if users is not None else self.users
1049 _passwds = passwds if passwds is not None else self.passwords
1050 _keys = keys if keys is not None else self.keys
1051 _timeout = timeout if timeout != 0 else self.timeout
gcalvino337ec512018-07-30 10:30:13 +02001052
kuuse587aeea2019-04-26 12:33:07 +02001053 # vnfr_list=[d8272263-6bd3-4680-84ca-6a4be23b3f2d, 88b22e2f-994a-4b61-94fd-4a3c90de3dc4]
gcalvino337ec512018-07-30 10:30:13 +02001054 for vnfr_id in vnfr_list:
tiernoff6485d2018-11-28 17:19:46 +00001055 r = engine.test("Get VNFR to get IP_ADDRESS", "GET",
gcalvino337ec512018-07-30 10:30:13 +02001056 "/nslcm/v1/vnfrs/{}".format(vnfr_id), headers_json, None,
1057 200, r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +00001058 if not r:
1059 continue
gcalvino337ec512018-07-30 10:30:13 +02001060 vnfr_data = r.json()
1061
tiernoff6485d2018-11-28 17:19:46 +00001062 vnf_index = str(vnfr_data["member-vnf-index-ref"])
kuuse587aeea2019-04-26 12:33:07 +02001063
1064 ip_address = self.get_vnfr_ip(engine, vnf_index)
1065 description = "Exec command='{}' at VNFR={} IP={}".format(_commands.get(vnf_index)[0], vnf_index,
1066 ip_address)
1067 engine.step += 1
1068 test_description = "{}{} {}".format(engine.test_name, engine.step, description)
1069 logger.warning(test_description)
1070 while _timeout >= time:
1071 result, message = self.do_checks([ip_address],
1072 vnf_index=vnfr_data["member-vnf-index-ref"],
1073 commands=_commands.get(vnf_index), user=_users.get(vnf_index),
1074 passwd=_passwds.get(vnf_index), key=_keys.get(vnf_index))
1075 if result == 1:
1076 engine.passed_tests += 1
1077 logger.debug(message)
1078 break
1079 elif result == 0:
1080 time += 20
1081 sleep(20)
1082 elif result == -1:
1083 engine.failed_tests += 1
1084 logger.error(message)
1085 break
gcalvino337ec512018-07-30 10:30:13 +02001086 else:
1087 time -= 20
tiernoff6485d2018-11-28 17:19:46 +00001088 engine.failed_tests += 1
1089 logger.error(message)
gcalvino337ec512018-07-30 10:30:13 +02001090 else:
tiernoff6485d2018-11-28 17:19:46 +00001091 engine.failed_tests += 1
kuuse587aeea2019-04-26 12:33:07 +02001092 logger.error("VNFR {} has not mgmt address. Check failed".format(vnf_index))
gcalvino337ec512018-07-30 10:30:13 +02001093
1094 def do_checks(self, ip, vnf_index, commands=[], user=None, passwd=None, key=None):
1095 try:
1096 import urllib3
1097 from pssh.clients import ParallelSSHClient
1098 from pssh.utils import load_private_key
1099 from ssh2 import exceptions as ssh2Exception
1100 except ImportError as e:
tierno36ec8602018-11-02 17:27:11 +01001101 logger.critical("Package <pssh> or/and <urllib3> is not installed. Please add them with 'pip3 install "
1102 "parallel-ssh urllib3': {}".format(e))
tiernoff6485d2018-11-28 17:19:46 +00001103 return -1, "install needed packages 'pip3 install parallel-ssh urllib3'"
gcalvino337ec512018-07-30 10:30:13 +02001104 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
1105 try:
1106 p_host = os.environ.get("PROXY_HOST")
1107 p_user = os.environ.get("PROXY_USER")
1108 p_password = os.environ.get("PROXY_PASSWD")
1109
1110 if key:
1111 pkey = load_private_key(key)
1112 else:
1113 pkey = None
1114
1115 client = ParallelSSHClient(ip, user=user, password=passwd, pkey=pkey, proxy_host=p_host,
1116 proxy_user=p_user, proxy_password=p_password, timeout=10, num_retries=0)
1117 for cmd in commands:
1118 output = client.run_command(cmd)
1119 client.join(output)
1120 if output[ip[0]].exit_code:
tiernobee085c2018-12-12 17:03:04 +00001121 return -1, "VNFR {} command '{}' returns error: '{}'".format(ip[0], cmd,
1122 "\n".join(output[ip[0]].stderr))
gcalvino337ec512018-07-30 10:30:13 +02001123 else:
tiernobee085c2018-12-12 17:03:04 +00001124 return 1, "VNFR {} command '{}' successful".format(ip[0], cmd)
gcalvino337ec512018-07-30 10:30:13 +02001125 except (ssh2Exception.ChannelFailure, ssh2Exception.SocketDisconnectError, ssh2Exception.SocketTimeout,
1126 ssh2Exception.SocketRecvError) as e:
1127 return 0, "Timeout accessing the VNFR {}: {}".format(ip[0], str(e))
1128 except Exception as e:
1129 return -1, "ERROR checking the VNFR {}: {}".format(ip[0], str(e))
tiernoc32ba4a2018-05-24 18:06:41 +02001130
tiernobee085c2018-12-12 17:03:04 +00001131 def additional_operations(self, engine, test_osm, manual_check):
tiernoc32ba4a2018-05-24 18:06:41 +02001132 pass
1133
1134 def run(self, engine, test_osm, manual_check, test_params=None):
tiernoff6485d2018-11-28 17:19:46 +00001135 engine.set_test_name(self.test_name)
tiernoc32ba4a2018-05-24 18:06:41 +02001136 engine.get_autorization()
1137 nsname = os.environ.get("OSMNBITEST_NS_NAME", "OSMNBITEST")
1138 if test_params:
1139 if "vnfd-files" in test_params:
1140 self.vnfd_filenames = test_params["vnfd-files"].split(",")
1141 if "nsd-file" in test_params:
1142 self.nsd_filename = test_params["nsd-file"]
1143 if test_params.get("ns-name"):
1144 nsname = test_params["ns-name"]
1145 self.create_descriptors(engine)
1146
1147 # create real VIM if not exist
1148 self.vim_id = engine.get_create_vim(test_osm)
1149 ns_data = {"nsDescription": "default description", "nsName": nsname, "nsdId": self.nsd_id,
1150 "vimAccountId": self.vim_id}
tiernobee085c2018-12-12 17:03:04 +00001151 if self.ns_params:
1152 ns_data.update(self.ns_params)
tiernoc32ba4a2018-05-24 18:06:41 +02001153 if test_params and test_params.get("ns-config"):
1154 if isinstance(test_params["ns-config"], str):
1155 ns_data.update(yaml.load(test_params["ns-config"]))
1156 else:
1157 ns_data.update(test_params["ns-config"])
1158 self.instantiate(engine, ns_data)
1159
1160 if manual_check:
1161 input('NS has been deployed. Perform manual check and press enter to resume')
tiernobee085c2018-12-12 17:03:04 +00001162 if test_osm and self.commands:
1163 self.test_ns(engine, test_osm)
1164 self.additional_operations(engine, test_osm, manual_check)
tiernoc32ba4a2018-05-24 18:06:41 +02001165 self.terminate(engine)
1166 self.delete_descriptors(engine)
1167
kuuse587aeea2019-04-26 12:33:07 +02001168 def get_first_ip(self, ip_string):
1169 # When using a floating IP, the vnfr_data['ip-address'] contains a semicolon-separated list of IP:s.
1170 first_ip = ip_string.split(";")[0] if ip_string else ""
1171 return first_ip
1172
1173 def get_vnfr_ip(self, engine, vnfr_index_wanted):
1174 # If the IP address list has been obtained before, it has been stored in 'vnfr_ip_list'
1175 ip = self.vnfr_ip_list.get(vnfr_index_wanted, "")
1176 if (ip):
1177 return self.get_first_ip(ip)
1178 r = engine.test("Get VNFR to get IP_ADDRESS", "GET",
1179 "/nslcm/v1/vnfrs?member-vnf-index-ref={}&nsr-id-ref={}".format(
1180 vnfr_index_wanted, self.ns_id), headers_json, None,
1181 200, r_header_json, "json")
1182 if not r:
1183 return ""
1184 vnfr_data = r.json()
1185 if not (vnfr_data and vnfr_data[0]):
1186 return ""
1187 # Store the IP (or list of IPs) in 'vnfr_ip_list'
1188 ip_list = vnfr_data[0].get("ip-address", "")
1189 if ip_list:
1190 self.vnfr_ip_list[vnfr_index_wanted] = ip_list
1191 ip = self.get_first_ip(ip_list)
1192 return ip
1193
tiernoc32ba4a2018-05-24 18:06:41 +02001194
1195class TestDeployHackfestCirros(TestDeploy):
1196 description = "Load and deploy Hackfest cirros_2vnf_ns example"
1197
1198 def __init__(self):
1199 super().__init__()
tiernoff6485d2018-11-28 17:19:46 +00001200 self.test_name = "CIRROS"
tiernoc32ba4a2018-05-24 18:06:41 +02001201 self.vnfd_filenames = ("cirros_vnf.tar.gz",)
1202 self.nsd_filename = "cirros_2vnf_ns.tar.gz"
tiernobee085c2018-12-12 17:03:04 +00001203 self.commands = {'1': ['ls -lrt', ], '2': ['ls -lrt', ]}
1204 self.users = {'1': "cirros", '2': "cirros"}
1205 self.passwords = {'1': "cubswin:)", '2': "cubswin:)"}
tiernoc32ba4a2018-05-24 18:06:41 +02001206
tierno932499c2019-01-28 17:28:10 +00001207 def terminate(self, engine):
1208 # Make a delete in one step, overriding the normal two step of TestDeploy that launched terminate and delete
1209 if test_osm:
1210 engine.test("Terminate and delete NS in one step", "DELETE", "/nslcm/v1/ns_instances_content/{}".
1211 format(self.ns_id), headers_yaml, None, 202, None, "yaml")
1212
1213 engine .wait_until_delete("/nslcm/v1/ns_instances/{}".format(self.ns_id), timeout_deploy)
1214 else:
1215 engine.test("Delete NS with FORCE", "DELETE", "/nslcm/v1/ns_instances/{}?FORCE=True".format(self.ns_id),
1216 headers_yaml, None, 204, None, 0)
1217
1218 # check all it is deleted
1219 engine.test("Check NS is deleted", "GET", "/nslcm/v1/ns_instances/{}".format(self.ns_id), headers_yaml, None,
1220 404, None, "yaml")
1221 r = engine.test("Check NSLCMOPs are deleted", "GET",
1222 "/nslcm/v1/ns_lcm_op_occs?nsInstanceId={}".format(self.ns_id), headers_json, None,
1223 200, None, "json")
1224 if not r:
1225 return
1226 nslcmops = r.json()
1227 if not isinstance(nslcmops, list) or nslcmops:
1228 raise TestException("NS {} deleted but with ns_lcm_op_occ active: {}".format(self.ns_id, nslcmops))
1229
tiernoc32ba4a2018-05-24 18:06:41 +02001230
tiernocc103432018-10-19 14:10:35 +02001231class TestDeployHackfest1(TestDeploy):
1232 description = "Load and deploy Hackfest_1_vnfd example"
1233
1234 def __init__(self):
1235 super().__init__()
tiernoff6485d2018-11-28 17:19:46 +00001236 self.test_name = "HACKFEST1-"
tiernocc103432018-10-19 14:10:35 +02001237 self.vnfd_filenames = ("hackfest_1_vnfd.tar.gz",)
1238 self.nsd_filename = "hackfest_1_nsd.tar.gz"
tiernobee085c2018-12-12 17:03:04 +00001239 # self.commands = {'1': ['ls -lrt', ], '2': ['ls -lrt', ]}
1240 # self.users = {'1': "cirros", '2': "cirros"}
1241 # self.passwords = {'1': "cubswin:)", '2': "cubswin:)"}
tiernocc103432018-10-19 14:10:35 +02001242
1243
1244class TestDeployHackfestCirrosScaling(TestDeploy):
1245 description = "Load and deploy Hackfest cirros_2vnf_ns example with scaling modifications"
1246
1247 def __init__(self):
1248 super().__init__()
tiernoff6485d2018-11-28 17:19:46 +00001249 self.test_name = "CIRROS-SCALE"
tiernocc103432018-10-19 14:10:35 +02001250 self.vnfd_filenames = ("cirros_vnf.tar.gz",)
1251 self.nsd_filename = "cirros_2vnf_ns.tar.gz"
1252
1253 def create_descriptors(self, engine):
1254 super().create_descriptors(engine)
1255 # Modify VNFD to add scaling and count=2
tiernoff6485d2018-11-28 17:19:46 +00001256 self.descriptor_edit = {
1257 "vnfd0": {
1258 "vdu": {
1259 "$id: 'cirros_vnfd-VM'": {"count": 2}
1260 },
1261 "scaling-group-descriptor": [{
1262 "name": "scale_cirros",
1263 "max-instance-count": 2,
1264 "vdu": [{
1265 "vdu-id-ref": "cirros_vnfd-VM",
1266 "count": 2
1267 }]
1268 }]
1269 }
1270 }
tiernocc103432018-10-19 14:10:35 +02001271
tiernobee085c2018-12-12 17:03:04 +00001272 def additional_operations(self, engine, test_osm, manual_check):
tiernocc103432018-10-19 14:10:35 +02001273 if not test_osm:
1274 return
1275 # 2 perform scale out twice
1276 payload = '{scaleType: SCALE_VNF, scaleVnfData: {scaleVnfType: SCALE_OUT, scaleByStepData: ' \
1277 '{scaling-group-descriptor: scale_cirros, member-vnf-index: "1"}}}'
1278 for i in range(0, 2):
tiernoff6485d2018-11-28 17:19:46 +00001279 engine.test("Execute scale action over NS", "POST",
1280 "/nslcm/v1/ns_instances/{}/scale".format(self.ns_id), headers_yaml, payload,
tiernof717cbe2018-12-03 16:35:42 +00001281 201, r_headers_yaml_location_nslcmop, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001282 nslcmop2_scale_out = engine.last_id
1283 engine.wait_operation_ready("ns", nslcmop2_scale_out, timeout_deploy)
tiernocc103432018-10-19 14:10:35 +02001284 if manual_check:
1285 input('NS scale out done. Check that two more vdus are there')
1286 # TODO check automatic
1287
1288 # 2 perform scale in
1289 payload = '{scaleType: SCALE_VNF, scaleVnfData: {scaleVnfType: SCALE_IN, scaleByStepData: ' \
1290 '{scaling-group-descriptor: scale_cirros, member-vnf-index: "1"}}}'
1291 for i in range(0, 2):
tiernoff6485d2018-11-28 17:19:46 +00001292 engine.test("Execute scale IN action over NS", "POST",
1293 "/nslcm/v1/ns_instances/{}/scale".format(self.ns_id), headers_yaml, payload,
tiernof717cbe2018-12-03 16:35:42 +00001294 201, r_headers_yaml_location_nslcmop, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001295 nslcmop2_scale_in = engine.last_id
1296 engine.wait_operation_ready("ns", nslcmop2_scale_in, timeout_deploy)
tiernocc103432018-10-19 14:10:35 +02001297 if manual_check:
1298 input('NS scale in done. Check that two less vdus are there')
1299 # TODO check automatic
1300
1301 # perform scale in that must fail as reached limit
tiernoff6485d2018-11-28 17:19:46 +00001302 engine.test("Execute scale IN out of limit action over NS", "POST",
1303 "/nslcm/v1/ns_instances/{}/scale".format(self.ns_id), headers_yaml, payload,
tiernof717cbe2018-12-03 16:35:42 +00001304 201, r_headers_yaml_location_nslcmop, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001305 nslcmop2_scale_in = engine.last_id
1306 engine.wait_operation_ready("ns", nslcmop2_scale_in, timeout_deploy, expected_fail=True)
tiernocc103432018-10-19 14:10:35 +02001307
1308
tiernoc32ba4a2018-05-24 18:06:41 +02001309class TestDeployIpMac(TestDeploy):
1310 description = "Load and deploy descriptor examples setting mac, ip address at descriptor and instantiate params"
1311
1312 def __init__(self):
1313 super().__init__()
tiernoff6485d2018-11-28 17:19:46 +00001314 self.test_name = "SetIpMac"
tiernoc32ba4a2018-05-24 18:06:41 +02001315 self.vnfd_filenames = ("vnfd_2vdu_set_ip_mac2.yaml", "vnfd_2vdu_set_ip_mac.yaml")
1316 self.nsd_filename = "scenario_2vdu_set_ip_mac.yaml"
1317 self.descriptor_url = \
1318 "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 +00001319 self.commands = {'1': ['ls -lrt', ], '2': ['ls -lrt', ]}
1320 self.users = {'1': "osm", '2': "osm"}
1321 self.passwords = {'1': "osm4u", '2': "osm4u"}
gcalvino337ec512018-07-30 10:30:13 +02001322 self.timeout = 360
tiernoc32ba4a2018-05-24 18:06:41 +02001323
1324 def run(self, engine, test_osm, manual_check, test_params=None):
1325 # super().run(engine, test_osm, manual_check, test_params)
1326 # run again setting IPs with instantiate parameters
1327 instantiation_params = {
1328 "vnf": [
1329 {
1330 "member-vnf-index": "1",
1331 "internal-vld": [
1332 {
1333 "name": "internal_vld1", # net_internal
1334 "ip-profile": {
1335 "ip-version": "ipv4",
1336 "subnet-address": "10.9.8.0/24",
1337 "dhcp-params": {"count": 100, "start-address": "10.9.8.100"}
1338 },
1339 "internal-connection-point": [
1340 {
1341 "id-ref": "eth2",
1342 "ip-address": "10.9.8.2",
1343 },
1344 {
1345 "id-ref": "eth3",
1346 "ip-address": "10.9.8.3",
1347 }
1348 ]
1349 },
1350 ],
1351
1352 "vdu": [
1353 {
1354 "id": "VM1",
1355 "interface": [
tierno7ce1db92018-07-25 12:50:52 +02001356 # {
1357 # "name": "iface11",
1358 # "floating-ip-required": True,
1359 # },
tiernoc32ba4a2018-05-24 18:06:41 +02001360 {
1361 "name": "iface13",
1362 "mac-address": "52:33:44:55:66:13"
1363 },
1364 ],
1365 },
1366 {
1367 "id": "VM2",
1368 "interface": [
1369 {
1370 "name": "iface21",
gcalvino337ec512018-07-30 10:30:13 +02001371 "ip-address": "10.31.31.22",
tiernoc32ba4a2018-05-24 18:06:41 +02001372 "mac-address": "52:33:44:55:66:21"
1373 },
1374 ],
1375 },
1376 ]
1377 },
1378 ]
1379 }
gcalvino337ec512018-07-30 10:30:13 +02001380
tiernoc32ba4a2018-05-24 18:06:41 +02001381 super().run(engine, test_osm, manual_check, test_params={"ns-config": instantiation_params})
1382
1383
1384class TestDeployHackfest4(TestDeploy):
1385 description = "Load and deploy Hackfest 4 example."
1386
1387 def __init__(self):
1388 super().__init__()
tiernoff6485d2018-11-28 17:19:46 +00001389 self.test_name = "HACKFEST4-"
tiernoc32ba4a2018-05-24 18:06:41 +02001390 self.vnfd_filenames = ("hackfest_4_vnfd.tar.gz",)
1391 self.nsd_filename = "hackfest_4_nsd.tar.gz"
1392 self.uses_configuration = True
tiernobee085c2018-12-12 17:03:04 +00001393 self.commands = {'1': ['ls -lrt', ], '2': ['ls -lrt', ]}
1394 self.users = {'1': "ubuntu", '2': "ubuntu"}
1395 self.passwords = {'1': "osm4u", '2': "osm4u"}
tiernoc32ba4a2018-05-24 18:06:41 +02001396 # Modify VNFD to add scaling
tierno932499c2019-01-28 17:28:10 +00001397 # self.descriptor_edit = {
1398 # "vnfd0": {
1399 # 'vnf-configuration': {
1400 # 'config-primitive': [{
1401 # 'name': 'touch',
1402 # 'parameter': [{
1403 # 'name': 'filename',
1404 # 'data-type': 'STRING',
1405 # 'default-value': '/home/ubuntu/touched'
1406 # }]
1407 # }]
1408 # },
1409 # 'scaling-group-descriptor': [{
1410 # 'name': 'scale_dataVM',
1411 # 'scaling-policy': [{
1412 # 'threshold-time': 0,
1413 # 'name': 'auto_cpu_util_above_threshold',
1414 # 'scaling-type': 'automatic',
1415 # 'scaling-criteria': [{
1416 # 'name': 'cpu_util_above_threshold',
1417 # 'vnf-monitoring-param-ref': 'all_aaa_cpu_util',
1418 # 'scale-out-relational-operation': 'GE',
1419 # 'scale-in-threshold': 15,
1420 # 'scale-out-threshold': 60,
1421 # 'scale-in-relational-operation': 'LE'
1422 # }],
1423 # 'cooldown-time': 60
1424 # }],
1425 # 'max-instance-count': 10,
1426 # 'scaling-config-action': [
1427 # {'vnf-config-primitive-name-ref': 'touch',
1428 # 'trigger': 'post-scale-out'},
1429 # {'vnf-config-primitive-name-ref': 'touch',
1430 # 'trigger': 'pre-scale-in'}
1431 # ],
1432 # 'vdu': [{
1433 # 'vdu-id-ref': 'dataVM',
1434 # 'count': 1
1435 # }]
1436 # }]
1437 # }
1438 # }
tiernoc32ba4a2018-05-24 18:06:41 +02001439
tiernoc32ba4a2018-05-24 18:06:41 +02001440
1441class TestDeployHackfest3Charmed(TestDeploy):
tiernobee085c2018-12-12 17:03:04 +00001442 description = "Load and deploy Hackfest 3charmed_ns example"
tiernoc32ba4a2018-05-24 18:06:41 +02001443
1444 def __init__(self):
1445 super().__init__()
tiernoff6485d2018-11-28 17:19:46 +00001446 self.test_name = "HACKFEST3-"
tiernoc32ba4a2018-05-24 18:06:41 +02001447 self.vnfd_filenames = ("hackfest_3charmed_vnfd.tar.gz",)
1448 self.nsd_filename = "hackfest_3charmed_nsd.tar.gz"
1449 self.uses_configuration = True
tiernobee085c2018-12-12 17:03:04 +00001450 self.commands = {'1': ['ls -lrt /home/ubuntu/first-touch'], '2': ['ls -lrt /home/ubuntu/first-touch']}
1451 self.users = {'1': "ubuntu", '2': "ubuntu"}
1452 self.passwords = {'1': "osm4u", '2': "osm4u"}
kuuse587aeea2019-04-26 12:33:07 +02001453 self.descriptor_edit = {
tierno65ca36d2019-02-12 19:27:52 +01001454 "vnfd0": yaml.safe_load(
kuuse587aeea2019-04-26 12:33:07 +02001455 """
1456 vnf-configuration:
1457 terminate-config-primitive:
1458 - seq: '1'
1459 name: touch
1460 parameter:
1461 - name: filename
1462 value: '/home/ubuntu/last-touch1'
1463 - seq: '3'
1464 name: touch
1465 parameter:
1466 - name: filename
1467 value: '/home/ubuntu/last-touch3'
1468 - seq: '2'
1469 name: touch
1470 parameter:
1471 - name: filename
1472 value: '/home/ubuntu/last-touch2'
1473 """)
1474 }
tiernoc32ba4a2018-05-24 18:06:41 +02001475
tiernobee085c2018-12-12 17:03:04 +00001476 def additional_operations(self, engine, test_osm, manual_check):
tiernoc32ba4a2018-05-24 18:06:41 +02001477 if not test_osm:
1478 return
1479 # 1 perform action
kuuse587aeea2019-04-26 12:33:07 +02001480 vnfr_index_selected = "2"
tiernoc32ba4a2018-05-24 18:06:41 +02001481 payload = '{member_vnf_index: "2", primitive: touch, primitive_params: { filename: /home/ubuntu/OSMTESTNBI }}'
tiernoff6485d2018-11-28 17:19:46 +00001482 engine.test("Exec service primitive over NS", "POST",
1483 "/nslcm/v1/ns_instances/{}/action".format(self.ns_id), headers_yaml, payload,
tiernof717cbe2018-12-03 16:35:42 +00001484 201, r_headers_yaml_location_nslcmop, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001485 nslcmop2_action = engine.last_id
tiernoc32ba4a2018-05-24 18:06:41 +02001486 # Wait until status is Ok
tiernoff6485d2018-11-28 17:19:46 +00001487 engine.wait_operation_ready("ns", nslcmop2_action, timeout_deploy)
kuuse587aeea2019-04-26 12:33:07 +02001488 vnfr_ip = self.get_vnfr_ip(engine, vnfr_index_selected)
tiernoc32ba4a2018-05-24 18:06:41 +02001489 if manual_check:
kuuse587aeea2019-04-26 12:33:07 +02001490 input(
1491 "NS service primitive has been executed."
1492 "Check that file /home/ubuntu/OSMTESTNBI is present at {}".
1493 format(vnfr_ip))
tiernoff6485d2018-11-28 17:19:46 +00001494 if test_osm:
tiernobee085c2018-12-12 17:03:04 +00001495 commands = {'1': [''], '2': ['ls -lrt /home/ubuntu/OSMTESTNBI', ]}
1496 self.test_ns(engine, test_osm, commands=commands)
tiernoc32ba4a2018-05-24 18:06:41 +02001497
1498 # # 2 perform scale out
1499 # payload = '{scaleType: SCALE_VNF, scaleVnfData: {scaleVnfType: SCALE_OUT, scaleByStepData: ' \
1500 # '{scaling-group-descriptor: scale_dataVM, member-vnf-index: "1"}}}'
tiernoff6485d2018-11-28 17:19:46 +00001501 # engine.test("Execute scale action over NS", "POST",
1502 # "/nslcm/v1/ns_instances/{}/scale".format(self.ns_id), headers_yaml, payload,
tiernof717cbe2018-12-03 16:35:42 +00001503 # 201, r_headers_yaml_location_nslcmop, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001504 # nslcmop2_scale_out = engine.last_id
1505 # engine.wait_operation_ready("ns", nslcmop2_scale_out, timeout_deploy)
tiernoc32ba4a2018-05-24 18:06:41 +02001506 # if manual_check:
1507 # input('NS scale out done. Check that file /home/ubuntu/touched is present and new VM is created')
1508 # # TODO check automatic
1509 #
1510 # # 2 perform scale in
1511 # payload = '{scaleType: SCALE_VNF, scaleVnfData: {scaleVnfType: SCALE_IN, scaleByStepData: ' \
1512 # '{scaling-group-descriptor: scale_dataVM, member-vnf-index: "1"}}}'
tiernoff6485d2018-11-28 17:19:46 +00001513 # engine.test("Execute scale action over NS", "POST",
1514 # "/nslcm/v1/ns_instances/{}/scale".format(self.ns_id), headers_yaml, payload,
tiernof717cbe2018-12-03 16:35:42 +00001515 # 201, r_headers_yaml_location_nslcmop, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001516 # nslcmop2_scale_in = engine.last_id
1517 # engine.wait_operation_ready("ns", nslcmop2_scale_in, timeout_deploy)
tiernoc32ba4a2018-05-24 18:06:41 +02001518 # if manual_check:
1519 # input('NS scale in done. Check that file /home/ubuntu/touched is updated and new VM is deleted')
1520 # # TODO check automatic
1521
tiernof27c79b2018-03-12 17:08:42 +01001522
tiernoff6485d2018-11-28 17:19:46 +00001523class TestDeployHackfest3Charmed2(TestDeployHackfest3Charmed):
1524 description = "Load and deploy Hackfest 3charmed_ns example modified version of descriptors to have dots in " \
tiernobee085c2018-12-12 17:03:04 +00001525 "ids and member-vnf-index."
tiernoff6485d2018-11-28 17:19:46 +00001526
1527 def __init__(self):
1528 super().__init__()
tiernobee085c2018-12-12 17:03:04 +00001529 self.test_name = "HACKFEST3v2-"
tiernoff6485d2018-11-28 17:19:46 +00001530 self.qforce = "?FORCE=True"
1531 self.descriptor_edit = {
1532 "vnfd0": {
1533 "vdu": {
1534 "$[0]": {
1535 "interface": {"$[0]": {"external-connection-point-ref": "pdu-mgmt"}}
1536 },
1537 "$[1]": None
1538 },
1539 "vnf-configuration": None,
1540 "connection-point": {
1541 "$[0]": {
1542 "id": "pdu-mgmt",
1543 "name": "pdu-mgmt",
1544 "short-name": "pdu-mgmt"
1545 },
1546 "$[1]": None
1547 },
1548 "mgmt-interface": {"cp": "pdu-mgmt"},
1549 "description": "A vnf single vdu to be used as PDU",
1550 "id": "vdu-as-pdu",
1551 "internal-vld": {
1552 "$[0]": {
1553 "id": "pdu_internal",
1554 "name": "pdu_internal",
1555 "internal-connection-point": {"$[1]": None},
1556 "short-name": "pdu_internal",
1557 "type": "ELAN"
1558 }
1559 }
1560 },
1561
1562 # Modify NSD accordingly
1563 "nsd": {
1564 "constituent-vnfd": {
1565 "$[0]": {"vnfd-id-ref": "vdu-as-pdu"},
1566 "$[1]": None,
1567 },
1568 "description": "A nsd to deploy the vnf to act as as PDU",
1569 "id": "nsd-as-pdu",
1570 "name": "nsd-as-pdu",
1571 "short-name": "nsd-as-pdu",
1572 "vld": {
1573 "$[0]": {
1574 "id": "mgmt_pdu",
1575 "name": "mgmt_pdu",
1576 "short-name": "mgmt_pdu",
1577 "vnfd-connection-point-ref": {
1578 "$[0]": {
1579 "vnfd-connection-point-ref": "pdu-mgmt",
1580 "vnfd-id-ref": "vdu-as-pdu",
1581 },
1582 "$[1]": None
1583 },
1584 "type": "ELAN"
1585 },
1586 "$[1]": None,
1587 }
1588 }
1589 }
1590
1591
tiernobee085c2018-12-12 17:03:04 +00001592class TestDeployHackfest3Charmed3(TestDeployHackfest3Charmed):
1593 description = "Load and deploy Hackfest 3charmed_ns example modified version to test scaling and NS parameters"
1594
1595 def __init__(self):
1596 super().__init__()
1597 self.test_name = "HACKFEST3v3-"
tiernoa1c1b532019-01-16 14:12:22 +00001598 self.commands = {'1': ['ls -lrt /home/ubuntu/first-touch-1'], '2': ['ls -lrt /home/ubuntu/first-touch-2']}
tiernobee085c2018-12-12 17:03:04 +00001599 self.descriptor_edit = {
1600 "vnfd0": yaml.load(
1601 """
1602 scaling-group-descriptor:
1603 - name: "scale_dataVM"
1604 max-instance-count: 10
1605 scaling-policy:
1606 - name: "auto_cpu_util_above_threshold"
1607 scaling-type: "automatic"
1608 threshold-time: 0
1609 cooldown-time: 60
1610 scaling-criteria:
1611 - name: "cpu_util_above_threshold"
1612 scale-in-threshold: 15
1613 scale-in-relational-operation: "LE"
1614 scale-out-threshold: 60
1615 scale-out-relational-operation: "GE"
1616 vnf-monitoring-param-ref: "monitor1"
1617 vdu:
1618 - vdu-id-ref: dataVM
1619 count: 1
1620 scaling-config-action:
1621 - trigger: post-scale-out
1622 vnf-config-primitive-name-ref: touch
1623 - trigger: pre-scale-in
1624 vnf-config-primitive-name-ref: touch
1625 vdu:
1626 "$id: dataVM":
1627 monitoring-param:
1628 - id: "dataVM_cpu_util"
1629 nfvi-metric: "cpu_utilization"
1630
1631 monitoring-param:
1632 - id: "monitor1"
1633 name: "monitor1"
1634 aggregation-type: AVERAGE
1635 vdu-monitoring-param:
1636 vdu-ref: "dataVM"
1637 vdu-monitoring-param-ref: "dataVM_cpu_util"
1638 vnf-configuration:
1639 initial-config-primitive:
1640 "$[1]":
1641 parameter:
1642 "$[0]":
tiernoe4a07d52019-05-16 15:25:37 +00001643 value: "<touch_filename>" # default-value: /home/ubuntu/first-touch
tiernoa1c1b532019-01-16 14:12:22 +00001644 config-primitive:
1645 "$[0]":
1646 parameter:
1647 "$[0]":
tiernoe4a07d52019-05-16 15:25:37 +00001648 default-value: "<touch_filename2>"
tiernobee085c2018-12-12 17:03:04 +00001649 """)
1650 }
1651 self.ns_params = {
1652 "additionalParamsForVnf": [
tiernoe4a07d52019-05-16 15:25:37 +00001653 {"member-vnf-index": "1", "additionalParams": {"touch_filename": "/home/ubuntu/first-touch-1",
1654 "touch_filename2": "/home/ubuntu/second-touch-1"}},
1655 {"member-vnf-index": "2", "additionalParams": {"touch_filename": "/home/ubuntu/first-touch-2",
1656 "touch_filename2": "/home/ubuntu/second-touch-2"}},
tiernobee085c2018-12-12 17:03:04 +00001657 ]
1658 }
1659
1660 def additional_operations(self, engine, test_osm, manual_check):
1661 super().additional_operations(engine, test_osm, manual_check)
1662 if not test_osm:
1663 return
1664
1665 # 2 perform scale out
1666 payload = '{scaleType: SCALE_VNF, scaleVnfData: {scaleVnfType: SCALE_OUT, scaleByStepData: ' \
1667 '{scaling-group-descriptor: scale_dataVM, member-vnf-index: "1"}}}'
1668 engine.test("Execute scale action over NS", "POST",
1669 "/nslcm/v1/ns_instances/{}/scale".format(self.ns_id), headers_yaml, payload,
1670 201, r_headers_yaml_location_nslcmop, "yaml")
1671 nslcmop2_scale_out = engine.last_id
1672 engine.wait_operation_ready("ns", nslcmop2_scale_out, timeout_deploy)
1673 if manual_check:
tiernoa1c1b532019-01-16 14:12:22 +00001674 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 +00001675 if test_osm:
tiernoa1c1b532019-01-16 14:12:22 +00001676 commands = {'1': ['ls -lrt /home/ubuntu/second-touch-1', ]}
tiernobee085c2018-12-12 17:03:04 +00001677 self.test_ns(engine, test_osm, commands=commands)
1678 # TODO check automatic connection to scaled VM
1679
1680 # 2 perform scale in
1681 payload = '{scaleType: SCALE_VNF, scaleVnfData: {scaleVnfType: SCALE_IN, scaleByStepData: ' \
1682 '{scaling-group-descriptor: scale_dataVM, member-vnf-index: "1"}}}'
1683 engine.test("Execute scale action over NS", "POST",
1684 "/nslcm/v1/ns_instances/{}/scale".format(self.ns_id), headers_yaml, payload,
1685 201, r_headers_yaml_location_nslcmop, "yaml")
1686 nslcmop2_scale_in = engine.last_id
1687 engine.wait_operation_ready("ns", nslcmop2_scale_in, timeout_deploy)
1688 if manual_check:
tiernoa1c1b532019-01-16 14:12:22 +00001689 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 +00001690 # TODO check automatic
1691
1692
1693class TestDeploySimpleCharm(TestDeploy):
1694 description = "Deploy hackfest-4 hackfest_simplecharm example"
1695
1696 def __init__(self):
1697 super().__init__()
1698 self.test_name = "HACKFEST-SIMPLE"
1699 self.descriptor_url = "https://osm-download.etsi.org/ftp/osm-4.0-four/4th-hackfest/packages/"
1700 self.vnfd_filenames = ("hackfest_simplecharm_vnf.tar.gz",)
1701 self.nsd_filename = "hackfest_simplecharm_ns.tar.gz"
1702 self.uses_configuration = True
1703 self.commands = {'1': [''], '2': ['ls -lrt /home/ubuntu/first-touch', ]}
1704 self.users = {'1': "ubuntu", '2': "ubuntu"}
1705 self.passwords = {'1': "osm4u", '2': "osm4u"}
1706
1707
1708class TestDeploySimpleCharm2(TestDeploySimpleCharm):
1709 description = "Deploy hackfest-4 hackfest_simplecharm example changing naming to contain dots on ids and " \
1710 "vnf-member-index"
1711
1712 def __init__(self):
1713 super().__init__()
1714 self.test_name = "HACKFEST-SIMPLE2-"
1715 self.qforce = "?FORCE=True"
1716 self.descriptor_edit = {
1717 "vnfd0": {
1718 "id": "hackfest.simplecharm.vnf"
1719 },
1720
1721 "nsd": {
1722 "id": "hackfest.simplecharm.ns",
1723 "constituent-vnfd": {
1724 "$[0]": {"vnfd-id-ref": "hackfest.simplecharm.vnf", "member-vnf-index": "$1"},
1725 "$[1]": {"vnfd-id-ref": "hackfest.simplecharm.vnf", "member-vnf-index": "$2"},
1726 },
1727 "vld": {
1728 "$[0]": {
1729 "vnfd-connection-point-ref": {"$[0]": {"member-vnf-index-ref": "$1",
1730 "vnfd-id-ref": "hackfest.simplecharm.vnf"},
1731 "$[1]": {"member-vnf-index-ref": "$2",
1732 "vnfd-id-ref": "hackfest.simplecharm.vnf"}},
1733 },
1734 "$[1]": {
1735 "vnfd-connection-point-ref": {"$[0]": {"member-vnf-index-ref": "$1",
1736 "vnfd-id-ref": "hackfest.simplecharm.vnf"},
1737 "$[1]": {"member-vnf-index-ref": "$2",
1738 "vnfd-id-ref": "hackfest.simplecharm.vnf"}},
1739 },
1740 }
1741 }
1742 }
1743
1744
tierno36ec8602018-11-02 17:27:11 +01001745class TestDeploySingleVdu(TestDeployHackfest3Charmed):
1746 description = "Generate a single VDU base on editing Hackfest3Charmed descriptors and deploy"
1747
1748 def __init__(self):
1749 super().__init__()
tiernoff6485d2018-11-28 17:19:46 +00001750 self.test_name = "SingleVDU"
tierno36ec8602018-11-02 17:27:11 +01001751 self.qforce = "?FORCE=True"
1752 self.descriptor_edit = {
1753 # Modify VNFD to remove one VDU
1754 "vnfd0": {
1755 "vdu": {
1756 "$[0]": {
1757 "interface": {"$[0]": {"external-connection-point-ref": "pdu-mgmt"}}
1758 },
1759 "$[1]": None
1760 },
1761 "vnf-configuration": None,
1762 "connection-point": {
1763 "$[0]": {
1764 "id": "pdu-mgmt",
1765 "name": "pdu-mgmt",
1766 "short-name": "pdu-mgmt"
1767 },
1768 "$[1]": None
1769 },
1770 "mgmt-interface": {"cp": "pdu-mgmt"},
1771 "description": "A vnf single vdu to be used as PDU",
1772 "id": "vdu-as-pdu",
1773 "internal-vld": {
1774 "$[0]": {
1775 "id": "pdu_internal",
1776 "name": "pdu_internal",
1777 "internal-connection-point": {"$[1]": None},
1778 "short-name": "pdu_internal",
1779 "type": "ELAN"
1780 }
1781 }
1782 },
1783
1784 # Modify NSD accordingly
1785 "nsd": {
1786 "constituent-vnfd": {
1787 "$[0]": {"vnfd-id-ref": "vdu-as-pdu"},
1788 "$[1]": None,
1789 },
1790 "description": "A nsd to deploy the vnf to act as as PDU",
1791 "id": "nsd-as-pdu",
1792 "name": "nsd-as-pdu",
1793 "short-name": "nsd-as-pdu",
1794 "vld": {
1795 "$[0]": {
1796 "id": "mgmt_pdu",
1797 "name": "mgmt_pdu",
1798 "short-name": "mgmt_pdu",
1799 "vnfd-connection-point-ref": {
1800 "$[0]": {
1801 "vnfd-connection-point-ref": "pdu-mgmt",
1802 "vnfd-id-ref": "vdu-as-pdu",
1803 },
1804 "$[1]": None
1805 },
1806 "type": "ELAN"
1807 },
1808 "$[1]": None,
1809 }
1810 }
1811 }
1812
1813
1814class TestDeployHnfd(TestDeployHackfest3Charmed):
1815 description = "Generate a HNFD base on editing Hackfest3Charmed descriptors and deploy"
1816
1817 def __init__(self):
1818 super().__init__()
tiernoff6485d2018-11-28 17:19:46 +00001819 self.test_name = "HNFD"
tierno36ec8602018-11-02 17:27:11 +01001820 self.pduDeploy = TestDeploySingleVdu()
1821 self.pdu_interface_0 = {}
1822 self.pdu_interface_1 = {}
1823
1824 self.pdu_id = None
1825 # self.vnf_to_pdu = """
1826 # vdu:
1827 # "$[0]":
1828 # pdu-type: PDU-TYPE-1
1829 # interface:
1830 # "$[0]":
1831 # name: mgmt-iface
1832 # "$[1]":
1833 # name: pdu-iface-internal
1834 # id: hfn1
1835 # description: HFND, one PDU + One VDU
1836 # name: hfn1
1837 # short-name: hfn1
1838 #
1839 # """
1840
1841 self.pdu_descriptor = {
1842 "name": "my-PDU",
1843 "type": "PDU-TYPE-1",
1844 "vim_accounts": "to-override",
1845 "interfaces": [
1846 {
1847 "name": "mgmt-iface",
1848 "mgmt": True,
1849 "type": "overlay",
1850 "ip-address": "to override",
1851 "mac-address": "mac_address",
1852 "vim-network-name": "mgmt",
1853 },
1854 {
1855 "name": "pdu-iface-internal",
1856 "mgmt": False,
1857 "type": "overlay",
1858 "ip-address": "to override",
1859 "mac-address": "mac_address",
1860 "vim-network-name": "pdu_internal", # OSMNBITEST-PDU-pdu_internal
1861 },
1862 ]
1863 }
1864 self.vnfd_filenames = ("hackfest_3charmed_vnfd.tar.gz", "hackfest_3charmed_vnfd.tar.gz")
1865
1866 self.descriptor_edit = {
1867 "vnfd0": {
1868 "id": "hfnd1",
1869 "name": "hfn1",
1870 "short-name": "hfn1",
1871 "vdu": {
1872 "$[0]": {
1873 "pdu-type": "PDU-TYPE-1",
1874 "interface": {
1875 "$[0]": {"name": "mgmt-iface"},
1876 "$[1]": {"name": "pdu-iface-internal"},
1877 }
1878 }
1879 }
1880 },
1881 "nsd": {
1882 "constituent-vnfd": {
1883 "$[1]": {"vnfd-id-ref": "hfnd1"}
tiernoff6485d2018-11-28 17:19:46 +00001884 },
1885 "vld": {
1886 "$[0]": {"vnfd-connection-point-ref": {"$[1]": {"vnfd-id-ref": "hfnd1"}}},
1887 "$[1]": {"vnfd-connection-point-ref": {"$[1]": {"vnfd-id-ref": "hfnd1"}}}
tierno36ec8602018-11-02 17:27:11 +01001888 }
1889 }
1890 }
1891
1892 def create_descriptors(self, engine):
1893 super().create_descriptors(engine)
1894
1895 # Create PDU
1896 self.pdu_descriptor["interfaces"][0].update(self.pdu_interface_0)
1897 self.pdu_descriptor["interfaces"][1].update(self.pdu_interface_1)
1898 self.pdu_descriptor["vim_accounts"] = [self.vim_id]
1899 # TODO get vim-network-name from vnfr.vld.name
1900 self.pdu_descriptor["interfaces"][1]["vim-network-name"] = "{}-{}-{}".format(
1901 os.environ.get("OSMNBITEST_NS_NAME", "OSMNBITEST"),
1902 "PDU", self.pdu_descriptor["interfaces"][1]["vim-network-name"])
tiernoff6485d2018-11-28 17:19:46 +00001903 engine.test("Onboard PDU descriptor", "POST", "/pdu/v1/pdu_descriptors",
tierno36ec8602018-11-02 17:27:11 +01001904 {"Location": "/pdu/v1/pdu_descriptors/", "Content-Type": "application/yaml"}, self.pdu_descriptor,
1905 201, r_header_yaml, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00001906 self.pdu_id = engine.last_id
tierno36ec8602018-11-02 17:27:11 +01001907
1908 def run(self, engine, test_osm, manual_check, test_params=None):
1909 engine.get_autorization()
tiernoff6485d2018-11-28 17:19:46 +00001910 engine.set_test_name(self.test_name)
tierno36ec8602018-11-02 17:27:11 +01001911 nsname = os.environ.get("OSMNBITEST_NS_NAME", "OSMNBITEST")
1912
1913 # create real VIM if not exist
1914 self.vim_id = engine.get_create_vim(test_osm)
tiernoff6485d2018-11-28 17:19:46 +00001915 # instantiate PDU
tierno36ec8602018-11-02 17:27:11 +01001916 self.pduDeploy.create_descriptors(engine)
1917 self.pduDeploy.instantiate(engine, {"nsDescription": "to be used as PDU", "nsName": nsname + "-PDU",
1918 "nsdId": self.pduDeploy.nsd_id, "vimAccountId": self.vim_id})
1919 if manual_check:
1920 input('VNF to be used as PDU has been deployed. Perform manual check and press enter to resume')
tiernoff6485d2018-11-28 17:19:46 +00001921 if test_osm:
tiernobee085c2018-12-12 17:03:04 +00001922 self.pduDeploy.test_ns(engine, test_osm)
tierno36ec8602018-11-02 17:27:11 +01001923
1924 if test_osm:
tiernoff6485d2018-11-28 17:19:46 +00001925 r = engine.test("Get VNFR to obtain IP_ADDRESS", "GET",
tierno36ec8602018-11-02 17:27:11 +01001926 "/nslcm/v1/vnfrs?nsr-id-ref={}".format(self.pduDeploy.ns_id), headers_json, None,
1927 200, r_header_json, "json")
tiernoff6485d2018-11-28 17:19:46 +00001928 if not r:
1929 return
tierno36ec8602018-11-02 17:27:11 +01001930 vnfr_data = r.json()
1931 # print(vnfr_data)
1932
1933 self.pdu_interface_0["ip-address"] = vnfr_data[0]["vdur"][0]["interfaces"][0].get("ip-address")
1934 self.pdu_interface_1["ip-address"] = vnfr_data[0]["vdur"][0]["interfaces"][1].get("ip-address")
1935 self.pdu_interface_0["mac-address"] = vnfr_data[0]["vdur"][0]["interfaces"][0].get("mac-address")
1936 self.pdu_interface_1["mac-address"] = vnfr_data[0]["vdur"][0]["interfaces"][1].get("mac-address")
1937 if not self.pdu_interface_0["ip-address"]:
1938 raise TestException("Vnfr has not managment ip address")
1939 else:
1940 self.pdu_interface_0["ip-address"] = "192.168.10.10"
1941 self.pdu_interface_1["ip-address"] = "192.168.11.10"
1942 self.pdu_interface_0["mac-address"] = "52:33:44:55:66:13"
1943 self.pdu_interface_1["mac-address"] = "52:33:44:55:66:14"
1944
1945 self.create_descriptors(engine)
1946
1947 ns_data = {"nsDescription": "default description", "nsName": nsname, "nsdId": self.nsd_id,
1948 "vimAccountId": self.vim_id}
1949 if test_params and test_params.get("ns-config"):
1950 if isinstance(test_params["ns-config"], str):
1951 ns_data.update(yaml.load(test_params["ns-config"]))
1952 else:
1953 ns_data.update(test_params["ns-config"])
1954
1955 self.instantiate(engine, ns_data)
1956 if manual_check:
1957 input('NS has been deployed. Perform manual check and press enter to resume')
tiernoff6485d2018-11-28 17:19:46 +00001958 if test_osm:
tiernobee085c2018-12-12 17:03:04 +00001959 self.test_ns(engine, test_osm)
1960 self.additional_operations(engine, test_osm, manual_check)
tierno36ec8602018-11-02 17:27:11 +01001961 self.terminate(engine)
1962 self.pduDeploy.terminate(engine)
1963 self.delete_descriptors(engine)
1964 self.pduDeploy.delete_descriptors(engine)
1965
tierno36ec8602018-11-02 17:27:11 +01001966 def delete_descriptors(self, engine):
1967 super().delete_descriptors(engine)
1968 # delete pdu
tiernoff6485d2018-11-28 17:19:46 +00001969 engine.test("Delete PDU SOL005", "DELETE",
tierno36ec8602018-11-02 17:27:11 +01001970 "/pdu/v1/pdu_descriptors/{}".format(self.pdu_id),
1971 headers_yaml, None, 204, None, 0)
1972
1973
tierno49e42062018-10-24 12:50:53 +02001974class TestDescriptors:
1975 description = "Test VNFD, NSD, PDU descriptors CRUD and dependencies"
tierno65ca36d2019-02-12 19:27:52 +01001976 vnfd_empty = """vnfd:vnfd-catalog:
1977 vnfd:
1978 - name: prova
1979 short-name: prova
1980 id: prova
1981 """
1982 vnfd_prova = """vnfd:vnfd-catalog:
1983 vnfd:
1984 - connection-point:
1985 - name: cp_0h8m
1986 type: VPORT
1987 id: prova
1988 name: prova
1989 short-name: prova
1990 vdu:
1991 - id: vdu_z4bm
1992 image: ubuntu
1993 interface:
1994 - external-connection-point-ref: cp_0h8m
1995 name: eth0
1996 virtual-interface:
1997 type: VIRTIO
1998 name: vdu_z4bm
1999 version: '1.0'
2000 """
tierno49e42062018-10-24 12:50:53 +02002001
2002 def __init__(self):
tierno49e42062018-10-24 12:50:53 +02002003 self.vnfd_filename = "hackfest_3charmed_vnfd.tar.gz"
2004 self.nsd_filename = "hackfest_3charmed_nsd.tar.gz"
2005 self.descriptor_url = "https://osm-download.etsi.org/ftp/osm-3.0-three/2nd-hackfest/packages/"
2006 self.vnfd_id = None
2007 self.nsd_id = None
2008
2009 def run(self, engine, test_osm, manual_check, test_params=None):
tiernoff6485d2018-11-28 17:19:46 +00002010 engine.set_test_name("Descriptors")
tierno49e42062018-10-24 12:50:53 +02002011 engine.get_autorization()
2012 temp_dir = os.path.dirname(os.path.abspath(__file__)) + "/temp/"
2013 if not os.path.exists(temp_dir):
2014 os.makedirs(temp_dir)
2015
2016 # download files
2017 for filename in (self.vnfd_filename, self.nsd_filename):
2018 filename_path = temp_dir + filename
2019 if not os.path.exists(filename_path):
2020 with open(filename_path, "wb") as file:
2021 response = requests.get(self.descriptor_url + filename)
2022 if response.status_code >= 300:
2023 raise TestException("Error downloading descriptor from '{}': {}".format(
2024 self.descriptor_url + filename, response.status_code))
2025 file.write(response.content)
2026
2027 vnfd_filename_path = temp_dir + self.vnfd_filename
2028 nsd_filename_path = temp_dir + self.nsd_filename
2029
tiernof717cbe2018-12-03 16:35:42 +00002030 engine.test("Onboard empty VNFD in one step", "POST", "/vnfpkgm/v1/vnf_packages_content", headers_yaml,
2031 self.vnfd_empty, 201, r_headers_yaml_location_vnfd, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00002032 self.vnfd_id = engine.last_id
tierno49e42062018-10-24 12:50:53 +02002033
tiernof717cbe2018-12-03 16:35:42 +00002034 # test bug 605
2035 engine.test("Upload invalid VNFD ", "PUT", "/vnfpkgm/v1/vnf_packages/{}/package_content".format(self.vnfd_id),
2036 headers_yaml, self.vnfd_prova, 422, r_header_yaml, "yaml")
2037
2038 engine.test("Upload VNFD {}".format(self.vnfd_filename), "PUT",
2039 "/vnfpkgm/v1/vnf_packages/{}/package_content".format(self.vnfd_id), headers_zip_yaml,
2040 "@b" + vnfd_filename_path, 204, None, 0)
2041
gcalvino95f94c22019-01-10 13:03:30 +01002042 queries = ["mgmt-interface.cp=mgmt", "vdu.0.interface.0.external-connection-point-ref=mgmt",
2043 "vdu.0.interface.1.internal-connection-point-ref=internal",
delacruzramo6902c912019-03-29 12:39:35 +01002044 "internal-vld.0.internal-connection-point.0.id-ref=internal",
2045 # Detection of duplicated VLD names in VNF Descriptors
2046 # URL: internal-vld=[
2047 # {id: internal1, name: internal, type:ELAN,
2048 # internal-connection-point: [{id-ref: mgmtVM-internal}, {id-ref: dataVM-internal}]},
2049 # {id: internal2, name: internal, type:ELAN,
2050 # internal-connection-point: [{id-ref: mgmtVM-internal}, {id-ref: dataVM-internal}]}
2051 # ]
2052 "internal-vld=%5B%7Bid%3A%20internal1%2C%20name%3A%20internal%2C%20type%3A%20ELAN%2C%20"
2053 "internal-connection-point%3A%20%5B%7Bid-ref%3A%20mgmtVM-internal%7D%2C%20%7Bid-ref%3A%20"
2054 "dataVM-internal%7D%5D%7D%2C%20%7Bid%3A%20internal2%2C%20name%3A%20internal%2C%20type%3A%20"
2055 "ELAN%2C%20internal-connection-point%3A%20%5B%7Bid-ref%3A%20mgmtVM-internal%7D%2C%20%7B"
2056 "id-ref%3A%20dataVM-internal%7D%5D%7D%5D"
2057 ]
gcalvino95f94c22019-01-10 13:03:30 +01002058 for query in queries:
2059 engine.test("Upload invalid VNFD ", "PUT",
2060 "/vnfpkgm/v1/vnf_packages/{}/package_content?{}".format(self.vnfd_id, query),
2061 headers_zip_yaml, "@b" + vnfd_filename_path, 422, r_header_yaml, "yaml")
2062
tiernof717cbe2018-12-03 16:35:42 +00002063 # test bug 605
2064 engine.test("Upload invalid VNFD ", "PUT", "/vnfpkgm/v1/vnf_packages/{}/package_content".format(self.vnfd_id),
2065 headers_yaml, self.vnfd_prova, 422, r_header_yaml, "yaml")
2066
tierno49e42062018-10-24 12:50:53 +02002067 # get vnfd descriptor
tiernof717cbe2018-12-03 16:35:42 +00002068 engine.test("Get VNFD descriptor", "GET", "/vnfpkgm/v1/vnf_packages/{}".format(self.vnfd_id),
2069 headers_yaml, None, 200, r_header_yaml, "yaml")
tierno49e42062018-10-24 12:50:53 +02002070
2071 # get vnfd file descriptor
tiernof717cbe2018-12-03 16:35:42 +00002072 engine.test("Get VNFD file descriptor", "GET", "/vnfpkgm/v1/vnf_packages/{}/vnfd".format(self.vnfd_id),
2073 headers_text, None, 200, r_header_text, "text", temp_dir+"vnfd-yaml")
tierno49e42062018-10-24 12:50:53 +02002074 # TODO compare files: diff vnfd-yaml hackfest_3charmed_vnfd/hackfest_3charmed_vnfd.yaml
2075
2076 # get vnfd zip file package
tiernoff6485d2018-11-28 17:19:46 +00002077 engine.test("Get VNFD zip package", "GET",
tierno49e42062018-10-24 12:50:53 +02002078 "/vnfpkgm/v1/vnf_packages/{}/package_content".format(self.vnfd_id), headers_zip, None, 200,
2079 r_header_zip, "zip", temp_dir+"vnfd-zip")
tierno49e42062018-10-24 12:50:53 +02002080 # TODO compare files: diff vnfd-zip hackfest_3charmed_vnfd.tar.gz
2081
2082 # get vnfd artifact
tiernoff6485d2018-11-28 17:19:46 +00002083 engine.test("Get VNFD artifact package", "GET",
tierno49e42062018-10-24 12:50:53 +02002084 "/vnfpkgm/v1/vnf_packages/{}/artifacts/icons/osm.png".format(self.vnfd_id), headers_zip, None, 200,
2085 r_header_octect, "octet-string", temp_dir+"vnfd-icon")
tierno49e42062018-10-24 12:50:53 +02002086 # TODO compare files: diff vnfd-icon hackfest_3charmed_vnfd/icons/osm.png
2087
2088 # nsd CREATE AND UPLOAD in one step:
tiernof717cbe2018-12-03 16:35:42 +00002089 engine.test("Onboard NSD in one step", "POST", "/nsd/v1/ns_descriptors_content", headers_zip_yaml,
2090 "@b" + nsd_filename_path, 201, r_headers_yaml_location_nsd, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00002091 self.nsd_id = engine.last_id
tierno49e42062018-10-24 12:50:53 +02002092
gcalvino95f94c22019-01-10 13:03:30 +01002093 queries = ["vld.0.vnfd-connection-point-ref.0.vnfd-id-ref=hf"]
2094 for query in queries:
2095 engine.test("Upload invalid NSD ", "PUT",
2096 "/nsd/v1/ns_descriptors/{}/nsd_content?{}".format(self.nsd_id, query),
2097 headers_zip_yaml, "@b" + nsd_filename_path, 422, r_header_yaml, "yaml")
2098
tierno49e42062018-10-24 12:50:53 +02002099 # get nsd descriptor
tiernof717cbe2018-12-03 16:35:42 +00002100 engine.test("Get NSD descriptor", "GET", "/nsd/v1/ns_descriptors/{}".format(self.nsd_id), headers_yaml,
2101 None, 200, r_header_yaml, "yaml")
tierno49e42062018-10-24 12:50:53 +02002102
2103 # get nsd file descriptor
tiernof717cbe2018-12-03 16:35:42 +00002104 engine.test("Get NSD file descriptor", "GET", "/nsd/v1/ns_descriptors/{}/nsd".format(self.nsd_id), headers_text,
2105 None, 200, r_header_text, "text", temp_dir+"nsd-yaml")
tierno49e42062018-10-24 12:50:53 +02002106 # TODO compare files: diff nsd-yaml hackfest_3charmed_nsd/hackfest_3charmed_nsd.yaml
2107
2108 # get nsd zip file package
tiernof717cbe2018-12-03 16:35:42 +00002109 engine.test("Get NSD zip package", "GET", "/nsd/v1/ns_descriptors/{}/nsd_content".format(self.nsd_id),
2110 headers_zip, None, 200, r_header_zip, "zip", temp_dir+"nsd-zip")
tierno49e42062018-10-24 12:50:53 +02002111 # TODO compare files: diff nsd-zip hackfest_3charmed_nsd.tar.gz
2112
2113 # get nsd artifact
tiernoff6485d2018-11-28 17:19:46 +00002114 engine.test("Get NSD artifact package", "GET",
tierno49e42062018-10-24 12:50:53 +02002115 "/nsd/v1/ns_descriptors/{}/artifacts/icons/osm.png".format(self.nsd_id), headers_zip, None, 200,
2116 r_header_octect, "octet-string", temp_dir+"nsd-icon")
tierno49e42062018-10-24 12:50:53 +02002117 # TODO compare files: diff nsd-icon hackfest_3charmed_nsd/icons/osm.png
2118
2119 # vnfd DELETE
tiernof717cbe2018-12-03 16:35:42 +00002120 test_rest.test("Delete VNFD conflict", "DELETE", "/vnfpkgm/v1/vnf_packages/{}".format(self.vnfd_id),
2121 headers_yaml, None, 409, None, None)
tierno49e42062018-10-24 12:50:53 +02002122
tiernof717cbe2018-12-03 16:35:42 +00002123 test_rest.test("Delete VNFD force", "DELETE", "/vnfpkgm/v1/vnf_packages/{}?FORCE=TRUE".format(self.vnfd_id),
2124 headers_yaml, None, 204, None, 0)
tierno49e42062018-10-24 12:50:53 +02002125
2126 # nsd DELETE
tiernof717cbe2018-12-03 16:35:42 +00002127 test_rest.test("Delete NSD", "DELETE", "/nsd/v1/ns_descriptors/{}".format(self.nsd_id), headers_yaml, None, 204,
2128 None, 0)
tierno49e42062018-10-24 12:50:53 +02002129
2130
Felipe Vicense36ab852018-11-23 14:12:09 +01002131class TestNetSliceTemplates:
Felipe Vicensb57758d2018-10-16 16:00:20 +02002132 description = "Upload a NST to OSM"
2133
2134 def __init__(self):
Felipe Vicens09e65422019-01-22 15:06:46 +01002135 self.vnfd_filename = ("@./slice_shared/vnfd/slice_shared_vnfd.yaml")
2136 self.vnfd_filename_middle = ("@./slice_shared/vnfd/slice_shared_middle_vnfd.yaml")
2137 self.nsd_filename = ("@./slice_shared/nsd/slice_shared_nsd.yaml")
2138 self.nsd_filename_middle = ("@./slice_shared/nsd/slice_shared_middle_nsd.yaml")
2139 self.nst_filenames = ("@./slice_shared/slice_shared_nstd.yaml")
Felipe Vicensb57758d2018-10-16 16:00:20 +02002140
2141 def run(self, engine, test_osm, manual_check, test_params=None):
2142 # nst CREATE
Felipe Vicens09e65422019-01-22 15:06:46 +01002143 engine.set_test_name("NST step ")
Felipe Vicensb57758d2018-10-16 16:00:20 +02002144 engine.get_autorization()
Felipe Vicens09e65422019-01-22 15:06:46 +01002145 temp_dir = os.path.dirname(os.path.abspath(__file__)) + "/temp/"
2146 if not os.path.exists(temp_dir):
2147 os.makedirs(temp_dir)
2148
2149 # Onboard VNFDs
2150 engine.test("Onboard edge VNFD", "POST", "/vnfpkgm/v1/vnf_packages_content", headers_yaml,
2151 self.vnfd_filename, 201, r_headers_yaml_location_vnfd, "yaml")
2152 self.vnfd_edge_id = engine.last_id
2153
2154 engine.test("Onboard middle VNFD", "POST", "/vnfpkgm/v1/vnf_packages_content", headers_yaml,
2155 self.vnfd_filename_middle, 201, r_headers_yaml_location_vnfd, "yaml")
2156 self.vnfd_middle_id = engine.last_id
2157
2158 # Onboard NSDs
2159 engine.test("Onboard NSD edge", "POST", "/nsd/v1/ns_descriptors_content", headers_yaml,
2160 self.nsd_filename, 201, r_headers_yaml_location_nsd, "yaml")
2161 self.nsd_edge_id = engine.last_id
2162
2163 engine.test("Onboard NSD middle", "POST", "/nsd/v1/ns_descriptors_content", headers_yaml,
2164 self.nsd_filename_middle, 201, r_headers_yaml_location_nsd, "yaml")
2165 self.nsd_middle_id = engine.last_id
2166
2167 # Onboard NST
tiernoff6485d2018-11-28 17:19:46 +00002168 engine.test("Onboard NST", "POST", "/nst/v1/netslice_templates_content", headers_yaml, self.nst_filenames,
tiernof717cbe2018-12-03 16:35:42 +00002169 201, r_headers_yaml_location_nst, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00002170 nst_id = engine.last_id
Felipe Vicensb57758d2018-10-16 16:00:20 +02002171
2172 # nstd SHOW OSM format
tiernoff6485d2018-11-28 17:19:46 +00002173 engine.test("Show NSTD OSM format", "GET", "/nst/v1/netslice_templates/{}".format(nst_id), headers_json, None,
2174 200, r_header_json, "json")
Felipe Vicensb57758d2018-10-16 16:00:20 +02002175
2176 # nstd DELETE
tiernoff6485d2018-11-28 17:19:46 +00002177 engine.test("Delete NSTD", "DELETE", "/nst/v1/netslice_templates/{}".format(nst_id), headers_json, None,
2178 204, None, 0)
Felipe Vicensb57758d2018-10-16 16:00:20 +02002179
Felipe Vicens09e65422019-01-22 15:06:46 +01002180 # NSDs DELETE
2181 test_rest.test("Delete NSD middle", "DELETE", "/nsd/v1/ns_descriptors/{}".format(self.nsd_middle_id),
2182 headers_json, None, 204, None, 0)
2183
2184 test_rest.test("Delete NSD edge", "DELETE", "/nsd/v1/ns_descriptors/{}".format(self.nsd_edge_id), headers_json,
2185 None, 204, None, 0)
2186
2187 # VNFDs DELETE
2188 test_rest.test("Delete VNFD edge", "DELETE", "/vnfpkgm/v1/vnf_packages/{}".format(self.vnfd_edge_id),
2189 headers_yaml, None, 204, None, 0)
2190
2191 test_rest.test("Delete VNFD middle", "DELETE", "/vnfpkgm/v1/vnf_packages/{}".format(self.vnfd_middle_id),
2192 headers_yaml, None, 204, None, 0)
2193
Felipe Vicensb57758d2018-10-16 16:00:20 +02002194
Felipe Vicense36ab852018-11-23 14:12:09 +01002195class TestNetSliceInstances:
Felipe Vicens09e65422019-01-22 15:06:46 +01002196 '''
2197 Test procedure:
2198 1. Populate databases with VNFD, NSD, NST with the following scenario
2199 +-----------------management-----------------+
2200 | | |
2201 +--+---+ +----+----+ +---+--+
2202 | | | | | |
2203 | edge +---data1----+ middle +---data2-----+ edge |
2204 | | | | | |
2205 +------+ +---------+ +------+
2206 shared-nss
2207 2. Create NSI-1
2208 3. Instantiate NSI-1
2209 4. Create NSI-2
2210 5. Instantiate NSI-2
2211 Manual check - Are 2 slices instantiated correctly?
2212 NSI-1 3 nss (2 nss-edges + 1 nss-middle)
2213 NSI-2 2 nss (2 nss-edge sharing nss-middle)
2214 6. Terminate NSI-1
2215 7. Delete NSI-1
2216 Manual check - Is slice NSI-1 deleted correctly?
2217 NSI-2 with 2 nss-edge + 1 nss-middle (The one from NSI-1)
2218 8. Create NSI-3
2219 9. Instantiate NSI-3
2220 Manual check - Is slice NSI-3 instantiated correctly?
2221 NSI-3 reuse nss-middle. NSI-3 only create 2 nss-edge
2222 10. Delete NSI-2
2223 11. Terminate NSI-2
2224 12. Delete NSI-3
2225 13. Terminate NSI-3
2226 Manual check - All cleaned correctly?
2227 NSI-2 and NSI-3 were terminated and deleted
2228 14. Cleanup database
2229 '''
2230
Felipe Vicense36ab852018-11-23 14:12:09 +01002231 description = "Upload a NST to OSM"
2232
2233 def __init__(self):
tiernoff6485d2018-11-28 17:19:46 +00002234 self.vim_id = None
Felipe Vicens09e65422019-01-22 15:06:46 +01002235 self.vnfd_filename = ("@./slice_shared/vnfd/slice_shared_vnfd.yaml")
2236 self.vnfd_filename_middle = ("@./slice_shared/vnfd/slice_shared_middle_vnfd.yaml")
2237 self.nsd_filename = ("@./slice_shared/nsd/slice_shared_nsd.yaml")
2238 self.nsd_filename_middle = ("@./slice_shared/nsd/slice_shared_middle_nsd.yaml")
2239 self.nst_filenames = ("@./slice_shared/slice_shared_nstd.yaml")
2240
2241 def create_slice(self, engine, nsi_data, name):
2242 ns_data_text = yaml.safe_dump(nsi_data, default_flow_style=True, width=256)
2243 r = engine.test(name, "POST", "/nsilcm/v1/netslice_instances",
2244 headers_yaml, ns_data_text, 201,
2245 {"Location": "nsilcm/v1/netslice_instances/", "Content-Type": "application/yaml"}, "yaml")
2246 return r
2247
2248 def instantiate_slice(self, engine, nsi_data, nsi_id, name):
2249 ns_data_text = yaml.safe_dump(nsi_data, default_flow_style=True, width=256)
2250 engine.test(name, "POST",
2251 "/nsilcm/v1/netslice_instances/{}/instantiate".format(nsi_id), headers_yaml, ns_data_text,
2252 201, r_headers_yaml_location_nsilcmop, "yaml")
2253
2254 def terminate_slice(self, engine, nsi_id, name):
2255 engine.test(name, "POST", "/nsilcm/v1/netslice_instances/{}/terminate".format(nsi_id),
2256 headers_yaml, None, 201, r_headers_yaml_location_nsilcmop, "yaml")
2257
2258 def delete_slice(self, engine, nsi_id, name):
2259 engine.test(name, "DELETE", "/nsilcm/v1/netslice_instances/{}".format(nsi_id), headers_yaml, None,
2260 204, None, 0)
Felipe Vicense36ab852018-11-23 14:12:09 +01002261
2262 def run(self, engine, test_osm, manual_check, test_params=None):
2263 # nst CREATE
tiernoff6485d2018-11-28 17:19:46 +00002264 engine.set_test_name("NSI")
Felipe Vicense36ab852018-11-23 14:12:09 +01002265 engine.get_autorization()
Felipe Vicens09e65422019-01-22 15:06:46 +01002266
2267 # Onboard VNFDs
2268 engine.test("Onboard edge VNFD", "POST", "/vnfpkgm/v1/vnf_packages_content", headers_yaml,
2269 self.vnfd_filename, 201, r_headers_yaml_location_vnfd, "yaml")
2270 self.vnfd_edge_id = engine.last_id
2271
2272 engine.test("Onboard middle VNFD", "POST", "/vnfpkgm/v1/vnf_packages_content", headers_yaml,
2273 self.vnfd_filename_middle, 201, r_headers_yaml_location_vnfd, "yaml")
2274 self.vnfd_middle_id = engine.last_id
2275
2276 # Onboard NSDs
2277 engine.test("Onboard NSD edge", "POST", "/nsd/v1/ns_descriptors_content", headers_yaml,
2278 self.nsd_filename, 201, r_headers_yaml_location_nsd, "yaml")
2279 self.nsd_edge_id = engine.last_id
2280
2281 engine.test("Onboard NSD middle", "POST", "/nsd/v1/ns_descriptors_content", headers_yaml,
2282 self.nsd_filename_middle, 201, r_headers_yaml_location_nsd, "yaml")
2283 self.nsd_middle_id = engine.last_id
2284
2285 # Onboard NST
2286 engine.test("Onboard NST", "POST", "/nst/v1/netslice_templates_content", headers_yaml, self.nst_filenames,
2287 201, r_headers_yaml_location_nst, "yaml")
tiernoff6485d2018-11-28 17:19:46 +00002288 nst_id = engine.last_id
Felipe Vicense36ab852018-11-23 14:12:09 +01002289
tiernoff6485d2018-11-28 17:19:46 +00002290 self.vim_id = engine.get_create_vim(test_osm)
2291
Felipe Vicens09e65422019-01-22 15:06:46 +01002292 # CREATE NSI-1
2293 ns_data = {'nsiName': 'Deploy-NSI-1', 'vimAccountId': self.vim_id, 'nstId': nst_id, 'nsiDescription': 'default'}
2294 r = self.create_slice(engine, ns_data, "Create NSI-1 step 1")
2295 if not r:
2296 return
2297 self.nsi_id1 = engine.last_id
Felipe Vicense36ab852018-11-23 14:12:09 +01002298
Felipe Vicens09e65422019-01-22 15:06:46 +01002299 # INSTANTIATE NSI-1
2300 self.instantiate_slice(engine, ns_data, self.nsi_id1, "Instantiate NSI-1 step 2")
2301 nsilcmop_id1 = engine.last_id
Felipe Vicense36ab852018-11-23 14:12:09 +01002302
Felipe Vicens09e65422019-01-22 15:06:46 +01002303 # Waiting for NSI-1
tiernoe4a07d52019-05-16 15:25:37 +00002304 if test_osm:
2305 engine.wait_operation_ready("nsi", nsilcmop_id1, timeout_deploy)
Felipe Vicens09e65422019-01-22 15:06:46 +01002306
2307 # CREATE NSI-2
2308 ns_data = {'nsiName': 'Deploy-NSI-2', 'vimAccountId': self.vim_id, 'nstId': nst_id, 'nsiDescription': 'default'}
2309 r = self.create_slice(engine, ns_data, "Create NSI-2 step 1")
2310 if not r:
2311 return
2312 self.nsi_id2 = engine.last_id
2313
2314 # INSTANTIATE NSI-2
2315 self.instantiate_slice(engine, ns_data, self.nsi_id2, "Instantiate NSI-2 step 2")
2316 nsilcmop_id2 = engine.last_id
2317
2318 # Waiting for NSI-2
tiernoe4a07d52019-05-16 15:25:37 +00002319 if test_osm:
2320 engine.wait_operation_ready("nsi", nsilcmop_id2, timeout_deploy)
Felipe Vicens09e65422019-01-22 15:06:46 +01002321
2322 if manual_check:
2323 input('NSI-1 AND NSI-2 has been deployed. Perform manual check and press enter to resume')
2324
2325 # TERMINATE NSI-1
tiernoe4a07d52019-05-16 15:25:37 +00002326 if test_osm:
2327 self.terminate_slice(engine, self.nsi_id1, "Terminate NSI-1")
2328 nsilcmop1_id = engine.last_id
Felipe Vicens09e65422019-01-22 15:06:46 +01002329
tiernoe4a07d52019-05-16 15:25:37 +00002330 # Wait terminate NSI-1
2331 engine.wait_operation_ready("nsi", nsilcmop1_id, timeout_deploy)
Felipe Vicens09e65422019-01-22 15:06:46 +01002332
2333 # DELETE NSI-1
2334 self.delete_slice(engine, self.nsi_id1, "Delete NS")
2335
2336 if manual_check:
2337 input('NSI-1 has been deleted. Perform manual check and press enter to resume')
2338
2339 # CREATE NSI-3
2340 ns_data = {'nsiName': 'Deploy-NSI-3', 'vimAccountId': self.vim_id, 'nstId': nst_id, 'nsiDescription': 'default'}
2341 r = self.create_slice(engine, ns_data, "Create NSI-3 step 1")
2342
2343 if not r:
2344 return
2345 self.nsi_id3 = engine.last_id
2346
2347 # INSTANTIATE NSI-3
2348 self.instantiate_slice(engine, ns_data, self.nsi_id3, "Instantiate NSI-3 step 2")
2349 nsilcmop_id3 = engine.last_id
2350
2351 # Wait Instantiate NSI-3
tiernoe4a07d52019-05-16 15:25:37 +00002352 if test_osm:
2353 engine.wait_operation_ready("nsi", nsilcmop_id3, timeout_deploy)
Felipe Vicens09e65422019-01-22 15:06:46 +01002354
2355 if manual_check:
2356 input('NSI-3 has been deployed. Perform manual check and press enter to resume')
2357
2358 # TERMINATE NSI-2
tiernoe4a07d52019-05-16 15:25:37 +00002359 if test_osm:
2360 self.terminate_slice(engine, self.nsi_id2, "Terminate NSI-2")
2361 nsilcmop2_id = engine.last_id
Felipe Vicens09e65422019-01-22 15:06:46 +01002362
tiernoe4a07d52019-05-16 15:25:37 +00002363 # Wait terminate NSI-2
2364 engine.wait_operation_ready("nsi", nsilcmop2_id, timeout_deploy)
Felipe Vicense36ab852018-11-23 14:12:09 +01002365
Felipe Vicens09e65422019-01-22 15:06:46 +01002366 # DELETE NSI-2
2367 self.delete_slice(engine, self.nsi_id2, "DELETE NSI-2")
2368
2369 # TERMINATE NSI-3
tiernoe4a07d52019-05-16 15:25:37 +00002370 if test_osm:
2371 self. terminate_slice(engine, self.nsi_id3, "Terminate NSI-3")
2372 nsilcmop3_id = engine.last_id
2373
2374 # Wait terminate NSI-3
2375 engine.wait_operation_ready("nsi", nsilcmop3_id, timeout_deploy)
Felipe Vicens09e65422019-01-22 15:06:46 +01002376
2377 # DELETE NSI-3
2378 self.delete_slice(engine, self.nsi_id3, "DELETE NSI-3")
2379
2380 if manual_check:
2381 input('NSI-2 and NSI-3 has been deleted. Perform manual check and press enter to resume')
Felipe Vicense36ab852018-11-23 14:12:09 +01002382
2383 # nstd DELETE
tiernoff6485d2018-11-28 17:19:46 +00002384 engine.test("Delete NSTD", "DELETE", "/nst/v1/netslice_templates/{}".format(nst_id), headers_json, None,
2385 204, None, 0)
Felipe Vicense36ab852018-11-23 14:12:09 +01002386
Felipe Vicens09e65422019-01-22 15:06:46 +01002387 # NSDs DELETE
2388 test_rest.test("Delete NSD middle", "DELETE", "/nsd/v1/ns_descriptors/{}".format(self.nsd_middle_id),
2389 headers_json, None, 204, None, 0)
2390
2391 test_rest.test("Delete NSD edge", "DELETE", "/nsd/v1/ns_descriptors/{}".format(self.nsd_edge_id), headers_json,
2392 None, 204, None, 0)
2393
2394 # VNFDs DELETE
2395 test_rest.test("Delete VNFD edge", "DELETE", "/vnfpkgm/v1/vnf_packages/{}".format(self.vnfd_edge_id),
2396 headers_yaml, None, 204, None, 0)
2397
2398 test_rest.test("Delete VNFD middle", "DELETE", "/vnfpkgm/v1/vnf_packages/{}".format(self.vnfd_middle_id),
2399 headers_yaml, None, 204, None, 0)
2400
Felipe Vicense36ab852018-11-23 14:12:09 +01002401
tiernof27c79b2018-03-12 17:08:42 +01002402if __name__ == "__main__":
2403 global logger
2404 test = ""
tierno0f98af52018-03-19 10:28:22 +01002405
2406 # Disable warnings from self-signed certificates.
2407 requests.packages.urllib3.disable_warnings()
tiernof27c79b2018-03-12 17:08:42 +01002408 try:
2409 logging.basicConfig(format="%(levelname)s %(message)s", level=logging.ERROR)
2410 logger = logging.getLogger('NBI')
2411 # load parameters and configuration
2412 opts, args = getopt.getopt(sys.argv[1:], "hvu:p:",
tiernoc32ba4a2018-05-24 18:06:41 +02002413 ["url=", "user=", "password=", "help", "version", "verbose", "no-verbose",
2414 "project=", "insecure", "timeout", "timeout-deploy", "timeout-configure",
tiernoff6485d2018-11-28 17:19:46 +00002415 "test=", "list", "test-osm", "manual-check", "params=", 'fail-fast'])
tiernof27c79b2018-03-12 17:08:42 +01002416 url = "https://localhost:9999/osm"
2417 user = password = project = "admin"
tiernoc32ba4a2018-05-24 18:06:41 +02002418 test_osm = False
2419 manual_check = False
tiernof27c79b2018-03-12 17:08:42 +01002420 verbose = 0
2421 verify = True
tiernoff6485d2018-11-28 17:19:46 +00002422 fail_fast = False
tiernoc32ba4a2018-05-24 18:06:41 +02002423 test_classes = {
2424 "NonAuthorized": TestNonAuthorized,
2425 "FakeVIM": TestFakeVim,
tierno65ca36d2019-02-12 19:27:52 +01002426 "Users-Projects": TestUsersProjects,
2427 "Projects-Descriptors": TestProjectsDescriptors,
tiernoc32ba4a2018-05-24 18:06:41 +02002428 "VIM-SDN": TestVIMSDN,
2429 "Deploy-Custom": TestDeploy,
2430 "Deploy-Hackfest-Cirros": TestDeployHackfestCirros,
tiernocc103432018-10-19 14:10:35 +02002431 "Deploy-Hackfest-Cirros-Scaling": TestDeployHackfestCirrosScaling,
tiernoc32ba4a2018-05-24 18:06:41 +02002432 "Deploy-Hackfest-3Charmed": TestDeployHackfest3Charmed,
tiernobee085c2018-12-12 17:03:04 +00002433 "Deploy-Hackfest-3Charmed2": TestDeployHackfest3Charmed2,
2434 "Deploy-Hackfest-3Charmed3": TestDeployHackfest3Charmed3,
tiernoc32ba4a2018-05-24 18:06:41 +02002435 "Deploy-Hackfest-4": TestDeployHackfest4,
2436 "Deploy-CirrosMacIp": TestDeployIpMac,
tierno65ca36d2019-02-12 19:27:52 +01002437 "Descriptors": TestDescriptors,
2438 "Deploy-Hackfest1": TestDeployHackfest1,
gcalvino337ec512018-07-30 10:30:13 +02002439 # "Deploy-MultiVIM": TestDeployMultiVIM,
tierno65ca36d2019-02-12 19:27:52 +01002440 "Deploy-SingleVdu": TestDeploySingleVdu,
2441 "Deploy-Hnfd": TestDeployHnfd,
Felipe Vicens09e65422019-01-22 15:06:46 +01002442 "Upload-Slice-Template": TestNetSliceTemplates,
2443 "Deploy-Slice-Instance": TestNetSliceInstances,
tierno65ca36d2019-02-12 19:27:52 +01002444 "Deploy-SimpleCharm": TestDeploySimpleCharm,
2445 "Deploy-SimpleCharm2": TestDeploySimpleCharm2,
tiernoc32ba4a2018-05-24 18:06:41 +02002446 }
2447 test_to_do = []
2448 test_params = {}
tiernof27c79b2018-03-12 17:08:42 +01002449
2450 for o, a in opts:
tiernoc32ba4a2018-05-24 18:06:41 +02002451 # print("parameter:", o, a)
tiernof27c79b2018-03-12 17:08:42 +01002452 if o == "--version":
tierno2236d202018-05-16 19:05:16 +02002453 print("test version " + __version__ + ' ' + version_date)
tiernoc32ba4a2018-05-24 18:06:41 +02002454 exit()
2455 elif o == "--list":
tiernobee085c2018-12-12 17:03:04 +00002456 for test, test_class in sorted(test_classes.items()):
2457 print("{:32} {}".format(test + ":", test_class.description))
tiernoc32ba4a2018-05-24 18:06:41 +02002458 exit()
tiernof27c79b2018-03-12 17:08:42 +01002459 elif o in ("-v", "--verbose"):
2460 verbose += 1
tierno2236d202018-05-16 19:05:16 +02002461 elif o == "no-verbose":
tiernof27c79b2018-03-12 17:08:42 +01002462 verbose = -1
2463 elif o in ("-h", "--help"):
2464 usage()
2465 sys.exit()
tiernoc32ba4a2018-05-24 18:06:41 +02002466 elif o == "--test-osm":
2467 test_osm = True
2468 elif o == "--manual-check":
2469 manual_check = True
tierno2236d202018-05-16 19:05:16 +02002470 elif o == "--url":
tiernof27c79b2018-03-12 17:08:42 +01002471 url = a
2472 elif o in ("-u", "--user"):
2473 user = a
2474 elif o in ("-p", "--password"):
2475 password = a
tierno2236d202018-05-16 19:05:16 +02002476 elif o == "--project":
tiernof27c79b2018-03-12 17:08:42 +01002477 project = a
tiernoff6485d2018-11-28 17:19:46 +00002478 elif o == "--fail-fast":
2479 fail_fast = True
tiernoc32ba4a2018-05-24 18:06:41 +02002480 elif o == "--test":
2481 # print("asdfadf", o, a, a.split(","))
2482 for _test in a.split(","):
2483 if _test not in test_classes:
2484 print("Invalid test name '{}'. Use option '--list' to show available tests".format(_test),
2485 file=sys.stderr)
2486 exit(1)
2487 test_to_do.append(_test)
2488 elif o == "--params":
2489 param_key, _, param_value = a.partition("=")
2490 text_index = len(test_to_do)
2491 if text_index not in test_params:
2492 test_params[text_index] = {}
2493 test_params[text_index][param_key] = param_value
tierno2236d202018-05-16 19:05:16 +02002494 elif o == "--insecure":
tiernof27c79b2018-03-12 17:08:42 +01002495 verify = False
tiernoc32ba4a2018-05-24 18:06:41 +02002496 elif o == "--timeout":
2497 timeout = int(a)
2498 elif o == "--timeout-deploy":
2499 timeout_deploy = int(a)
2500 elif o == "--timeout-configure":
2501 timeout_configure = int(a)
tiernof27c79b2018-03-12 17:08:42 +01002502 else:
2503 assert False, "Unhandled option"
2504 if verbose == 0:
2505 logger.setLevel(logging.WARNING)
2506 elif verbose > 1:
2507 logger.setLevel(logging.DEBUG)
2508 else:
2509 logger.setLevel(logging.ERROR)
2510
tiernoc32ba4a2018-05-24 18:06:41 +02002511 test_rest = TestRest(url, user=user, password=password, project=project)
2512 # print("tests to do:", test_to_do)
2513 if test_to_do:
2514 text_index = 0
2515 for test in test_to_do:
tiernoff6485d2018-11-28 17:19:46 +00002516 if fail_fast and test_rest.failed_tests:
2517 break
tiernoc32ba4a2018-05-24 18:06:41 +02002518 text_index += 1
2519 test_class = test_classes[test]
2520 test_class().run(test_rest, test_osm, manual_check, test_params.get(text_index))
2521 else:
delacruzramoc061f562019-04-05 11:00:02 +02002522 for test, test_class in sorted(test_classes.items()):
tiernoff6485d2018-11-28 17:19:46 +00002523 if fail_fast and test_rest.failed_tests:
2524 break
tiernoc32ba4a2018-05-24 18:06:41 +02002525 test_class().run(test_rest, test_osm, manual_check, test_params.get(0))
tiernoff6485d2018-11-28 17:19:46 +00002526 test_rest.print_results()
2527 exit(1 if test_rest.failed_tests else 0)
tiernof27c79b2018-03-12 17:08:42 +01002528
tiernoc32ba4a2018-05-24 18:06:41 +02002529 except TestException as e:
2530 logger.error(test + "Test {} Exception: {}".format(test, str(e)))
2531 exit(1)
2532 except getopt.GetoptError as e:
2533 logger.error(e)
2534 print(e, file=sys.stderr)
2535 exit(1)
tiernof27c79b2018-03-12 17:08:42 +01002536 except Exception as e:
tiernoc32ba4a2018-05-24 18:06:41 +02002537 logger.critical(test + " Exception: " + str(e), exc_info=True)