4 # Copyright 2016-2017 RIFT.IO Inc
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
10 # http://www.apache.org/licenses/LICENSE-2.0
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
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')
42 from gi
.repository
import (
43 RwCloudYang
as rwcloudyang
,
45 RwLaunchpadYang
as launchpadyang
,
46 RwNsmYang
as rwnsmyang
,
47 RwNsrYang
as rwnsryang
,
49 RwResourceMgrYang
as rmgryang
,
50 RwcalYang
as rwcalyang
,
51 RwConfigAgentYang
as rwcfg_agent
,
55 from gi
.repository
.RwTypes
import RwStatus
56 import rift
.mano
.examples
.ping_pong_nsd
as ping_pong_nsd
60 from rift
.mano
.utils
.project
import (
70 'password': 'mypasswd',
71 'auth_url': 'http://10.66.4.27:5000/v3/',
72 'project_name': 'demo',
73 'mgmt_network': 'private',
77 if sys
.version_info
< (3, 4, 4):
78 asyncio
.ensure_future
= asyncio
.async
84 return ("C,/project-nsd:nsd-catalog/project-nsd:nsd" +
85 ("[project-nsd:id='{}']".format(k
) if k
is not None else ""))
89 return ("C,/vld:vld-catalog/vld:vld" +
90 ("[vld:id='{}']".format(k
) if k
is not None else ""))
94 return ("C,/project-vnfd:vnfd-catalog/project-vnfd:vnfd" +
95 ("[project-vnfd:id='{}']".format(k
) if k
is not None else ""))
99 return ("D,/vnfr:vnfr-catalog/vnfr:vnfr" +
100 ("[vnfr:id='{}']".format(k
) if k
is not None else ""))
104 return ("D,/vlr:vlr-catalog/vlr:vlr" +
105 ("[vlr:id='{}']".format(k
) if k
is not None else ""))
108 def nsd_ref_count(k
=None):
109 return ("D,/nsr:ns-instance-opdata/rw-nsr:nsd-ref-count" +
110 ("[rw-nsr:nsd-id-ref='{}']".format(k
) if k
is not None else ""))
113 def vnfd_ref_count(k
=None):
114 return ("D,/vnfr:vnfr-catalog/rw-vnfr:vnfd-ref-count" +
115 ("[rw-nsr:nsd-id-ref='{}']".format(k
) if k
is not None else ""))
118 def nsr_config(k
=None):
119 return ("C,/nsr:ns-instance-config/nsr:nsr" +
120 ("[nsr:id='{}']".format(k
) if k
is not None else ""))
123 def nsr_opdata(k
=None):
124 return ("D,/nsr:ns-instance-opdata/nsr:nsr" +
125 ("[nsr:ns-instance-config-ref='{}']".format(k
) if k
is not None else ""))
128 def nsr_config_status(k
=None):
129 return ("D,/nsr:ns-instance-opdata/nsr:nsr" +
130 ("[nsr:ns-instance-config-ref='{}']/config_status".format(k
) if k
is not None else ""))
133 def cm_state(k
=None):
134 return ("D,/rw-conman:cm-state/rw-conman:cm-nsr" +
135 ("[rw-conman:id='{}']".format(k
) if k
is not None else ""))
138 def nsr_scale_group_instance(nsr_id
=None, group_name
=None, index
=None):
139 return (("D,/nsr:ns-instance-opdata/nsr:nsr") +
140 ("[nsr:ns-instance-config-ref='{}']".format(nsr_id
) if nsr_id
is not None else "") +
141 ("/nsr:scaling-group-record") +
142 ("[nsr:scaling-group-name-ref='{}']".format(group_name
) if group_name
is not None else "") +
144 ("[nsr:scaling-group-index-ref='{}']".format(index
) if index
is not None else ""))
147 def nsr_scale_group_instance_config(nsr_id
=None, group_name
=None, index
=None):
148 return (("C,/nsr:ns-instance-config/nsr:nsr") +
149 ("[nsr:id='{}']".format(nsr_id
) if nsr_id
is not None else "") +
150 ("/nsr:scaling-group") +
151 ("[nsr:scaling-group-name-ref='{}']".format(group_name
) if group_name
is not None else "") +
153 ("[nsr:index='{}']".format(index
) if index
is not None else ""))
156 def cloud_account(k
=None):
157 return ("C,/rw-cloud:cloud/rw-cloud:account" +
158 ("[rw-cloud:name='{}']".format(k
) if k
is not None else ""))
162 return ("C,/rw-project:project" +
163 ("[rw-project:name='{}']".format(k
) if k
is not None else ""))
166 class ManoQuerier(object):
167 def __init__(self
, log
, dts
, project
):
170 self
.project
= project
172 def add_project(self
, xpath
):
173 return self
.project
.add_project(xpath
)
176 def _read_query(self
, xpath
, do_trace
=False, project
=True):
178 xp
= self
.add_project(xpath
)
181 self
.log
.debug("Running XPATH read query: %s (trace: %s)", xp
, do_trace
)
182 flags
= rwdts
.XactFlag
.MERGE
183 flags
+= rwdts
.XactFlag
.TRACE
if do_trace
else 0
184 res_iter
= yield from self
.dts
.query_read(
190 result
= yield from i
191 if result
is not None:
192 results
.append(result
.result
)
197 def _delete_query(self
, xpath
, flags
=0):
198 xp
= self
.add_project(xpath
)
199 self
.log
.debug("Running XPATH delete query: %s (flags: %d)", xp
, flags
)
200 with self
.dts
.transaction() as xact
:
201 yield from self
.dts
.query_delete(
207 def _update_query(self
, xpath
, msg
, flags
=0):
208 xp
= self
.add_project(xpath
)
209 self
.log
.debug("Running XPATH update query: %s (flags: %d)", xp
, flags
)
210 with self
.dts
.transaction() as xact
:
211 yield from self
.dts
.query_update(
218 def get_cm_state(self
, nsr_id
=None):
219 return (yield from self
._read
_query
(XPaths
.cm_state(nsr_id
), False))
222 def get_nsr_opdatas(self
, nsr_id
=None):
223 return (yield from self
._read
_query
(XPaths
.nsr_opdata(nsr_id
), False))
226 def get_nsr_scale_group_instance_opdata(self
, nsr_id
=None, group_name
=None, index
=None):
227 return (yield from self
._read
_query
(XPaths
.nsr_scale_group_instance(nsr_id
, group_name
, index
), False))
230 def get_nsr_configs(self
, nsr_id
=None):
231 return (yield from self
._read
_query
(XPaths
.nsr_config(nsr_id
)))
234 def get_nsr_config_status(self
, nsr_id
=None):
235 return (yield from self
._read
_query
(XPaths
.nsr_config_status(nsr_id
)))
238 def get_vnfrs(self
, vnfr_id
=None):
239 return (yield from self
._read
_query
(XPaths
.vnfr(vnfr_id
)))
242 def get_vlrs(self
, vlr_id
=None):
243 return (yield from self
._read
_query
(XPaths
.vlr(vlr_id
)))
246 def get_nsd_ref_counts(self
, nsd_id
=None):
247 return (yield from self
._read
_query
(XPaths
.nsd_ref_count(nsd_id
)))
250 def get_vnfd_ref_counts(self
, vnfd_id
=None):
251 return (yield from self
._read
_query
(XPaths
.vnfd_ref_count(vnfd_id
)))
254 def delete_nsr(self
, nsr_id
):
255 return (yield from self
._delete
_query
(XPaths
.nsr_config(nsr_id
)))
258 def delete_nsd(self
, nsd_id
):
259 return (yield from self
._delete
_query
(XPaths
.nsd(nsd_id
),
260 rwdts
.XactFlag
.ADVISE
))
263 def delete_vnfd(self
, vnfd_id
):
264 return (yield from self
._delete
_query
(XPaths
.vnfd(vnfd_id
),
265 rwdts
.XactFlag
.ADVISE
))
268 def update_nsd(self
, nsd_id
, nsd_msg
):
269 return (yield from self
._update
_query
(XPaths
.nsd(nsd_id
), nsd_msg
,
270 rwdts
.XactFlag
.ADVISE
))
273 def update_vnfd(self
, vnfd_id
, vnfd_msg
):
274 return (yield from self
._update
_query
(XPaths
.vnfd(vnfd_id
), vnfd_msg
,
275 rwdts
.XactFlag
.ADVISE
))
278 def update_nsr_config(self
, nsr_id
, nsr_msg
):
279 return (yield from self
._update
_query
(
280 XPaths
.nsr_config(nsr_id
),
282 rwdts
.XactFlag
.ADVISE|rwdts
.XactFlag
.REPLACE
))
285 class ManoTestCase(rift
.test
.dts
.AbstractDTSTest
):
287 def verify_nsr_state(self
, nsr_id
, state
):
288 nsrs
= yield from self
.querier
.get_nsr_opdatas(nsr_id
)
289 self
.assertEqual(1, len(nsrs
))
292 self
.log
.debug("Got nsr = %s", nsr
)
293 self
.assertEqual(state
, nsr
.operational_status
)
296 def verify_vlr_state(self
, vlr_id
, state
):
297 vlrs
= yield from self
.querier
.get_vlrs(vlr_id
)
298 self
.assertEqual(1, len(vlrs
))
301 self
.assertEqual(state
, vlr
.operational_status
)
303 def verify_vdu_state(self
, vdu
, state
):
304 self
.assertEqual(state
, vdu
.operational_status
)
307 def verify_vnf_state(self
, vnfr_id
, state
):
308 vnfrs
= yield from self
.querier
.get_vnfrs(vnfr_id
)
309 self
.assertEqual(1, len(vnfrs
))
312 self
.assertEqual(state
, vnfr
.operational_status
)
315 def terminate_nsr(self
, nsr_id
):
316 self
.log
.debug("Terminating nsr id: %s", nsr_id
)
317 yield from self
.querier
.delete_nsr(nsr_id
)
320 def verify_nsr_deleted(self
, nsr_id
):
321 nsr_opdatas
= yield from self
.querier
.get_nsr_opdatas(nsr_id
)
322 self
.assertEqual(0, len(nsr_opdatas
))
324 nsr_configs
= yield from self
.querier
.get_nsr_configs(nsr_id
)
325 self
.assertEqual(0, len(nsr_configs
))
328 def verify_num_vlrs(self
, num_vlrs
):
329 vlrs
= yield from self
.querier
.get_vlrs()
330 self
.assertEqual(num_vlrs
, len(vlrs
))
333 def get_nsr_vlrs(self
, nsr_id
):
334 nsrs
= yield from self
.querier
.get_nsr_opdatas(nsr_id
)
335 return [v
.vlr_ref
for v
in nsrs
[0].vlr
]
338 def get_nsr_vnfs(self
, nsr_id
):
339 nsrs
= yield from self
.querier
.get_nsr_opdatas(nsr_id
)
340 return nsrs
[0].constituent_vnfr_ref
343 def get_vnf_vlrs(self
, vnfr_id
):
344 vnfrs
= yield from self
.querier
.get_vnfrs(vnfr_id
)
345 return [i
.vlr_ref
for i
in vnfrs
[0].internal_vlr
]
348 def verify_num_nsr_vlrs(self
, nsr_id
, num_vlrs
):
349 vlrs
= yield from self
.get_nsr_vlrs(nsr_id
)
350 self
.assertEqual(num_vlrs
, len(vlrs
))
353 def verify_num_nsr_vnfrs(self
, nsr_id
, num_vnfs
):
354 vnfs
= yield from self
.get_nsr_vnfs(nsr_id
)
355 self
.assertEqual(num_vnfs
, len(vnfs
))
358 def verify_num_vnfr_vlrs(self
, vnfr_id
, num_vlrs
):
359 vlrs
= yield from self
.get_vnf_vlrs(vnfr_id
)
360 self
.assertEqual(num_vlrs
, len(vlrs
))
363 def get_vnf_vdus(self
, vnfr_id
):
364 vnfrs
= yield from self
.querier
.get_vnfrs(vnfr_id
)
365 return [i
for i
in vnfrs
[0].vdur
]
368 def verify_num_vnfr_vdus(self
, vnfr_id
, num_vdus
):
369 vdus
= yield from self
.get_vnf_vdus(vnfr_id
)
370 self
.assertEqual(num_vdus
, len(vdus
))
373 def verify_num_vnfrs(self
, num_vnfrs
):
374 vnfrs
= yield from self
.querier
.get_vnfrs()
375 self
.assertEqual(num_vnfrs
, len(vnfrs
))
378 def verify_nsd_ref_count(self
, nsd_id
, num_ref
):
379 nsd_ref_counts
= yield from self
.querier
.get_nsd_ref_counts(nsd_id
)
380 self
.assertEqual(num_ref
, nsd_ref_counts
[0].instance_ref_count
)
383 class DescriptorPublisher(object):
384 def __init__(self
, log
, loop
, dts
, project
):
388 self
.project
= project
390 self
._registrations
= []
393 def publish(self
, w_path
, path
, desc
):
394 ready_event
= asyncio
.Event(loop
=self
.loop
)
395 if 'rw-project' in path
:
399 w_xp
= self
.project
.add_project(w_path
)
400 xp
= self
.project
.add_project(path
)
403 def on_ready(regh
, status
):
404 self
.log
.debug("Create element: %s, obj-type:%s obj:%s",
405 xp
, type(desc
), desc
)
406 with self
.dts
.transaction() as xact
:
407 regh
.create_element(xp
, desc
, xact
.xact
)
408 self
.log
.debug("Created element: %s, obj:%s", xp
, desc
)
411 handler
= rift
.tasklets
.DTS
.RegistrationHandler(
415 self
.log
.debug("Registering path: %s, obj:%s", w_xp
, desc
)
416 reg
= yield from self
.dts
.register(
419 flags
=rwdts
.Flag
.PUBLISHER | rwdts
.Flag
.NO_PREP_READ
421 self
._registrations
.append(reg
)
422 self
.log
.debug("Registered path : %s", w_xp
)
423 yield from ready_event
.wait()
427 def unpublish_all(self
):
428 self
.log
.debug("Deregistering all published descriptors")
429 for reg
in self
._registrations
:
433 class ProjectPublisher(object):
434 XPATH
= "C,/rw-project:project"
436 def __init__(self
, log
, loop
, dts
, project
):
440 self
.project
= project
443 self
.querier
= ManoQuerier(log
, dts
, project
)
444 self
.publisher
= DescriptorPublisher(log
, loop
,
447 self
._ready
_event
= asyncio
.Event(loop
=self
.loop
)
448 asyncio
.ensure_future(self
.register(), loop
=loop
)
453 def on_ready(regh
, status
):
454 self
._ready
_event
.set()
456 self
.log
.debug("Registering path: %s", ProjectPublisher
.XPATH
)
457 self
.reg
= yield from self
.dts
.register(
458 ProjectPublisher
.XPATH
,
459 flags
=rwdts
.Flag
.PUBLISHER
,
460 handler
=rift
.tasklets
.DTS
.RegistrationHandler(
465 def deregister(self
):
466 if self
.reg
is not None:
467 self
.reg
.deregister()
470 def publish_project(self
, config
, xpath
, xpath_wild
):
472 self
.log
.debug("Publishing cloud_account path: %s - %s, type:%s, obj:%s",
473 xpath
, xpath_wild
, type(config
), config
)
474 yield from self
.publisher
.publish(xpath_wild
, xpath
, config
)
477 class CloudAccountPublisher(object):
478 XPATH
= "C,/rw-cloud:cloud"
480 def __init__(self
, log
, loop
, dts
, project
):
484 self
.project
= project
487 self
.querier
= ManoQuerier(log
, dts
, project
)
488 self
.publisher
= DescriptorPublisher(log
, loop
,
491 self
.xpath
= self
.project
.add_project(CloudAccountPublisher
.XPATH
)
493 self
._ready
_event
= asyncio
.Event(loop
=self
.loop
)
494 asyncio
.ensure_future(self
.register(), loop
=loop
)
499 def on_ready(regh
, status
):
500 self
._ready
_event
.set()
502 self
.log
.debug("Registering path: %s", self
.xpath
)
503 self
.reg
= yield from self
.dts
.register(
505 flags
=rwdts
.Flag
.PUBLISHER
,
506 handler
=rift
.tasklets
.DTS
.RegistrationHandler(
511 def deregister(self
):
512 if self
.reg
is not None:
513 self
.reg
.deregister()
516 def publish_account(self
, account
, xpath
, xpath_wild
):
517 # Publish cloud account
518 self
.log
.debug("Publishing cloud_account path: %s - %s, type:%s, obj:%s",
519 xpath
, xpath_wild
, type(account
), account
)
520 yield from self
.publisher
.publish(xpath_wild
, xpath
, account
)
523 class PingPongNsrConfigPublisher(object):
524 XPATH
= "C,/nsr:ns-instance-config"
526 def __init__(self
, log
, loop
, dts
, ping_pong
, cloud_account_name
, project
):
530 self
.project
= project
533 self
.querier
= ManoQuerier(log
, dts
, project
)
534 self
.xpath
= self
.project
.add_project(PingPongNsrConfigPublisher
.XPATH
)
535 self
.nsr_config
= rwnsryang
.YangData_RwProject_Project_NsInstanceConfig()
537 nsr
= rwnsryang
.YangData_RwProject_Project_NsInstanceConfig_Nsr()
538 nsr
.id = str(uuid
.uuid4())
539 nsr
.name
= "ns1.{}".format(nsr
.id)
540 nsr
.nsd
= nsryang
.YangData_RwProject_Project_NsInstanceConfig_Nsr_Nsd()
541 nsr
.nsd
.from_dict(ping_pong
.ping_pong_nsd
.nsd
.as_dict())
542 nsr
.cloud_account
= cloud_account_name
544 nsr
.vnf_cloud_account_map
.add().from_dict({
545 'member_vnf_index_ref': nsr
.nsd
.constituent_vnfd
[0].member_vnf_index
,
546 'config_agent_account': 'RiftCA',
547 #'cloud_account':'mock_account1'
550 inputs
= nsryang
.YangData_RwProject_Project_NsInstanceConfig_Nsr_InputParameter()
551 inputs
.xpath
= self
.project
.add_project(
552 "/project-nsd:nsd-catalog/project-nsd:nsd[project-nsd:id={}]/project-nsd:name".format(ping_pong
.nsd_id
))
553 inputs
.value
= "inigo montoya"
555 fast_cpu
= {'metadata_key': 'FASTCPU', 'metadata_value': 'True'}
556 self
.create_nsd_placement_group_map(nsr
,
557 group_name
= 'Orcus',
558 cloud_type
= 'openstack',
559 construct_type
= 'host_aggregate',
560 construct_value
= [fast_cpu
])
562 fast_storage
= {'metadata_key': 'FASTSSD', 'metadata_value': 'True'}
563 self
.create_nsd_placement_group_map(nsr
,
564 group_name
= 'Quaoar',
565 cloud_type
= 'openstack',
566 construct_type
= 'host_aggregate',
567 construct_value
= [fast_storage
])
569 fast_cpu
= {'metadata_key': 'BLUE_HW', 'metadata_value': 'True'}
570 self
.create_vnfd_placement_group_map(nsr
,
572 vnfd_id
= ping_pong
.ping_vnfd_id
,
573 cloud_type
= 'openstack',
574 construct_type
= 'host_aggregate',
575 construct_value
= [fast_cpu
])
577 fast_storage
= {'metadata_key': 'YELLOW_HW', 'metadata_value': 'True'}
578 self
.create_vnfd_placement_group_map(nsr
,
579 group_name
= 'Weywot',
580 vnfd_id
= ping_pong
.pong_vnfd_id
,
581 cloud_type
= 'openstack',
582 construct_type
= 'host_aggregate',
583 construct_value
= [fast_storage
])
586 nsr
.input_parameter
.append(inputs
)
589 self
.nsr_config
.nsr
.append(nsr
)
591 self
._ready
_event
= asyncio
.Event(loop
=self
.loop
)
592 asyncio
.ensure_future(self
.register(), loop
=loop
)
597 def on_ready(regh
, status
):
598 self
._ready
_event
.set()
600 self
.log
.debug("Registering path: %s", self
.xpath
)
601 self
.reg
= yield from self
.dts
.register(
603 flags
=rwdts
.Flag
.PUBLISHER
,
604 handler
=rift
.tasklets
.DTS
.RegistrationHandler(
611 self
.log
.debug("Publishing NSR: {}".format(self
.nsr_config
))
612 yield from self
._ready
_event
.wait()
613 with self
.dts
.transaction() as xact
:
614 self
.reg
.create_element(
623 def create_scale_group_instance(self
, group_name
, index
):
625 scaling_group
= self
.nsr_config
.nsr
[0].scaling_group
.add()
626 scaling_group
.from_dict({
627 "scaling_group_name_ref": group_name
,
628 "instance": [{"index": index
}],
630 with self
.dts
.transaction() as xact
:
631 self
.reg
.update_element(
639 def create_nsd_placement_group_map(self
,
645 placement_group
= nsr
.nsd_placement_group_maps
.add()
646 placement_group
.from_dict({
647 "placement_group_ref" : group_name
,
648 "cloud_type" : cloud_type
,
649 construct_type
: construct_value
,
653 def create_vnfd_placement_group_map(self
,
660 placement_group
= nsr
.vnfd_placement_group_maps
.add()
661 placement_group
.from_dict({
662 "placement_group_ref" : group_name
,
663 "vnfd_id_ref" : vnfd_id
,
664 "cloud_type" : cloud_type
,
665 construct_type
: construct_value
,
670 def delete_scale_group_instance(self
, group_name
, index
):
671 self
.log
.debug("Deleting scale group %s instance %s", group_name
, index
)
672 #del self.nsr_config.nsr[0].scaling_group[0].instance[0]
673 xpath
= self
.project
.add_project(
674 XPaths
.nsr_scale_group_instance_config(self
.nsr_config
.nsr
[0].id,
676 yield from self
.dts
.query_delete(xpath
, flags
=rwdts
.XactFlag
.ADVISE
)
678 def deregister(self
):
679 if self
.reg
is not None:
680 self
.reg
.deregister()
682 def create_nsr_vl(self
):
683 vld
= self
.nsr_config
.nsr
[0].nsd
.vld
.add()
684 vld
.id = 'ping_pong_vld_2'
685 vld
.name
= 'ping_pong_vld_2' # hard coded
686 vld
.short_name
= vld
.name
687 vld
.vendor
= 'RIFT.io'
688 vld
.description
= 'Toy VL'
690 vld
.type_yang
= 'ELAN'
692 # cpref = vld.vnfd_connection_point_ref.add()
693 # cpref.member_vnf_index_ref = cp[0]
694 # cpref.vnfd_id_ref = cp[1]
695 # cpref.vnfd_connection_point_ref = cp[2]
697 vld
= self
.nsr_config
.nsr
[0].vl_cloud_account_map
.add()
698 vld
.vld_id_ref
= 'ping_pong_vld_2'
699 vld
.cloud_accounts
= ["mock_account"]
702 def add_nsr_vl(self
):
704 yield from self
.querier
.update_nsr_config(
705 self
.nsr_config
.nsr
[0].id,
706 self
.nsr_config
.nsr
[0],
710 def del_nsr_vl(self
):
711 for vld
in self
.nsr_config
.nsr
[0].nsd
.vld
:
712 if vld
.id == 'ping_pong_vld_2':
713 self
.nsr_config
.nsr
[0].nsd
.vld
.remove(vld
)
716 yield from self
.querier
.update_nsr_config(
717 self
.nsr_config
.nsr
[0].id,
718 self
.nsr_config
.nsr
[0],
721 def update_vnf_cloud_map(self
,vnf_cloud_map
):
722 self
.log
.debug("Modifying NSR to add VNF cloud account map: {}".format(vnf_cloud_map
))
723 for vnf_index
,cloud_acct
in vnf_cloud_map
.items():
724 vnf_maps
= [vnf_map
for vnf_map
in \
725 self
.nsr_config
.nsr
[0].vnf_cloud_account_map \
726 if vnf_index
== vnf_map
.member_vnf_index_ref
]
728 vnf_maps
[0].cloud_account
= cloud_acct
730 self
.nsr_config
.nsr
[0].vnf_cloud_account_map
.add().from_dict({
731 'member_vnf_index_ref':vnf_index
,
732 'cloud_account':cloud_acct
736 class PingPongDescriptorPublisher(object):
737 def __init__(self
, log
, loop
, dts
, project
,
738 num_external_vlrs
=1, num_internal_vlrs
=1, num_ping_vms
=1):
742 self
.project
= project
744 self
.querier
= ManoQuerier(self
.log
, self
.dts
, self
.project
)
745 self
.publisher
= DescriptorPublisher(self
.log
, self
.loop
,
746 self
.dts
, self
.project
)
747 self
.ping_vnfd
, self
.pong_vnfd
, self
.ping_pong_nsd
= \
748 ping_pong_nsd
.generate_ping_pong_descriptors(
750 external_vlr_count
=num_external_vlrs
,
751 internal_vlr_count
=num_internal_vlrs
,
754 use_scale_group
=True,
755 use_mon_params
=False,
758 self
.config_dir
= os
.path
.join(os
.getenv('RIFT_ARTIFACTS'),
760 self
.ping_pong_nsd
.id,
765 return self
.ping_pong_nsd
.id
768 def ping_vnfd_id(self
):
769 return self
.ping_vnfd
.id
772 def pong_vnfd_id(self
):
773 return self
.pong_vnfd
.id
776 def publish_desciptors(self
):
778 xpath
= XPaths
.vnfd(self
.ping_vnfd_id
)
779 xpath_wild
= XPaths
.vnfd()
780 for obj
in self
.ping_vnfd
.descriptor
.vnfd
:
781 self
.log
.debug("Publishing ping_vnfd path: %s - %s, type:%s, obj:%s",
782 xpath
, xpath_wild
, type(obj
), obj
)
783 yield from self
.publisher
.publish(xpath_wild
, xpath
, obj
)
786 xpath
= XPaths
.vnfd(self
.pong_vnfd_id
)
787 xpath_wild
= XPaths
.vnfd()
788 for obj
in self
.pong_vnfd
.descriptor
.vnfd
:
789 self
.log
.debug("Publishing pong_vnfd path: %s, wild_path: %s, obj:%s",
790 xpath
, xpath_wild
, obj
)
791 yield from self
.publisher
.publish(xpath_wild
, xpath
, obj
)
793 # Publish ping_pong_nsd
794 xpath
= XPaths
.nsd(self
.nsd_id
)
795 xpath_wild
= XPaths
.nsd()
796 for obj
in self
.ping_pong_nsd
.descriptor
.nsd
:
797 self
.log
.debug("Publishing ping_pong nsd path: %s, wild_path: %s, obj:%s",
798 xpath
, xpath_wild
, obj
)
799 yield from self
.publisher
.publish(xpath_wild
, xpath
, obj
)
801 self
.log
.debug("DONE - publish_desciptors")
803 def unpublish_descriptors(self
):
804 self
.publisher
.unpublish_all()
807 def delete_nsd(self
):
808 yield from self
.querier
.delete_nsd(self
.ping_pong_nsd
.id)
811 def delete_ping_vnfd(self
):
812 yield from self
.querier
.delete_vnfd(self
.ping_vnfd
.id)
815 def update_nsd(self
):
816 yield from self
.querier
.update_nsd(
817 self
.ping_pong_nsd
.id,
818 self
.ping_pong_nsd
.descriptor
.nsd
[0]
822 def update_ping_vnfd(self
):
823 yield from self
.querier
.update_vnfd(
825 self
.ping_vnfd
.descriptor
.vnfd
[0]
829 class ManoTestCase(rift
.test
.dts
.AbstractDTSTest
):
831 DTS GI interface unittests
833 Note: Each tests uses a list of asyncio.Events for staging through the
834 test. These are required here because we are bring up each coroutine
835 ("tasklet") at the same time and are not implementing any re-try
836 mechanisms. For instance, this is used in numerous tests to make sure that
837 a publisher is up and ready before the subscriber sends queries. Such
838 event lists should not be used in production software.
842 def configure_suite(cls
, rwmain
):
843 vns_dir
= os
.environ
.get('VNS_DIR')
844 vnfm_dir
= os
.environ
.get('VNFM_DIR')
845 nsm_dir
= os
.environ
.get('NSM_DIR')
846 rm_dir
= os
.environ
.get('RM_DIR')
848 rwmain
.add_tasklet(vns_dir
, 'rwvnstasklet')
849 rwmain
.add_tasklet(vnfm_dir
, 'rwvnfmtasklet')
850 rwmain
.add_tasklet(nsm_dir
, 'rwnsmtasklet')
851 rwmain
.add_tasklet(rm_dir
, 'rwresmgrtasklet')
852 rwmain
.add_tasklet(rm_dir
, 'rwconmantasklet')
855 def configure_schema(cls
):
856 return rwnsmyang
.get_schema()
859 def configure_timeout(cls
):
863 def get_cal_account(account_type
, account_name
):
865 Creates an object for class RwcalYang.Cloud
867 account
= rwcloudyang
.CloudAcc()
868 if account_type
== 'mock':
869 account
.name
= account_name
870 account
.account_type
= "mock"
871 account
.mock
.username
= "mock_user"
872 elif ((account_type
== 'openstack_static') or (account_type
== 'openstack_dynamic')):
873 account
.name
= account_name
874 account
.account_type
= 'openstack'
875 account
.openstack
.key
= openstack_info
['username']
876 account
.openstack
.secret
= openstack_info
['password']
877 account
.openstack
.auth_url
= openstack_info
['auth_url']
878 account
.openstack
.tenant
= openstack_info
['project_name']
879 account
.openstack
.mgmt_network
= openstack_info
['mgmt_network']
883 def configure_project(self
, project
=None):
885 project
= self
.project
887 proj_xpath
= "C,{}/project-config".format(project
.prefix
)
888 self
.log
.info("Creating project: {} with {}".
889 format(proj_xpath
, project
.config
.as_dict()))
890 xpath_wild
= "C,/rw-project:project/project-config"
891 yield from self
.project_publisher
.publish_project(project
.config
,
896 def configure_cloud_account(self
, dts
, cloud_type
, cloud_name
="cloud1", project
=None):
897 account
= self
.get_cal_account(cloud_type
, cloud_name
)
898 self
.log
.info("Configuring cloud-account: %s", account
)
900 project
= self
.project
901 xpath
= project
.add_project(XPaths
.cloud_account(account
.name
))
902 xpath_wild
= project
.add_project(XPaths
.cloud_account())
904 # account_xpath = project.add_project(
905 # "C,/rw-cloud:cloud/rw-cloud:account[rw-cloud:name='{}']".format(cloud_name))
906 # yield from dts.query_create(account_xpath,
907 # rwdts.XactFlag.ADVISE,
909 yield from self
.cloud_publisher
.publish_account(account
, xpath
, xpath_wild
)
912 def wait_tasklets(self
):
913 yield from asyncio
.sleep(5, loop
=self
.loop
)
915 def configure_test(self
, loop
, test_id
):
916 self
.log
.debug("STARTING - %s", self
.id())
917 self
.tinfo
= self
.new_tinfo(self
.id())
918 self
.dts
= rift
.tasklets
.DTS(self
.tinfo
, self
.schema
, self
.loop
)
919 self
.project
= ManoProject(self
.log
,
920 name
=DEFAULT_PROJECT
)
921 self
.project1
= ManoProject(self
.log
,
923 self
.ping_pong
= PingPongDescriptorPublisher(self
.log
, self
.loop
,
924 self
.dts
, self
.project
)
925 self
.querier
= ManoQuerier(self
.log
, self
.dts
, self
.project
)
926 self
.project_publisher
= ProjectPublisher(
932 self
.cloud_publisher
= CloudAccountPublisher(
938 self
.nsr_publisher
= PingPongNsrConfigPublisher(
947 def test_create_nsr_record(self
):
950 def verify_projects(termination
=False):
951 self
.log
.debug("Verifying projects = %s", XPaths
.project())
953 accts
= yield from self
.querier
._read
_query
(XPaths
.project(),
957 self
.log
.debug("Project: {}".format(acc
.as_dict()))
958 if acc
.name
not in projs
:
959 projs
.append(acc
.name
)
960 self
.log
.debug("Merged: {}".format(projs
))
961 self
.assertEqual(2, len(projs
))
964 def verify_cloud_accounts(termination
=False):
965 self
.log
.debug("Verifying cloud accounts = %s", XPaths
.cloud_account())
967 accts
= yield from self
.querier
._read
_query
(XPaths
.cloud_account())
968 self
.assertEqual(2, len(accts
))
970 accts
= yield from self
.querier
._read
_query
(
971 self
.project1
.add_project(XPaths
.cloud_account()), project
=False)
972 self
.assertEqual(1, len(accts
))
974 accts
= yield from self
.querier
._read
_query
(
975 "C,/rw-project:project/rw-cloud:cloud/rw-cloud:account",
977 self
.assertEqual(3, len(accts
))
979 accts
= yield from self
.querier
._read
_query
(
980 "C,/rw-project:project/rw-cloud:cloud/rw-cloud:account[rw-cloud:name='mock_account']",
982 self
.assertEqual(2, len(accts
))
985 def verify_cm_state(termination
=False, nsrid
=None):
986 self
.log
.debug("Verifying cm_state path = %s", XPaths
.cm_state(nsrid
))
991 yield from asyncio
.sleep(loop_sleep
, loop
=self
.loop
)
994 cm_nsr_i
= yield from self
.querier
.get_cm_state(nsr_id
=nsrid
)
995 if (cm_nsr_i
is not None and len(cm_nsr_i
) != 0):
996 self
.assertEqual(1, len(cm_nsr_i
))
997 cm_nsr
= cm_nsr_i
[0].as_dict()
998 #print("###>>> cm_nsr=", cm_nsr)
1000 if len(cm_nsr_i
) == 0:
1001 print("\n###>>> cm-state NSR deleted OK <<<###\n")
1003 elif (cm_nsr
is not None and
1004 'state' in cm_nsr
and
1005 (cm_nsr
['state'] == 'ready')):
1006 self
.log
.debug("Got cm_nsr record %s", cm_nsr
)
1007 print("\n###>>> cm-state NSR 'ready' OK <<<###\n")
1010 # if (len(cm_nsr_i) == 1 and cm_nsr_i[0].state == 'ready'):
1011 # self.log.debug("Got cm_nsr record %s", cm_nsr)
1013 # yield from asyncio.sleep(10, loop=self.loop)
1015 print("###>>> Failed cm-state, termination:", termination
)
1016 self
.assertEqual(1, loop_count
)
1019 def verify_nsr_opdata(termination
=False):
1020 self
.log
.debug("Verifying nsr opdata path = %s", XPaths
.nsr_opdata())
1023 nsrs
= yield from self
.querier
.get_nsr_opdatas()
1027 nsrs
= yield from self
.querier
.get_nsr_opdatas()
1029 self
.log
.debug("No active NSR records found. NSR termination successful")
1032 self
.assertEqual(0, len(nsrs
))
1033 self
.log
.error("Active NSR records found. NSR termination failed")
1036 self
.log
.debug("No active NSR records found. NSR termination successful")
1037 self
.assertEqual(0, len(nsrs
))
1041 self
.log
.debug("Got nsr record %s", nsr
)
1042 if nsr
.operational_status
== 'running':
1043 self
.log
.debug("!!! Rcvd NSR with running status !!!")
1044 self
.assertEqual("configuring", nsr
.config_status
)
1047 self
.log
.debug("Rcvd NSR with %s status", nsr
.operational_status
)
1048 self
.log
.debug("Sleeping for 10 seconds")
1049 yield from asyncio
.sleep(10, loop
=self
.loop
)
1052 def verify_nsr_config(termination
=False):
1053 self
.log
.debug("Verifying nsr config path = %s", XPaths
.nsr_config())
1055 nsr_configs
= yield from self
.querier
.get_nsr_configs()
1056 self
.assertEqual(1, len(nsr_configs
))
1058 nsr_config
= nsr_configs
[0]
1060 "/rw-project:project/project-nsd:nsd-catalog/project-nsd:nsd[project-nsd:id={}]/project-nsd:name".format(self
.ping_pong
.nsd_id
),
1061 nsr_config
.input_parameter
[0].xpath
,
1065 def verify_nsr_config_status(termination
=False, nsrid
=None):
1066 if termination
is False and nsrid
is not None:
1067 self
.log
.debug("Verifying nsr config status path = %s", XPaths
.nsr_opdata(nsrid
))
1073 yield from asyncio
.sleep(loop_sleep
, loop
=self
.loop
)
1074 nsr_opdata_l
= yield from self
.querier
.get_nsr_opdatas(nsrid
)
1075 self
.assertEqual(1, len(nsr_opdata_l
))
1076 nsr_opdata
= nsr_opdata_l
[0].as_dict()
1077 if ("configured" == nsr_opdata
['config_status']):
1078 print("\n###>>> NSR Config Status 'configured' OK <<<###\n")
1080 self
.assertEqual("configured", nsr_opdata
['config_status'])
1083 def verify_vnfr_record(termination
=False):
1084 self
.log
.debug("Verifying vnfr record path = %s, Termination=%d",
1085 XPaths
.vnfr(), termination
)
1088 vnfrs
= yield from self
.querier
.get_vnfrs()
1093 self
.log
.debug("VNFR still exists = %s", vnfr
)
1095 yield from asyncio
.sleep(.5, loop
=self
.loop
)
1098 assert len(vnfrs
) == 0
1101 vnfrs
= yield from self
.querier
.get_vnfrs()
1102 if len(vnfrs
) != 0 and termination
is False:
1104 self
.log
.debug("Rcvd VNFR with %s status", vnfr
.operational_status
)
1105 if vnfr
.operational_status
== 'running':
1106 self
.log
.debug("!!! Rcvd VNFR with running status !!!")
1109 elif vnfr
.operational_status
== "failed":
1110 self
.log
.debug("!!! Rcvd VNFR with failed status !!!")
1113 self
.log
.debug("Sleeping for 10 seconds")
1114 yield from asyncio
.sleep(10, loop
=self
.loop
)
1118 def verify_vnfr_cloud_account(vnf_index
, cloud_account
):
1119 self
.log
.debug("Verifying vnfr record Cloud account for vnf index = %d is %s", vnf_index
,cloud_account
)
1120 vnfrs
= yield from self
.querier
.get_vnfrs()
1121 cloud_accounts
= [vnfr
.cloud_account
for vnfr
in vnfrs
if vnfr
.member_vnf_index_ref
== vnf_index
]
1122 self
.log
.debug("VNFR cloud account for index %d is %s", vnf_index
,cloud_accounts
[0])
1123 assert cloud_accounts
[0] == cloud_account
1126 def verify_vlr_record(termination
=False):
1127 vlr_xpath
= XPaths
.vlr()
1128 self
.log
.debug("Verifying vlr record path = %s, termination: %s",
1129 vlr_xpath
, termination
)
1130 res_iter
= yield from self
.dts
.query_read(vlr_xpath
)
1133 result
= yield from i
1135 self
.assertIsNone(result
)
1137 self
.log
.debug("Got vlr record %s", result
)
1140 def verify_vlrs(nsr_id
, count
=0):
1142 nsrs
= yield from self
.querier
.get_nsr_opdatas()
1144 self
.log
.debug("Got nsr record %s", nsr
)
1145 if nsr
.operational_status
== 'running':
1146 self
.log
.debug("!!! Rcvd NSR with running status !!!")
1147 # Check the VLR count
1148 if (len(nsr
.vlr
)) == count
:
1149 self
.log
.debug("NSR %s has %d VLRs", nsr_id
, count
)
1152 self
.log
.debug("Rcvd NSR %s with %s status", nsr_id
, nsr
.operational_status
)
1153 self
.log
.debug("Sleeping for 10 seconds")
1154 yield from asyncio
.sleep(10, loop
=self
.loop
)
1157 def verify_nsd_ref_count(termination
):
1158 self
.log
.debug("Verifying nsd ref count= %s", XPaths
.nsd_ref_count())
1159 res_iter
= yield from self
.dts
.query_read(XPaths
.nsd_ref_count())
1162 result
= yield from i
1163 self
.log
.debug("Got nsd ref count record %s", result
)
1166 def verify_vnfd_ref_count(termination
):
1167 self
.log
.debug("Verifying vnfd ref count= %s", XPaths
.vnfd_ref_count())
1168 res_iter
= yield from self
.dts
.query_read(XPaths
.vnfd_ref_count())
1171 result
= yield from i
1172 self
.log
.debug("Got vnfd ref count record %s", result
)
1175 def verify_scale_group_reaches_state(nsr_id
, scale_group
, index
, state
, timeout
=1000):
1176 start_time
= time
.time()
1177 instance_state
= None
1178 while (time
.time() - start_time
) < timeout
:
1179 results
= yield from self
.querier
.get_nsr_opdatas(nsr_id
=nsr_id
)
1180 if len(results
) == 1:
1182 if len(result
.scaling_group_record
) == 0:
1185 if len(result
.scaling_group_record
[0].instance
) == 0:
1188 instance
= result
.scaling_group_record
[0].instance
[0]
1189 self
.assertEqual(instance
.scaling_group_index_ref
, index
)
1191 instance_state
= instance
.op_status
1192 if instance_state
== state
:
1193 self
.log
.debug("Scale group instance reached %s state", state
)
1196 yield from asyncio
.sleep(1, loop
=self
.loop
)
1198 self
.assertEqual(state
, instance_state
)
1201 def verify_results(termination
=False, nsrid
=None):
1202 yield from verify_vnfr_record(termination
)
1203 #yield from verify_vlr_record(termination)
1204 yield from verify_nsr_opdata(termination
)
1205 yield from verify_nsr_config(termination
)
1206 yield from verify_nsd_ref_count(termination
)
1207 yield from verify_vnfd_ref_count(termination
)
1210 yield from verify_cm_state(termination
, nsrid
)
1211 yield from verify_nsr_config_status(termination
, nsrid
)
1213 yield from verify_cloud_account(termination
)
1214 yield from verify_project_record(termination
)
1217 def verify_scale_instance(index
):
1218 self
.log
.debug("Verifying scale record path = %s, Termination=%d",
1219 XPaths
.vnfr(), termination
)
1222 vnfrs
= yield from self
.querier
.get_vnfrs()
1227 self
.log
.debug("VNFR still exists = %s", vnfr
)
1230 assert len(vnfrs
) == 0
1233 vnfrs
= yield from self
.querier
.get_vnfrs()
1234 if len(vnfrs
) != 0 and termination
is False:
1236 self
.log
.debug("Rcvd VNFR with %s status", vnfr
.operational_status
)
1237 if vnfr
.operational_status
== 'running':
1238 self
.log
.debug("!!! Rcvd VNFR with running status !!!")
1241 elif vnfr
.operational_status
== "failed":
1242 self
.log
.debug("!!! Rcvd VNFR with failed status !!!")
1245 self
.log
.debug("Sleeping for 10 seconds")
1246 yield from asyncio
.sleep(10, loop
=self
.loop
)
1249 def terminate_ns(nsr_id
):
1250 xpath
= XPaths
.nsr_config(nsr_id
)
1251 self
.log
.debug("Terminating network service with path %s", xpath
)
1252 yield from self
.dts
.query_delete(xpath
, flags
=rwdts
.XactFlag
.ADVISE
)
1253 self
.log
.debug("Terminated network service with path %s", xpath
)
1257 yield from self
.wait_tasklets()
1259 yield from self
.configure_project()
1260 yield from self
.configure_project(project
=self
.project1
)
1263 yield from self
.configure_cloud_account(self
.dts
, cloud_type
, "mock_account")
1264 yield from self
.configure_cloud_account(self
.dts
, cloud_type
, "mock_account1")
1265 yield from self
.configure_cloud_account(self
.dts
, cloud_type
, "mock_account",
1266 project
=self
.project1
)
1268 yield from verify_cloud_accounts()
1269 yield from verify_projects()
1271 yield from self
.ping_pong
.publish_desciptors()
1274 # Attempt deleting VNFD not in use
1275 yield from self
.ping_pong
.update_ping_vnfd()
1277 # Attempt updating NSD not in use
1278 yield from self
.ping_pong
.update_nsd()
1280 # Attempt deleting VNFD not in use
1281 yield from self
.ping_pong
.delete_ping_vnfd()
1283 # Attempt deleting NSD not in use
1284 yield from self
.ping_pong
.delete_nsd()
1286 yield from self
.ping_pong
.publish_desciptors()
1288 nsr_id
= yield from self
.nsr_publisher
.publish()
1290 yield from verify_results(nsrid
=nsr_id
)
1292 # yield from self.nsr_publisher.create_scale_group_instance("ping_group", 1)
1294 # yield from verify_scale_group_reaches_state(nsr_id, "ping_group", 1, "running")
1296 # yield from self.nsr_publisher.delete_scale_group_instance("ping_group", 1)
1298 yield from asyncio
.sleep(10, loop
=self
.loop
)
1300 # Attempt deleting VNFD in use
1301 yield from self
.ping_pong
.delete_ping_vnfd()
1303 # Attempt updating NSD in use
1304 yield from self
.ping_pong
.update_nsd()
1306 # Update NSD in use with new VL
1307 yield from self
.nsr_publisher
.add_nsr_vl()
1309 # Verify the new VL has been added
1310 yield from verify_vlrs(nsr_id
, count
=2)
1312 # Delete the added VL
1313 yield from self
.nsr_publisher
.del_nsr_vl()
1315 # Verify the new VL has been added
1316 yield from verify_vlrs(nsr_id
, count
=1)
1318 # Attempt deleting NSD in use
1319 yield from self
.ping_pong
.delete_nsd()
1321 yield from terminate_ns(nsr_id
)
1323 yield from asyncio
.sleep(25, loop
=self
.loop
)
1324 self
.log
.debug("Verifying termination results")
1325 yield from verify_results(termination
=True, nsrid
=nsr_id
)
1326 self
.log
.debug("Verified termination results")
1328 # Multi site NS case
1329 self
.log
.debug("Testing multi site NS")
1330 self
.nsr_publisher
.update_vnf_cloud_map({1:"mock_account1",2:"mock_account"})
1331 nsr_id
= yield from self
.nsr_publisher
.publish()
1333 yield from verify_results(nsrid
=nsr_id
)
1334 yield from verify_vnfr_cloud_account(1,"mock_account1")
1335 yield from verify_vnfr_cloud_account(2,"mock_account")
1336 yield from verify_vlrs(nsr_id
, count
=2)
1338 yield from terminate_ns(nsr_id
)
1340 yield from asyncio
.sleep(25, loop
=self
.loop
)
1341 self
.log
.debug("Verifying termination results for multi site NS")
1342 yield from verify_results(termination
=True, nsrid
=nsr_id
)
1343 self
.log
.debug("Verified termination results for multi site NS")
1345 self
.log
.debug("Attempting to delete VNFD for real")
1346 yield from self
.ping_pong
.delete_ping_vnfd()
1348 self
.log
.debug("Attempting to delete NSD for real")
1349 yield from self
.ping_pong
.delete_nsd()
1351 future
= asyncio
.ensure_future(run_test(), loop
=self
.loop
)
1352 self
.run_until(future
.done
)
1353 if future
.exception() is not None:
1354 self
.log
.error("Caught exception during test")
1355 raise future
.exception()
1359 plugin_dir
= os
.path
.join(os
.environ
["RIFT_INSTALL"], "usr/lib/rift/plugins")
1360 if 'VNS_DIR' not in os
.environ
:
1361 os
.environ
['VNS_DIR'] = os
.path
.join(plugin_dir
, 'rwvns')
1363 if 'VNFM_DIR' not in os
.environ
:
1364 os
.environ
['VNFM_DIR'] = os
.path
.join(plugin_dir
, 'rwvnfm')
1366 if 'NSM_DIR' not in os
.environ
:
1367 os
.environ
['NSM_DIR'] = os
.path
.join(plugin_dir
, 'rwnsm')
1369 if 'RM_DIR' not in os
.environ
:
1370 os
.environ
['RM_DIR'] = os
.path
.join(plugin_dir
, 'rwresmgrtasklet')
1372 runner
= xmlrunner
.XMLTestRunner(output
=os
.environ
["RIFT_MODULE_TEST"])
1374 parser
= argparse
.ArgumentParser()
1375 parser
.add_argument('-v', '--verbose', action
='store_true')
1376 parser
.add_argument('-n', '--no-runner', action
='store_true')
1377 args
, unittest_args
= parser
.parse_known_args()
1381 ManoTestCase
.log_level
= logging
.DEBUG
if args
.verbose
else logging
.WARN
1383 unittest
.main(testRunner
=runner
, argv
=[sys
.argv
[0]] + unittest_args
)
1385 if __name__
== '__main__':