Merge "Revert "Create folder structure in backend for onboarded descriptor - RIFT...
[osm/SO.git] / rwlaunchpad / test / mano_ut.py
1 #!/usr/bin/env python3
2
3 #
4 # Copyright 2016 RIFT.IO Inc
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 #
18
19
20 import asyncio
21 import os
22 import sys
23 import unittest
24 import uuid
25 import xmlrunner
26 import argparse
27 import logging
28 import time
29 import types
30
31 import gi
32 gi.require_version('RwCloudYang', '1.0')
33 gi.require_version('RwDts', '1.0')
34 gi.require_version('RwNsmYang', '1.0')
35 gi.require_version('RwLaunchpadYang', '1.0')
36 gi.require_version('RwResourceMgrYang', '1.0')
37 gi.require_version('RwcalYang', '1.0')
38 gi.require_version('RwNsrYang', '1.0')
39 gi.require_version('NsrYang', '1.0')
40 gi.require_version('RwlogMgmtYang', '1.0')
41
42 from gi.repository import (
43 RwCloudYang as rwcloudyang,
44 RwDts as rwdts,
45 RwLaunchpadYang as launchpadyang,
46 RwNsmYang as rwnsmyang,
47 RwNsrYang as rwnsryang,
48 NsrYang as nsryang,
49 RwResourceMgrYang as rmgryang,
50 RwcalYang as rwcalyang,
51 RwConfigAgentYang as rwcfg_agent,
52 RwlogMgmtYang
53 )
54
55 from gi.repository.RwTypes import RwStatus
56 import rift.mano.examples.ping_pong_nsd as ping_pong_nsd
57 import rift.tasklets
58 import rift.test.dts
59 import rw_peas
60
61
62 openstack_info = {
63 'username': 'pluto',
64 'password': 'mypasswd',
65 'auth_url': 'http://10.66.4.27:5000/v3/',
66 'project_name': 'demo',
67 'mgmt_network': 'private',
68 }
69
70
71 if sys.version_info < (3, 4, 4):
72 asyncio.ensure_future = asyncio.async
73
74
75 class XPaths(object):
76 @staticmethod
77 def nsd(k=None):
78 return ("C,/nsd:nsd-catalog/nsd:nsd" +
79 ("[nsd:id='{}']".format(k) if k is not None else ""))
80
81 @staticmethod
82 def vld(k=None):
83 return ("C,/vld:vld-catalog/vld:vld" +
84 ("[vld:id='{}']".format(k) if k is not None else ""))
85
86 @staticmethod
87 def vnfd(k=None):
88 return ("C,/vnfd:vnfd-catalog/vnfd:vnfd" +
89 ("[vnfd:id='{}']".format(k) if k is not None else ""))
90
91 @staticmethod
92 def vnfr(k=None):
93 return ("D,/vnfr:vnfr-catalog/vnfr:vnfr" +
94 ("[vnfr:id='{}']".format(k) if k is not None else ""))
95
96 @staticmethod
97 def vlr(k=None):
98 return ("D,/vlr:vlr-catalog/vlr:vlr" +
99 ("[vlr:id='{}']".format(k) if k is not None else ""))
100
101 @staticmethod
102 def nsd_ref_count(k=None):
103 return ("D,/nsr:ns-instance-opdata/rw-nsr:nsd-ref-count" +
104 ("[rw-nsr:nsd-id-ref='{}']".format(k) if k is not None else ""))
105
106 @staticmethod
107 def vnfd_ref_count(k=None):
108 return ("D,/vnfr:vnfr-catalog/rw-vnfr:vnfd-ref-count" +
109 ("[rw-nsr:nsd-id-ref='{}']".format(k) if k is not None else ""))
110
111 @staticmethod
112 def nsr_config(k=None):
113 return ("C,/nsr:ns-instance-config/nsr:nsr" +
114 ("[nsr:id='{}']".format(k) if k is not None else ""))
115
116 @staticmethod
117 def nsr_opdata(k=None):
118 return ("D,/nsr:ns-instance-opdata/nsr:nsr" +
119 ("[nsr:ns-instance-config-ref='{}']".format(k) if k is not None else ""))
120
121 @staticmethod
122 def nsr_config_status(k=None):
123 return ("D,/nsr:ns-instance-opdata/nsr:nsr" +
124 ("[nsr:ns-instance-config-ref='{}']/config_status".format(k) if k is not None else ""))
125
126 @staticmethod
127 def cm_state(k=None):
128 if k is None:
129 return ("D,/rw-conman:cm-state/rw-conman:cm-nsr")
130 else:
131 return ("D,/rw-conman:cm-state/rw-conman:cm-nsr" +
132 ("[rw-conman:id='{}']".format(k) if k is not None else ""))
133
134 @staticmethod
135 def nsr_scale_group_instance(nsr_id=None, group_name=None, index=None):
136 return (("D,/nsr:ns-instance-opdata/nsr:nsr") +
137 ("[nsr:ns-instance-config-ref='{}']".format(nsr_id) if nsr_id is not None else "") +
138 ("/nsr:scaling-group-record") +
139 ("[nsr:scaling-group-name-ref='{}']".format(group_name) if group_name is not None else "") +
140 ("/nsr:instance") +
141 ("[nsr:scaling-group-index-ref='{}']".format(index) if index is not None else ""))
142
143 @staticmethod
144 def nsr_scale_group_instance_config(nsr_id=None, group_name=None, index=None):
145 return (("C,/nsr:ns-instance-config/nsr:nsr") +
146 ("[nsr:id='{}']".format(nsr_id) if nsr_id is not None else "") +
147 ("/nsr:scaling-group") +
148 ("[nsr:scaling-group-name-ref='{}']".format(group_name) if group_name is not None else "") +
149 ("/nsr:instance") +
150 ("[nsr:index='{}']".format(index) if index is not None else ""))
151
152
153 class ManoQuerier(object):
154 def __init__(self, log, dts):
155 self.log = log
156 self.dts = dts
157
158 @asyncio.coroutine
159 def _read_query(self, xpath, do_trace=False):
160 self.log.debug("Running XPATH read query: %s (trace: %s)", xpath, do_trace)
161 flags = rwdts.XactFlag.MERGE
162 flags += rwdts.XactFlag.TRACE if do_trace else 0
163 res_iter = yield from self.dts.query_read(
164 xpath, flags=flags
165 )
166
167 results = []
168 for i in res_iter:
169 result = yield from i
170 if result is not None:
171 results.append(result.result)
172
173 return results
174
175 @asyncio.coroutine
176 def get_cm_state(self, nsr_id=None):
177 return (yield from self._read_query(XPaths.cm_state(nsr_id), False))
178
179 @asyncio.coroutine
180 def get_nsr_opdatas(self, nsr_id=None):
181 return (yield from self._read_query(XPaths.nsr_opdata(nsr_id), False))
182
183 @asyncio.coroutine
184 def get_nsr_scale_group_instance_opdata(self, nsr_id=None, group_name=None, index=None):
185 return (yield from self._read_query(XPaths.nsr_scale_group_instance(nsr_id, group_name, index), False))
186 #return (yield from self._read_query(XPaths.nsr_scale_group_instance(nsr_id, group_name), True))
187
188 @asyncio.coroutine
189 def get_nsr_configs(self, nsr_id=None):
190 return (yield from self._read_query(XPaths.nsr_config(nsr_id)))
191
192 @asyncio.coroutine
193 def get_nsr_config_status(self, nsr_id=None):
194 return (yield from self._read_query(XPaths.nsr_config_status(nsr_id)))
195
196 @asyncio.coroutine
197 def get_vnfrs(self, vnfr_id=None):
198 return (yield from self._read_query(XPaths.vnfr(vnfr_id)))
199
200 @asyncio.coroutine
201 def get_vlrs(self, vlr_id=None):
202 return (yield from self._read_query(XPaths.vlr(vlr_id)))
203
204 @asyncio.coroutine
205 def get_nsd_ref_counts(self, nsd_id=None):
206 return (yield from self._read_query(XPaths.nsd_ref_count(nsd_id)))
207
208 @asyncio.coroutine
209 def get_vnfd_ref_counts(self, vnfd_id=None):
210 return (yield from self._read_query(XPaths.vnfd_ref_count(vnfd_id)))
211
212 @asyncio.coroutine
213 def delete_nsr(self, nsr_id):
214 with self.dts.transaction() as xact:
215 yield from self.dts.query_delete(
216 XPaths.nsr_config(nsr_id),
217 0
218 #rwdts.XactFlag.TRACE,
219 #rwdts.Flag.ADVISE,
220 )
221
222 @asyncio.coroutine
223 def delete_nsd(self, nsd_id):
224 nsd_xpath = XPaths.nsd(nsd_id)
225 self.log.debug("Attempting to delete NSD with path = %s", nsd_xpath)
226 with self.dts.transaction() as xact:
227 yield from self.dts.query_delete(
228 nsd_xpath,
229 rwdts.XactFlag.ADVISE,
230 )
231
232 @asyncio.coroutine
233 def delete_vnfd(self, vnfd_id):
234 vnfd_xpath = XPaths.vnfd(vnfd_id)
235 self.log.debug("Attempting to delete VNFD with path = %s", vnfd_xpath)
236 with self.dts.transaction() as xact:
237 yield from self.dts.query_delete(
238 vnfd_xpath,
239 rwdts.XactFlag.ADVISE,
240 )
241
242 @asyncio.coroutine
243 def update_nsd(self, nsd_id, nsd_msg):
244 nsd_xpath = XPaths.nsd(nsd_id)
245 self.log.debug("Attempting to update NSD with path = %s", nsd_xpath)
246 with self.dts.transaction() as xact:
247 yield from self.dts.query_update(
248 nsd_xpath,
249 rwdts.XactFlag.ADVISE,
250 nsd_msg,
251 )
252
253 @asyncio.coroutine
254 def update_vnfd(self, vnfd_id, vnfd_msg):
255 vnfd_xpath = XPaths.vnfd(vnfd_id)
256 self.log.debug("Attempting to delete VNFD with path = %s", vnfd_xpath)
257 with self.dts.transaction() as xact:
258 yield from self.dts.query_update(
259 vnfd_xpath,
260 rwdts.XactFlag.ADVISE,
261 vnfd_msg,
262 )
263
264 @asyncio.coroutine
265 def update_nsr_config(self, nsr_id, nsr_msg):
266 nsr_xpath = XPaths.nsr_config(nsr_id)
267 self.log.debug("Attempting to update NSR with path = %s", nsr_xpath)
268 with self.dts.transaction() as xact:
269 yield from self.dts.query_update(
270 nsr_xpath,
271 rwdts.XactFlag.ADVISE|rwdts.XactFlag.REPLACE,
272 nsr_msg,
273 )
274
275
276 class ManoTestCase(rift.test.dts.AbstractDTSTest):
277 @asyncio.coroutine
278 def verify_nsr_state(self, nsr_id, state):
279 nsrs = yield from self.querier.get_nsr_opdatas(nsr_id)
280 self.assertEqual(1, len(nsrs))
281 nsr = nsrs[0]
282
283 self.log.debug("Got nsr = %s", nsr)
284 self.assertEqual(state, nsr.operational_status)
285
286 @asyncio.coroutine
287 def verify_vlr_state(self, vlr_id, state):
288 vlrs = yield from self.querier.get_vlrs(vlr_id)
289 self.assertEqual(1, len(vlrs))
290 vlr = vlrs[0]
291
292 self.assertEqual(state, vlr.operational_status)
293
294 def verify_vdu_state(self, vdu, state):
295 self.assertEqual(state, vdu.operational_status)
296
297 @asyncio.coroutine
298 def verify_vnf_state(self, vnfr_id, state):
299 vnfrs = yield from self.querier.get_vnfrs(vnfr_id)
300 self.assertEqual(1, len(vnfrs))
301 vnfr = vnfrs[0]
302
303 self.assertEqual(state, vnfr.operational_status)
304
305 @asyncio.coroutine
306 def terminate_nsr(self, nsr_id):
307 self.log.debug("Terminating nsr id: %s", nsr_id)
308 yield from self.querier.delete_nsr(nsr_id)
309
310 @asyncio.coroutine
311 def verify_nsr_deleted(self, nsr_id):
312 nsr_opdatas = yield from self.querier.get_nsr_opdatas(nsr_id)
313 self.assertEqual(0, len(nsr_opdatas))
314
315 nsr_configs = yield from self.querier.get_nsr_configs(nsr_id)
316 self.assertEqual(0, len(nsr_configs))
317
318 @asyncio.coroutine
319 def verify_num_vlrs(self, num_vlrs):
320 vlrs = yield from self.querier.get_vlrs()
321 self.assertEqual(num_vlrs, len(vlrs))
322
323 @asyncio.coroutine
324 def get_nsr_vlrs(self, nsr_id):
325 nsrs = yield from self.querier.get_nsr_opdatas(nsr_id)
326 return [v.vlr_ref for v in nsrs[0].vlr]
327
328 @asyncio.coroutine
329 def get_nsr_vnfs(self, nsr_id):
330 nsrs = yield from self.querier.get_nsr_opdatas(nsr_id)
331 return nsrs[0].constituent_vnfr_ref
332
333 @asyncio.coroutine
334 def get_vnf_vlrs(self, vnfr_id):
335 vnfrs = yield from self.querier.get_vnfrs(vnfr_id)
336 return [i.vlr_ref for i in vnfrs[0].internal_vlr]
337
338 @asyncio.coroutine
339 def verify_num_nsr_vlrs(self, nsr_id, num_vlrs):
340 vlrs = yield from self.get_nsr_vlrs(nsr_id)
341 self.assertEqual(num_vlrs, len(vlrs))
342
343 @asyncio.coroutine
344 def verify_num_nsr_vnfrs(self, nsr_id, num_vnfs):
345 vnfs = yield from self.get_nsr_vnfs(nsr_id)
346 self.assertEqual(num_vnfs, len(vnfs))
347
348 @asyncio.coroutine
349 def verify_num_vnfr_vlrs(self, vnfr_id, num_vlrs):
350 vlrs = yield from self.get_vnf_vlrs(vnfr_id)
351 self.assertEqual(num_vlrs, len(vlrs))
352
353 @asyncio.coroutine
354 def get_vnf_vdus(self, vnfr_id):
355 vnfrs = yield from self.querier.get_vnfrs(vnfr_id)
356 return [i for i in vnfrs[0].vdur]
357
358 @asyncio.coroutine
359 def verify_num_vnfr_vdus(self, vnfr_id, num_vdus):
360 vdus = yield from self.get_vnf_vdus(vnfr_id)
361 self.assertEqual(num_vdus, len(vdus))
362
363 @asyncio.coroutine
364 def verify_num_vnfrs(self, num_vnfrs):
365 vnfrs = yield from self.querier.get_vnfrs()
366 self.assertEqual(num_vnfrs, len(vnfrs))
367
368 @asyncio.coroutine
369 def verify_nsd_ref_count(self, nsd_id, num_ref):
370 nsd_ref_counts = yield from self.querier.get_nsd_ref_counts(nsd_id)
371 self.assertEqual(num_ref, nsd_ref_counts[0].instance_ref_count)
372
373 class DescriptorPublisher(object):
374 def __init__(self, log, loop, dts):
375 self.log = log
376 self.loop = loop
377 self.dts = dts
378
379 self._registrations = []
380
381 @asyncio.coroutine
382 def publish(self, w_path, path, desc):
383 ready_event = asyncio.Event(loop=self.loop)
384
385 @asyncio.coroutine
386 def on_ready(regh, status):
387 self.log.debug("Create element: %s, obj-type:%s obj:%s",
388 path, type(desc), desc)
389 with self.dts.transaction() as xact:
390 regh.create_element(path, desc, xact.xact)
391 self.log.debug("Created element: %s, obj:%s", path, desc)
392 ready_event.set()
393
394 handler = rift.tasklets.DTS.RegistrationHandler(
395 on_ready=on_ready
396 )
397
398 self.log.debug("Registering path: %s, obj:%s", w_path, desc)
399 reg = yield from self.dts.register(
400 w_path,
401 handler,
402 flags=rwdts.Flag.PUBLISHER | rwdts.Flag.NO_PREP_READ
403 )
404 self._registrations.append(reg)
405 self.log.debug("Registered path : %s", w_path)
406 yield from ready_event.wait()
407
408 return reg
409
410 def unpublish_all(self):
411 self.log.debug("Deregistering all published descriptors")
412 for reg in self._registrations:
413 reg.deregister()
414
415
416 class PingPongNsrConfigPublisher(object):
417 XPATH = "C,/nsr:ns-instance-config"
418
419 def __init__(self, log, loop, dts, ping_pong, cloud_account_name):
420 self.dts = dts
421 self.log = log
422 self.loop = loop
423 self.ref = None
424
425 self.querier = ManoQuerier(log, dts)
426
427 self.nsr_config = rwnsryang.YangData_Nsr_NsInstanceConfig()
428
429 nsr = rwnsryang.YangData_Nsr_NsInstanceConfig_Nsr()
430 nsr.id = str(uuid.uuid4())
431 nsr.name = "ns1.{}".format(nsr.id)
432 nsr.nsd = nsryang.YangData_Nsr_NsInstanceConfig_Nsr_Nsd()
433 nsr.nsd.from_dict(ping_pong.ping_pong_nsd.nsd.as_dict())
434 nsr.cloud_account = cloud_account_name
435
436 nsr.vnf_cloud_account_map.add().from_dict({
437 'member_vnf_index_ref': nsr.nsd.constituent_vnfd[0].member_vnf_index,
438 'config_agent_account': 'RiftCA',
439 #'cloud_account':'mock_account1'
440 })
441
442 inputs = nsryang.YangData_Nsr_NsInstanceConfig_Nsr_InputParameter()
443 inputs.xpath = "/nsd:nsd-catalog/nsd:nsd[nsd:id={}]/nsd:name".format(ping_pong.nsd_id)
444 inputs.value = "inigo montoya"
445
446 fast_cpu = {'metadata_key': 'FASTCPU', 'metadata_value': 'True'}
447 self.create_nsd_placement_group_map(nsr,
448 group_name = 'Orcus',
449 cloud_type = 'openstack',
450 construct_type = 'host_aggregate',
451 construct_value = [fast_cpu])
452
453 fast_storage = {'metadata_key': 'FASTSSD', 'metadata_value': 'True'}
454 self.create_nsd_placement_group_map(nsr,
455 group_name = 'Quaoar',
456 cloud_type = 'openstack',
457 construct_type = 'host_aggregate',
458 construct_value = [fast_storage])
459
460 fast_cpu = {'metadata_key': 'BLUE_HW', 'metadata_value': 'True'}
461 self.create_vnfd_placement_group_map(nsr,
462 group_name = 'Eris',
463 vnfd_id = ping_pong.ping_vnfd_id,
464 cloud_type = 'openstack',
465 construct_type = 'host_aggregate',
466 construct_value = [fast_cpu])
467
468 fast_storage = {'metadata_key': 'YELLOW_HW', 'metadata_value': 'True'}
469 self.create_vnfd_placement_group_map(nsr,
470 group_name = 'Weywot',
471 vnfd_id = ping_pong.pong_vnfd_id,
472 cloud_type = 'openstack',
473 construct_type = 'host_aggregate',
474 construct_value = [fast_storage])
475
476
477 nsr.input_parameter.append(inputs)
478
479 self._nsr = nsr
480 self.nsr_config.nsr.append(nsr)
481
482 self._ready_event = asyncio.Event(loop=self.loop)
483 asyncio.ensure_future(self.register(), loop=loop)
484
485 @asyncio.coroutine
486 def register(self):
487 @asyncio.coroutine
488 def on_ready(regh, status):
489 self._ready_event.set()
490
491 self.log.debug("Registering path: %s", PingPongNsrConfigPublisher.XPATH)
492 self.reg = yield from self.dts.register(
493 PingPongNsrConfigPublisher.XPATH,
494 flags=rwdts.Flag.PUBLISHER,
495 handler=rift.tasklets.DTS.RegistrationHandler(
496 on_ready=on_ready,
497 ),
498 )
499
500 @asyncio.coroutine
501 def publish(self):
502 self.log.debug("Publishing NSR: {}".format(self.nsr_config))
503 yield from self._ready_event.wait()
504 with self.dts.transaction() as xact:
505 self.reg.create_element(
506 PingPongNsrConfigPublisher.XPATH,
507 self.nsr_config,
508 xact=xact.xact,
509 )
510
511 return self._nsr.id
512
513 @asyncio.coroutine
514 def create_scale_group_instance(self, group_name, index):
515 index = 1
516 scaling_group = self.nsr_config.nsr[0].scaling_group.add()
517 scaling_group.from_dict({
518 "scaling_group_name_ref": group_name,
519 "instance": [{"index": index}],
520 })
521 with self.dts.transaction() as xact:
522 self.reg.update_element(
523 PingPongNsrConfigPublisher.XPATH,
524 self.nsr_config,
525 xact=xact.xact,
526 )
527
528 return index
529
530 def create_nsd_placement_group_map(self,
531 nsr,
532 group_name,
533 cloud_type,
534 construct_type,
535 construct_value):
536 placement_group = nsr.nsd_placement_group_maps.add()
537 placement_group.from_dict({
538 "placement_group_ref" : group_name,
539 "cloud_type" : cloud_type,
540 construct_type : construct_value,
541 })
542
543
544 def create_vnfd_placement_group_map(self,
545 nsr,
546 group_name,
547 vnfd_id,
548 cloud_type,
549 construct_type,
550 construct_value):
551 placement_group = nsr.vnfd_placement_group_maps.add()
552 placement_group.from_dict({
553 "placement_group_ref" : group_name,
554 "vnfd_id_ref" : vnfd_id,
555 "cloud_type" : cloud_type,
556 construct_type : construct_value,
557 })
558
559
560 @asyncio.coroutine
561 def delete_scale_group_instance(self, group_name, index):
562 self.log.debug("Deleting scale group %s instance %s", group_name, index)
563 #del self.nsr_config.nsr[0].scaling_group[0].instance[0]
564 xpath = XPaths.nsr_scale_group_instance_config(self.nsr_config.nsr[0].id, group_name, index)
565 yield from self.dts.query_delete(xpath, flags=rwdts.XactFlag.ADVISE)
566 #with self.dts.transaction() as xact:
567 # self.reg.update_element(
568 # PingPongNsrConfigPublisher.XPATH,
569 # self.nsr_config,
570 # flags=rwdts.XactFlag.REPLACE,
571 # xact=xact.xact,
572 # )
573
574 def deregister(self):
575 if self.reg is not None:
576 self.reg.deregister()
577
578 def create_nsr_vl(self):
579 vld = self.nsr_config.nsr[0].nsd.vld.add()
580 vld.id = 'ping_pong_vld_2'
581 vld.name = 'ping_pong_vld_2' # hard coded
582 vld.short_name = vld.name
583 vld.vendor = 'RIFT.io'
584 vld.description = 'Toy VL'
585 vld.version = '1.0'
586 vld.type_yang = 'ELAN'
587
588 # cpref = vld.vnfd_connection_point_ref.add()
589 # cpref.member_vnf_index_ref = cp[0]
590 # cpref.vnfd_id_ref = cp[1]
591 # cpref.vnfd_connection_point_ref = cp[2]
592
593 vld = self.nsr_config.nsr[0].vl_cloud_account_map.add()
594 vld.vld_id_ref = 'ping_pong_vld_2'
595 vld.cloud_accounts = ["mock_account"]
596
597 @asyncio.coroutine
598 def add_nsr_vl(self):
599 self.create_nsr_vl()
600 yield from self.querier.update_nsr_config(
601 self.nsr_config.nsr[0].id,
602 self.nsr_config.nsr[0],
603 )
604
605 @asyncio.coroutine
606 def del_nsr_vl(self):
607 for vld in self.nsr_config.nsr[0].nsd.vld:
608 if vld.id == 'ping_pong_vld_2':
609 self.nsr_config.nsr[0].nsd.vld.remove(vld)
610 break
611
612 yield from self.querier.update_nsr_config(
613 self.nsr_config.nsr[0].id,
614 self.nsr_config.nsr[0],
615 )
616
617 def update_vnf_cloud_map(self,vnf_cloud_map):
618 self.log.debug("Modifying NSR to add VNF cloud account map: {}".format(vnf_cloud_map))
619 for vnf_index,cloud_acct in vnf_cloud_map.items():
620 vnf_maps = [vnf_map for vnf_map in self.nsr_config.nsr[0].vnf_cloud_account_map if vnf_index == vnf_map.member_vnf_index_ref]
621 if vnf_maps:
622 vnf_maps[0].cloud_account = cloud_acct
623 else:
624 self.nsr_config.nsr[0].vnf_cloud_account_map.add().from_dict({
625 'member_vnf_index_ref':vnf_index,
626 'cloud_account':cloud_acct
627 })
628
629
630 class PingPongDescriptorPublisher(object):
631 def __init__(self, log, loop, dts, num_external_vlrs=1, num_internal_vlrs=1, num_ping_vms=1):
632 self.log = log
633 self.loop = loop
634 self.dts = dts
635
636 self.querier = ManoQuerier(self.log, self.dts)
637 self.publisher = DescriptorPublisher(self.log, self.loop, self.dts)
638 self.ping_vnfd, self.pong_vnfd, self.ping_pong_nsd = \
639 ping_pong_nsd.generate_ping_pong_descriptors(
640 pingcount=1,
641 external_vlr_count=num_external_vlrs,
642 internal_vlr_count=num_internal_vlrs,
643 num_vnf_vms=2,
644 mano_ut=True,
645 use_scale_group=True,
646 use_mon_params=False,
647 )
648
649 self.config_dir = os.path.join(os.getenv('RIFT_ARTIFACTS'),
650 "launchpad/libs",
651 self.ping_pong_nsd.id,
652 "config")
653
654 @property
655 def nsd_id(self):
656 return self.ping_pong_nsd.id
657
658 @property
659 def ping_vnfd_id(self):
660 return self.ping_vnfd.id
661
662 @property
663 def pong_vnfd_id(self):
664 return self.pong_vnfd.id
665
666 @asyncio.coroutine
667 def publish_desciptors(self):
668 # Publish ping_vnfd
669 xpath = XPaths.vnfd(self.ping_vnfd_id)
670 xpath_wild = XPaths.vnfd()
671 for obj in self.ping_vnfd.descriptor.vnfd:
672 self.log.debug("Publishing ping_vnfd path: %s - %s, type:%s, obj:%s",
673 xpath, xpath_wild, type(obj), obj)
674 yield from self.publisher.publish(xpath_wild, xpath, obj)
675
676 # Publish pong_vnfd
677 xpath = XPaths.vnfd(self.pong_vnfd_id)
678 xpath_wild = XPaths.vnfd()
679 for obj in self.pong_vnfd.descriptor.vnfd:
680 self.log.debug("Publishing pong_vnfd path: %s, wild_path: %s, obj:%s",
681 xpath, xpath_wild, obj)
682 yield from self.publisher.publish(xpath_wild, xpath, obj)
683
684 # Publish ping_pong_nsd
685 xpath = XPaths.nsd(self.nsd_id)
686 xpath_wild = XPaths.nsd()
687 for obj in self.ping_pong_nsd.descriptor.nsd:
688 self.log.debug("Publishing ping_pong nsd path: %s, wild_path: %s, obj:%s",
689 xpath, xpath_wild, obj)
690 yield from self.publisher.publish(xpath_wild, xpath, obj)
691
692 self.log.debug("DONE - publish_desciptors")
693
694 def unpublish_descriptors(self):
695 self.publisher.unpublish_all()
696
697 @asyncio.coroutine
698 def delete_nsd(self):
699 yield from self.querier.delete_nsd(self.ping_pong_nsd.id)
700
701 @asyncio.coroutine
702 def delete_ping_vnfd(self):
703 yield from self.querier.delete_vnfd(self.ping_vnfd.id)
704
705 @asyncio.coroutine
706 def update_nsd(self):
707 yield from self.querier.update_nsd(
708 self.ping_pong_nsd.id,
709 self.ping_pong_nsd.descriptor.nsd[0]
710 )
711
712 @asyncio.coroutine
713 def update_ping_vnfd(self):
714 yield from self.querier.update_vnfd(
715 self.ping_vnfd.id,
716 self.ping_vnfd.descriptor.vnfd[0]
717 )
718
719
720
721
722 class ManoTestCase(rift.test.dts.AbstractDTSTest):
723 """
724 DTS GI interface unittests
725
726 Note: Each tests uses a list of asyncio.Events for staging through the
727 test. These are required here because we are bring up each coroutine
728 ("tasklet") at the same time and are not implementing any re-try
729 mechanisms. For instance, this is used in numerous tests to make sure that
730 a publisher is up and ready before the subscriber sends queries. Such
731 event lists should not be used in production software.
732 """
733
734 @classmethod
735 def configure_suite(cls, rwmain):
736 vns_dir = os.environ.get('VNS_DIR')
737 vnfm_dir = os.environ.get('VNFM_DIR')
738 nsm_dir = os.environ.get('NSM_DIR')
739 rm_dir = os.environ.get('RM_DIR')
740
741 rwmain.add_tasklet(vns_dir, 'rwvnstasklet')
742 rwmain.add_tasklet(vnfm_dir, 'rwvnfmtasklet')
743 rwmain.add_tasklet(nsm_dir, 'rwnsmtasklet')
744 rwmain.add_tasklet(rm_dir, 'rwresmgrtasklet')
745 rwmain.add_tasklet(rm_dir, 'rwconmantasklet')
746
747 @classmethod
748 def configure_schema(cls):
749 return rwnsmyang.get_schema()
750
751 @classmethod
752 def configure_timeout(cls):
753 return 240
754
755 @staticmethod
756 def get_cal_account(account_type, account_name):
757 """
758 Creates an object for class RwcalYang.Clo
759 """
760 account = rwcloudyang.CloudAccount()
761 if account_type == 'mock':
762 account.name = account_name
763 account.account_type = "mock"
764 account.mock.username = "mock_user"
765 elif ((account_type == 'openstack_static') or (account_type == 'openstack_dynamic')):
766 account.name = account_name
767 account.account_type = 'openstack'
768 account.openstack.key = openstack_info['username']
769 account.openstack.secret = openstack_info['password']
770 account.openstack.auth_url = openstack_info['auth_url']
771 account.openstack.tenant = openstack_info['project_name']
772 account.openstack.mgmt_network = openstack_info['mgmt_network']
773 return account
774
775 @asyncio.coroutine
776 def configure_cloud_account(self, dts, cloud_type, cloud_name="cloud1"):
777 account = self.get_cal_account(cloud_type, cloud_name)
778 account_xpath = "C,/rw-cloud:cloud/rw-cloud:account[rw-cloud:name='{}']".format(cloud_name)
779 self.log.info("Configuring cloud-account: %s", account)
780 yield from dts.query_create(account_xpath,
781 rwdts.XactFlag.ADVISE,
782 account)
783
784 @asyncio.coroutine
785 def wait_tasklets(self):
786 yield from asyncio.sleep(5, loop=self.loop)
787
788 def configure_test(self, loop, test_id):
789 self.log.debug("STARTING - %s", self.id())
790 self.tinfo = self.new_tinfo(self.id())
791 self.dts = rift.tasklets.DTS(self.tinfo, self.schema, self.loop)
792 self.ping_pong = PingPongDescriptorPublisher(self.log, self.loop, self.dts)
793 self.querier = ManoQuerier(self.log, self.dts)
794 self.nsr_publisher = PingPongNsrConfigPublisher(
795 self.log,
796 loop,
797 self.dts,
798 self.ping_pong,
799 "mock_account",
800 )
801
802 def test_create_nsr_record(self):
803
804 @asyncio.coroutine
805 def verify_cm_state(termination=False, nsrid=None):
806 self.log.debug("Verifying cm_state path = %s", XPaths.cm_state(nsrid))
807 #print("###>>> Verifying cm_state path:", XPaths.cm_state(nsrid))
808
809 loop_count = 10
810 loop_sleep = 10
811 while loop_count:
812 yield from asyncio.sleep(loop_sleep, loop=self.loop)
813 loop_count -= 1
814 cm_nsr = None
815 cm_nsr_i = yield from self.querier.get_cm_state(nsr_id=nsrid)
816 if (cm_nsr_i is not None and len(cm_nsr_i) != 0):
817 self.assertEqual(1, len(cm_nsr_i))
818 cm_nsr = cm_nsr_i[0].as_dict()
819 #print("###>>> cm_nsr=", cm_nsr)
820 if termination:
821 if len(cm_nsr_i) == 0:
822 print("\n###>>> cm-state NSR deleted OK <<<###\n")
823 return
824 elif (cm_nsr is not None and
825 'state' in cm_nsr and
826 (cm_nsr['state'] == 'ready')):
827 self.log.debug("Got cm_nsr record %s", cm_nsr)
828 print("\n###>>> cm-state NSR 'ready' OK <<<###\n")
829 return
830
831 # if (len(cm_nsr_i) == 1 and cm_nsr_i[0].state == 'ready'):
832 # self.log.debug("Got cm_nsr record %s", cm_nsr)
833 # else:
834 # yield from asyncio.sleep(10, loop=self.loop)
835
836 print("###>>> Failed cm-state, termination:", termination)
837 self.assertEqual(1, loop_count)
838
839 @asyncio.coroutine
840 def verify_nsr_opdata(termination=False):
841 self.log.debug("Verifying nsr opdata path = %s", XPaths.nsr_opdata())
842
843 while True:
844 nsrs = yield from self.querier.get_nsr_opdatas()
845 if termination:
846 if len(nsrs) != 0:
847 for i in range(10):
848 nsrs = yield from self.querier.get_nsr_opdatas()
849 if len(nsrs) == 0:
850 self.log.debug("No active NSR records found. NSR termination successful")
851 return
852 else:
853 self.assertEqual(0, len(nsrs))
854 self.log.error("Active NSR records found. NSR termination failed")
855
856 else:
857 self.log.debug("No active NSR records found. NSR termination successful")
858 self.assertEqual(0, len(nsrs))
859 return
860
861 nsr = nsrs[0]
862 self.log.debug("Got nsr record %s", nsr)
863 if nsr.operational_status == 'running':
864 self.log.debug("!!! Rcvd NSR with running status !!!")
865 self.assertEqual("configuring", nsr.config_status)
866 break
867
868 self.log.debug("Rcvd NSR with %s status", nsr.operational_status)
869 self.log.debug("Sleeping for 10 seconds")
870 yield from asyncio.sleep(10, loop=self.loop)
871
872 @asyncio.coroutine
873 def verify_nsr_config(termination=False):
874 self.log.debug("Verifying nsr config path = %s", XPaths.nsr_config())
875
876 nsr_configs = yield from self.querier.get_nsr_configs()
877 self.assertEqual(1, len(nsr_configs))
878
879 nsr_config = nsr_configs[0]
880 self.assertEqual(
881 "/nsd:nsd-catalog/nsd:nsd[nsd:id={}]/nsd:name".format(self.ping_pong.nsd_id),
882 nsr_config.input_parameter[0].xpath,
883 )
884
885 @asyncio.coroutine
886 def verify_nsr_config_status(termination=False, nsrid=None):
887 if termination is False and nsrid is not None:
888 self.log.debug("Verifying nsr config status path = %s", XPaths.nsr_opdata(nsrid))
889
890 loop_count = 6
891 loop_sleep = 10
892 while loop_count:
893 loop_count -= 1
894 yield from asyncio.sleep(loop_sleep, loop=self.loop)
895 nsr_opdata_l = yield from self.querier.get_nsr_opdatas(nsrid)
896 self.assertEqual(1, len(nsr_opdata_l))
897 nsr_opdata = nsr_opdata_l[0].as_dict()
898 if ("configured" == nsr_opdata['config_status']):
899 print("\n###>>> NSR Config Status 'configured' OK <<<###\n")
900 return
901 self.assertEqual("configured", nsr_opdata['config_status'])
902
903 @asyncio.coroutine
904 def verify_vnfr_record(termination=False):
905 self.log.debug("Verifying vnfr record path = %s, Termination=%d",
906 XPaths.vnfr(), termination)
907 if termination:
908 for i in range(10):
909 vnfrs = yield from self.querier.get_vnfrs()
910 if len(vnfrs) == 0:
911 return True
912
913 for vnfr in vnfrs:
914 self.log.debug("VNFR still exists = %s", vnfr)
915
916 yield from asyncio.sleep(.5, loop=self.loop)
917
918
919 assert len(vnfrs) == 0
920
921 while True:
922 vnfrs = yield from self.querier.get_vnfrs()
923 if len(vnfrs) != 0 and termination is False:
924 vnfr = vnfrs[0]
925 self.log.debug("Rcvd VNFR with %s status", vnfr.operational_status)
926 if vnfr.operational_status == 'running':
927 self.log.debug("!!! Rcvd VNFR with running status !!!")
928 return True
929
930 elif vnfr.operational_status == "failed":
931 self.log.debug("!!! Rcvd VNFR with failed status !!!")
932 return False
933
934 self.log.debug("Sleeping for 10 seconds")
935 yield from asyncio.sleep(10, loop=self.loop)
936
937
938 @asyncio.coroutine
939 def verify_vnfr_cloud_account(vnf_index, cloud_account):
940 self.log.debug("Verifying vnfr record Cloud account for vnf index = %d is %s", vnf_index,cloud_account)
941 vnfrs = yield from self.querier.get_vnfrs()
942 cloud_accounts = [vnfr.cloud_account for vnfr in vnfrs if vnfr.member_vnf_index_ref == vnf_index]
943 self.log.debug("VNFR cloud account for index %d is %s", vnf_index,cloud_accounts[0])
944 assert cloud_accounts[0] == cloud_account
945
946 @asyncio.coroutine
947 def verify_vlr_record(termination=False):
948 vlr_xpath = XPaths.vlr()
949 self.log.debug("Verifying vlr record path = %s, termination: %s",
950 vlr_xpath, termination)
951 res_iter = yield from self.dts.query_read(vlr_xpath)
952
953 for i in res_iter:
954 result = yield from i
955 if termination:
956 self.assertIsNone(result)
957
958 self.log.debug("Got vlr record %s", result)
959
960 @asyncio.coroutine
961 def verify_vlrs(nsr_id, count=0):
962 while True:
963 nsrs = yield from self.querier.get_nsr_opdatas()
964 nsr = nsrs[0]
965 self.log.debug("Got nsr record %s", nsr)
966 if nsr.operational_status == 'running':
967 self.log.debug("!!! Rcvd NSR with running status !!!")
968 # Check the VLR count
969 if (len(nsr.vlr)) == count:
970 self.log.debug("NSR %s has %d VLRs", nsr_id, count)
971 break
972
973 self.log.debug("Rcvd NSR %s with %s status", nsr_id, nsr.operational_status)
974 self.log.debug("Sleeping for 10 seconds")
975 yield from asyncio.sleep(10, loop=self.loop)
976
977 @asyncio.coroutine
978 def verify_nsd_ref_count(termination):
979 self.log.debug("Verifying nsd ref count= %s", XPaths.nsd_ref_count())
980 res_iter = yield from self.dts.query_read(XPaths.nsd_ref_count())
981
982 for i in res_iter:
983 result = yield from i
984 self.log.debug("Got nsd ref count record %s", result)
985
986 @asyncio.coroutine
987 def verify_vnfd_ref_count(termination):
988 self.log.debug("Verifying vnfd ref count= %s", XPaths.vnfd_ref_count())
989 res_iter = yield from self.dts.query_read(XPaths.vnfd_ref_count())
990
991 for i in res_iter:
992 result = yield from i
993 self.log.debug("Got vnfd ref count record %s", result)
994
995 @asyncio.coroutine
996 def verify_scale_group_reaches_state(nsr_id, scale_group, index, state, timeout=1000):
997 start_time = time.time()
998 instance_state = None
999 while (time.time() - start_time) < timeout:
1000 results = yield from self.querier.get_nsr_opdatas(nsr_id=nsr_id)
1001 if len(results) == 1:
1002 result = results[0]
1003 if len(result.scaling_group_record) == 0:
1004 continue
1005
1006 if len(result.scaling_group_record[0].instance) == 0:
1007 continue
1008
1009 instance = result.scaling_group_record[0].instance[0]
1010 self.assertEqual(instance.scaling_group_index_ref, index)
1011
1012 instance_state = instance.op_status
1013 if instance_state == state:
1014 self.log.debug("Scale group instance reached %s state", state)
1015 return
1016
1017 yield from asyncio.sleep(1, loop=self.loop)
1018
1019 self.assertEqual(state, instance_state)
1020
1021 @asyncio.coroutine
1022 def verify_results(termination=False, nsrid=None):
1023 yield from verify_vnfr_record(termination)
1024 #yield from verify_vlr_record(termination)
1025 yield from verify_nsr_opdata(termination)
1026 yield from verify_nsr_config(termination)
1027 yield from verify_nsd_ref_count(termination)
1028 yield from verify_vnfd_ref_count(termination)
1029
1030 # Config Manager
1031 yield from verify_cm_state(termination, nsrid)
1032 yield from verify_nsr_config_status(termination, nsrid)
1033
1034 @asyncio.coroutine
1035 def verify_scale_instance(index):
1036 self.log.debug("Verifying scale record path = %s, Termination=%d",
1037 XPaths.vnfr(), termination)
1038 if termination:
1039 for i in range(5):
1040 vnfrs = yield from self.querier.get_vnfrs()
1041 if len(vnfrs) == 0:
1042 return True
1043
1044 for vnfr in vnfrs:
1045 self.log.debug("VNFR still exists = %s", vnfr)
1046
1047
1048 assert len(vnfrs) == 0
1049
1050 while True:
1051 vnfrs = yield from self.querier.get_vnfrs()
1052 if len(vnfrs) != 0 and termination is False:
1053 vnfr = vnfrs[0]
1054 self.log.debug("Rcvd VNFR with %s status", vnfr.operational_status)
1055 if vnfr.operational_status == 'running':
1056 self.log.debug("!!! Rcvd VNFR with running status !!!")
1057 return True
1058
1059 elif vnfr.operational_status == "failed":
1060 self.log.debug("!!! Rcvd VNFR with failed status !!!")
1061 return False
1062
1063 self.log.debug("Sleeping for 10 seconds")
1064 yield from asyncio.sleep(10, loop=self.loop)
1065
1066 @asyncio.coroutine
1067 def terminate_ns(nsr_id):
1068 xpath = XPaths.nsr_config(nsr_id)
1069 self.log.debug("Terminating network service with path %s", xpath)
1070 yield from self.dts.query_delete(xpath, flags=rwdts.XactFlag.ADVISE)
1071 self.log.debug("Terminated network service with path %s", xpath)
1072
1073 @asyncio.coroutine
1074 def run_test():
1075 yield from self.wait_tasklets()
1076
1077
1078 cloud_type = "mock"
1079 yield from self.configure_cloud_account(self.dts, cloud_type, "mock_account")
1080 yield from self.configure_cloud_account(self.dts, cloud_type, "mock_account1")
1081
1082 yield from self.ping_pong.publish_desciptors()
1083
1084 # Attempt deleting VNFD not in use
1085 yield from self.ping_pong.update_ping_vnfd()
1086
1087 # Attempt updating NSD not in use
1088 yield from self.ping_pong.update_nsd()
1089
1090 # Attempt deleting VNFD not in use
1091 yield from self.ping_pong.delete_ping_vnfd()
1092
1093 # Attempt deleting NSD not in use
1094 yield from self.ping_pong.delete_nsd()
1095
1096 yield from self.ping_pong.publish_desciptors()
1097
1098 nsr_id = yield from self.nsr_publisher.publish()
1099
1100 yield from verify_results(nsrid=nsr_id)
1101
1102 # yield from self.nsr_publisher.create_scale_group_instance("ping_group", 1)
1103
1104 # yield from verify_scale_group_reaches_state(nsr_id, "ping_group", 1, "running")
1105
1106 # yield from self.nsr_publisher.delete_scale_group_instance("ping_group", 1)
1107
1108 yield from asyncio.sleep(10, loop=self.loop)
1109
1110 # Attempt deleting VNFD in use
1111 yield from self.ping_pong.delete_ping_vnfd()
1112
1113 # Attempt updating NSD in use
1114 yield from self.ping_pong.update_nsd()
1115
1116 # Update NSD in use with new VL
1117 yield from self.nsr_publisher.add_nsr_vl()
1118
1119 # Verify the new VL has been added
1120 yield from verify_vlrs(nsr_id, count=2)
1121
1122 # Delete the added VL
1123 yield from self.nsr_publisher.del_nsr_vl()
1124
1125 # Verify the new VL has been added
1126 yield from verify_vlrs(nsr_id, count=1)
1127
1128 # Attempt deleting NSD in use
1129 yield from self.ping_pong.delete_nsd()
1130
1131 yield from terminate_ns(nsr_id)
1132
1133 yield from asyncio.sleep(25, loop=self.loop)
1134 self.log.debug("Verifying termination results")
1135 yield from verify_results(termination=True, nsrid=nsr_id)
1136 self.log.debug("Verified termination results")
1137
1138 # Multi site NS case
1139 self.log.debug("Testing multi site NS")
1140 self.nsr_publisher.update_vnf_cloud_map({1:"mock_account1",2:"mock_account"})
1141 nsr_id = yield from self.nsr_publisher.publish()
1142
1143 yield from verify_results(nsrid=nsr_id)
1144 yield from verify_vnfr_cloud_account(1,"mock_account1")
1145 yield from verify_vnfr_cloud_account(2,"mock_account")
1146 yield from verify_vlrs(nsr_id, count=2)
1147
1148 yield from terminate_ns(nsr_id)
1149
1150 yield from asyncio.sleep(25, loop=self.loop)
1151 self.log.debug("Verifying termination results for multi site NS")
1152 yield from verify_results(termination=True, nsrid=nsr_id)
1153 self.log.debug("Verified termination results for multi site NS")
1154
1155 self.log.debug("Attempting to delete VNFD for real")
1156 yield from self.ping_pong.delete_ping_vnfd()
1157
1158 self.log.debug("Attempting to delete NSD for real")
1159 yield from self.ping_pong.delete_nsd()
1160
1161 future = asyncio.ensure_future(run_test(), loop=self.loop)
1162 self.run_until(future.done)
1163 if future.exception() is not None:
1164 self.log.error("Caught exception during test")
1165 raise future.exception()
1166
1167
1168 def main():
1169 plugin_dir = os.path.join(os.environ["RIFT_INSTALL"], "usr/lib/rift/plugins")
1170 if 'VNS_DIR' not in os.environ:
1171 os.environ['VNS_DIR'] = os.path.join(plugin_dir, 'rwvns')
1172
1173 if 'VNFM_DIR' not in os.environ:
1174 os.environ['VNFM_DIR'] = os.path.join(plugin_dir, 'rwvnfm')
1175
1176 if 'NSM_DIR' not in os.environ:
1177 os.environ['NSM_DIR'] = os.path.join(plugin_dir, 'rwnsm')
1178
1179 if 'RM_DIR' not in os.environ:
1180 os.environ['RM_DIR'] = os.path.join(plugin_dir, 'rwresmgrtasklet')
1181
1182 runner = xmlrunner.XMLTestRunner(output=os.environ["RIFT_MODULE_TEST"])
1183
1184 parser = argparse.ArgumentParser()
1185 parser.add_argument('-v', '--verbose', action='store_true')
1186 parser.add_argument('-n', '--no-runner', action='store_true')
1187 args, unittest_args = parser.parse_known_args()
1188 if args.no_runner:
1189 runner = None
1190
1191 ManoTestCase.log_level = logging.DEBUG if args.verbose else logging.WARN
1192
1193 unittest.main(testRunner=runner, argv=[sys.argv[0]] + unittest_args)
1194
1195 if __name__ == '__main__':
1196 main()
1197
1198 # vim: sw=4