b770a01621ead9446777d9d3589371869ddb7158
[osm/N2VC.git] / tests / test_python.py
1 # A simple test to exercise the libraries' functionality
2 import asyncio
3 import functools
4 import os
5 import sys
6 import logging
7 import osm_im.vnfd as vnfd_catalog
8 import osm_im.nsd as nsd_catalog
9 from pyangbind.lib.serialise import pybindJSONDecoder
10 import unittest
11 import yaml
12 from n2vc.vnf import N2VC
13
14 NSD_YAML = """
15 nsd-catalog:
16 nsd:
17 - id: rift_ping_pong_ns
18 logo: rift_logo.png
19 name: ping_pong_ns
20 short-name: ping_pong_ns
21 vendor: RIFT.io
22 version: '1.1'
23 description: RIFT.io sample ping pong network service
24 constituent-vnfd:
25 - member-vnf-index: '1'
26 vnfd-id-ref: rift_ping_vnf
27 - member-vnf-index: '2'
28 vnfd-id-ref: rift_pong_vnf
29 initial-service-primitive:
30 - name: start traffic
31 parameter:
32 - name: port
33 value: 5555
34 - name: ssh-username
35 value: fedora
36 - name: ssh-password
37 value: fedora
38 seq: '1'
39 user-defined-script: start_traffic.py
40 input-parameter-xpath:
41 - xpath: /nsd:nsd-catalog/nsd:nsd/nsd:vendor
42 ip-profiles:
43 - description: Inter VNF Link
44 ip-profile-params:
45 gateway-address: 31.31.31.210
46 ip-version: ipv4
47 subnet-address: 31.31.31.0/24
48 dhcp-params:
49 count: 200
50 start-address: 31.31.31.2
51 name: InterVNFLink
52 placement-groups:
53 - member-vnfd:
54 - member-vnf-index-ref: '1'
55 vnfd-id-ref: rift_ping_vnf
56 - member-vnf-index-ref: '2'
57 vnfd-id-ref: rift_pong_vnf
58 name: Orcus
59 requirement: Place this VM on the Kuiper belt object Orcus
60 strategy: COLOCATION
61 - member-vnfd:
62 - member-vnf-index-ref: '1'
63 vnfd-id-ref: rift_ping_vnf
64 - member-vnf-index-ref: '2'
65 vnfd-id-ref: rift_pong_vnf
66 name: Quaoar
67 requirement: Place this VM on the Kuiper belt object Quaoar
68 strategy: COLOCATION
69 vld:
70 - id: mgmt_vl
71 description: Management VL
72 name: mgmt_vl
73 short-name: mgmt_vl
74 vim-network-name: mgmt
75 type: ELAN
76 vendor: RIFT.io
77 version: '1.0'
78 mgmt-network: 'true'
79 vnfd-connection-point-ref:
80 - member-vnf-index-ref: '1'
81 vnfd-connection-point-ref: ping_vnfd/cp0
82 vnfd-id-ref: rift_ping_vnf
83 - member-vnf-index-ref: '2'
84 vnfd-connection-point-ref: pong_vnfd/cp0
85 vnfd-id-ref: rift_pong_vnf
86 - id: ping_pong_vl1
87 description: Data VL
88 ip-profile-ref: InterVNFLink
89 name: data_vl
90 short-name: data_vl
91 type: ELAN
92 vendor: RIFT.io
93 version: '1.0'
94 vnfd-connection-point-ref:
95 - member-vnf-index-ref: '1'
96 vnfd-connection-point-ref: ping_vnfd/cp1
97 vnfd-id-ref: rift_ping_vnf
98 - member-vnf-index-ref: '2'
99 vnfd-connection-point-ref: pong_vnfd/cp1
100 vnfd-id-ref: rift_pong_vnf
101 """
102
103 VNFD_VCA_YAML = """
104 vnfd-catalog:
105 vnfd:
106 - id: rift_ping_vnf
107 name: ping_vnf
108 short-name: ping_vnf
109 logo: rift_logo.png
110 vendor: RIFT.io
111 version: '1.1'
112 description: This is an example RIFT.ware VNF
113 connection-point:
114 - name: ping_vnfd/cp0
115 type: VPORT
116 - name: ping_vnfd/cp1
117 type: VPORT
118 http-endpoint:
119 - path: api/v1/ping/stats
120 port: '18888'
121 mgmt-interface:
122 dashboard-params:
123 path: api/v1/ping/stats
124 port: '18888'
125 port: '18888'
126 cp: ping_vnfd/cp0
127 placement-groups:
128 - member-vdus:
129 - member-vdu-ref: iovdu_0
130 name: Eris
131 requirement: Place this VM on the Kuiper belt object Eris
132 strategy: COLOCATION
133 vdu:
134 - cloud-init-file: ping_cloud_init.cfg
135 count: '1'
136 interface:
137 - name: eth0
138 position: 0
139 type: EXTERNAL
140 virtual-interface:
141 type: VIRTIO
142 external-connection-point-ref: ping_vnfd/cp0
143 - name: eth1
144 position: 1
145 type: EXTERNAL
146 virtual-interface:
147 type: VIRTIO
148 external-connection-point-ref: ping_vnfd/cp1
149 id: iovdu_0
150 image: Fedora-x86_64-20-20131211.1-sda-ping.qcow2
151 name: iovdu_0
152 vm-flavor:
153 memory-mb: '512'
154 storage-gb: '4'
155 vcpu-count: '1'
156 vnf-configuration:
157 config-primitive:
158 - name: start
159 - name: stop
160 - name: restart
161 - name: config
162 parameter:
163 - data-type: STRING
164 default-value: <rw_mgmt_ip>
165 name: ssh-hostname
166 - data-type: STRING
167 default-value: fedora
168 name: ssh-username
169 - data-type: STRING
170 default-value: fedora
171 name: ssh-password
172 - data-type: STRING
173 name: ssh-private-key
174 - data-type: STRING
175 default-value: ping
176 name: mode
177 read-only: 'true'
178 - name: set-server
179 parameter:
180 - data-type: STRING
181 name: server-ip
182 - data-type: INTEGER
183 name: server-port
184 - name: set-rate
185 parameter:
186 - data-type: INTEGER
187 default-value: '5'
188 name: rate
189 - name: start-traffic
190 - name: stop-traffic
191 initial-config-primitive:
192 - name: config
193 parameter:
194 - name: ssh-hostname
195 value: <rw_mgmt_ip>
196 - name: ssh-username
197 value: fedora
198 - name: ssh-password
199 value: fedora
200 - name: mode
201 value: ping
202 seq: '1'
203 - name: start
204 seq: '2'
205 juju:
206 charm: pingpong
207 """
208
209 NSD_DICT = {'name': 'ping_pong_ns', 'short-name': 'ping_pong_ns', 'ip-profiles': [{'ip-profile-params': {'ip-version': 'ipv4', 'dhcp-params': {'count': 200, 'start-address': '31.31.31.2'}, 'subnet-address': '31.31.31.0/24', 'gateway-address': '31.31.31.210'}, 'description': 'Inter VNF Link', 'name': 'InterVNFLink'}], 'logo': 'rift_logo.png', 'description': 'RIFT.io sample ping pong network service', '_admin': {'storage': {'folder': 'd9bc2e64-dfec-4c36-a8bb-c4667e8d7a53', 'tarfile': 'pkg', 'file': 'ping_pong_ns', 'path': '/app/storage/', 'fs': 'local'}, 'created': 1521127984.6414561, 'modified': 1521127984.6414561, 'projects_write': ['admin'], 'projects_read': ['admin']}, 'placement-groups': [{'member-vnfd': [{'member-vnf-index-ref': '1', 'vnfd-id-ref': 'rift_ping_vnf'}, {'member-vnf-index-ref': '2', 'vnfd-id-ref': 'rift_pong_vnf'}], 'name': 'Orcus', 'strategy': 'COLOCATION', 'requirement': 'Place this VM on the Kuiper belt object Orcus'}, {'member-vnfd': [{'member-vnf-index-ref': '1', 'vnfd-id-ref': 'rift_ping_vnf'}, {'member-vnf-index-ref': '2', 'vnfd-id-ref': 'rift_pong_vnf'}], 'name': 'Quaoar', 'strategy': 'COLOCATION', 'requirement': 'Place this VM on the Kuiper belt object Quaoar'}], 'input-parameter-xpath': [{'xpath': '/nsd:nsd-catalog/nsd:nsd/nsd:vendor'}], 'version': '1.1', 'vld': [{'name': 'mgmt', 'short-name': 'mgmt', 'mgmt-network': 'true', 'vim-network-name': 'mgmt', 'version': '1.0', 'vnfd-connection-point-ref': [{'vnfd-connection-point-ref': 'ping_vnfd/cp0', 'member-vnf-index-ref': '1', 'vnfd-id-ref': 'rift_ping_vnf'}, {'vnfd-connection-point-ref': 'pong_vnfd/cp0', 'member-vnf-index-ref': '2', 'vnfd-id-ref': 'rift_pong_vnf'}], 'description': 'Management VL', 'vendor': 'RIFT.io', 'type': 'ELAN', 'id': 'mgmt'}, {'ip-profile-ref': 'InterVNFLink', 'name': 'data_vl', 'short-name': 'data_vl', 'version': '1.0', 'vnfd-connection-point-ref': [{'vnfd-connection-point-ref': 'ping_vnfd/cp1', 'member-vnf-index-ref': '1', 'vnfd-id-ref': 'rift_ping_vnf'}, {'vnfd-connection-point-ref': 'pong_vnfd/cp1', 'member-vnf-index-ref': '2', 'vnfd-id-ref': 'rift_pong_vnf'}], 'description': 'Data VL', 'vendor': 'RIFT.io', 'type': 'ELAN', 'id': 'ping_pong_vl1'}], 'constituent-vnfd': [{'member-vnf-index': '1', 'vnfd-id-ref': 'rift_ping_vnf'}, {'member-vnf-index': '2', 'vnfd-id-ref': 'rift_pong_vnf'}], '_id': 'd9bc2e64-dfec-4c36-a8bb-c4667e8d7a53', 'vendor': 'RIFT.io', 'id': 'rift_ping_pong_ns', 'initial-service-primitive': [{'parameter': [{'name': 'port', 'value': 5555}, {'name': 'ssh-username', 'value': 'fedora'}, {'name': 'ssh-password', 'value': 'fedora'}], 'name': 'start traffic', 'seq': '1', 'user-defined-script': 'start_traffic.py'}]}
210
211
212 VNFD_PING_DICT = {'name': 'ping_vnf', 'short-name': 'ping_vnf', 'mgmt-interface': {'port': '18888', 'cp': 'ping_vnfd/cp0', 'dashboard-params': {'port': '18888', 'path': 'api/v1/ping/stats'}}, 'description': 'This is an example RIFT.ware VNF', 'connection-point': [{'type': 'VPORT', 'name': 'ping_vnfd/cp0'}, {'type': 'VPORT', 'name': 'ping_vnfd/cp1'}], '_admin': {'storage': {'folder': '9ad8de93-cfcc-4da9-9795-d7dc5fec184e', 'fs': 'local', 'file': 'ping_vnf', 'path': '/app/storage/', 'tarfile': 'pkg'}, 'created': 1521127972.1878572, 'modified': 1521127972.1878572, 'projects_write': ['admin'], 'projects_read': ['admin']}, 'vnf-configuration': {'initial-config-primitive': [{'parameter': [{'name': 'ssh-hostname', 'value': '<rw_mgmt_ip>'}, {'name': 'ssh-username', 'value': 'ubuntu'}, {'name': 'ssh-password', 'value': 'ubuntu'}, {'name': 'mode', 'value': 'ping'}], 'name': 'config', 'seq': '1'}, {'name': 'start', 'seq': '2'}], 'juju': {'charm': 'pingpong'}, 'config-primitive': [{'name': 'start'}, {'name': 'stop'}, {'name': 'restart'}, {'parameter': [{'data-type': 'STRING', 'name': 'ssh-hostname', 'default-value': '<rw_mgmt_ip>'}, {'data-type': 'STRING', 'name': 'ssh-username', 'default-value': 'ubuntu'}, {'data-type': 'STRING', 'name': 'ssh-password', 'default-value': 'ubuntu'}, {'data-type': 'STRING', 'name': 'ssh-private-key'}, {'data-type': 'STRING', 'name': 'mode', 'read-only': 'true', 'default-value': 'ping'}], 'name': 'config'}, {'parameter': [{'data-type': 'STRING', 'name': 'server-ip'}, {'data-type': 'INTEGER', 'name': 'server-port'}], 'name': 'set-server'}, {'parameter': [{'data-type': 'INTEGER', 'name': 'rate', 'default-value': '5'}], 'name': 'set-rate'}, {'name': 'start-traffic'}, {'name': 'stop-traffic'}]}, 'placement-groups': [{'member-vdus': [{'member-vdu-ref': 'iovdu_0'}], 'name': 'Eris', 'strategy': 'COLOCATION', 'requirement': 'Place this VM on the Kuiper belt object Eris'}], 'http-endpoint': [{'port': '18888', 'path': 'api/v1/ping/stats'}], 'version': '1.1', 'logo': 'rift_logo.png', 'vdu': [{'vm-flavor': {'vcpu-count': '1', 'storage-gb': '20', 'memory-mb': '2048'}, 'count': '1', 'interface': [{'type': 'EXTERNAL', 'name': 'eth0', 'position': 0, 'virtual-interface': {'type': 'VIRTIO'}, 'external-connection-point-ref': 'ping_vnfd/cp0'}, {'type': 'EXTERNAL', 'name': 'eth1', 'position': 1, 'virtual-interface': {'type': 'VIRTIO'}, 'external-connection-point-ref': 'ping_vnfd/cp1'}], 'name': 'iovdu_0', 'image': 'xenial', 'id': 'iovdu_0', 'cloud-init-file': 'ping_cloud_init.cfg'}], '_id': '9ad8de93-cfcc-4da9-9795-d7dc5fec184e', 'vendor': 'RIFT.io', 'id': 'rift_ping_vnf'}
213
214 VNFD_PONG_DICT = {'name': 'pong_vnf', 'short-name': 'pong_vnf', 'mgmt-interface': {'port': '18888', 'cp': 'pong_vnfd/cp0', 'dashboard-params': {'port': '18888', 'path': 'api/v1/pong/stats'}}, 'description': 'This is an example RIFT.ware VNF', 'connection-point': [{'type': 'VPORT', 'name': 'pong_vnfd/cp0'}, {'type': 'VPORT', 'name': 'pong_vnfd/cp1'}], '_admin': {'storage': {'folder': '9ad8de93-cfcc-4da9-9795-d7dc5fec184e', 'fs': 'local', 'file': 'pong_vnf', 'path': '/app/storage/', 'tarfile': 'pkg'}, 'created': 1521127972.1878572, 'modified': 1521127972.1878572, 'projects_write': ['admin'], 'projects_read': ['admin']}, 'vnf-configuration': {'initial-config-primitive': [{'parameter': [{'name': 'ssh-hostname', 'value': '<rw_mgmt_ip>'}, {'name': 'ssh-username', 'value': 'ubuntu'}, {'name': 'ssh-password', 'value': 'ubuntu'}, {'name': 'mode', 'value': 'pong'}], 'name': 'config', 'seq': '1'}, {'name': 'start', 'seq': '2'}], 'juju': {'charm': 'pingpong'}, 'config-primitive': [{'name': 'start'}, {'name': 'stop'}, {'name': 'restart'}, {'parameter': [{'data-type': 'STRING', 'name': 'ssh-hostname', 'default-value': '<rw_mgmt_ip>'}, {'data-type': 'STRING', 'name': 'ssh-username', 'default-value': 'ubuntu'}, {'data-type': 'STRING', 'name': 'ssh-password', 'default-value': 'ubuntu'}, {'data-type': 'STRING', 'name': 'ssh-private-key'}, {'data-type': 'STRING', 'name': 'mode', 'read-only': 'true', 'default-value': 'pong'}], 'name': 'config'}, {'parameter': [{'data-type': 'STRING', 'name': 'server-ip'}, {'data-type': 'INTEGER', 'name': 'server-port'}], 'name': 'set-server'}, {'parameter': [{'data-type': 'INTEGER', 'name': 'rate', 'default-value': '5'}], 'name': 'set-rate'}, {'name': 'start-traffic'}, {'name': 'stop-traffic'}]}, 'placement-groups': [{'member-vdus': [{'member-vdu-ref': 'iovdu_0'}], 'name': 'Eris', 'strategy': 'COLOCATION', 'requirement': 'Place this VM on the Kuiper belt object Eris'}], 'http-endpoint': [{'port': '18888', 'path': 'api/v1/pong/stats'}], 'version': '1.1', 'logo': 'rift_logo.png', 'vdu': [{'vm-flavor': {'vcpu-count': '1', 'storage-gb': '20', 'memory-mb': '2048'}, 'count': '1', 'interface': [{'type': 'EXTERNAL', 'name': 'eth0', 'position': 0, 'virtual-interface': {'type': 'VIRTIO'}, 'external-connection-point-ref': 'ping_vnfd/cp0'}, {'type': 'EXTERNAL', 'name': 'eth1', 'position': 1, 'virtual-interface': {'type': 'VIRTIO'}, 'external-connection-point-ref': 'ping_vnfd/cp1'}], 'name': 'iovdu_0', 'image': 'xenial', 'id': 'iovdu_0', 'cloud-init-file': 'pong_cloud_init.cfg'}], '_id': '9ad8de93-cfcc-4da9-9795-d7dc5fec184e', 'vendor': 'RIFT.io', 'id': 'rift_pong_vnf'}
215
216
217 class PythonTest(unittest.TestCase):
218 n2vc = None
219
220 def setUp(self):
221
222 self.log = logging.getLogger()
223 self.log.level = logging.DEBUG
224
225 self.loop = asyncio.new_event_loop()
226 asyncio.set_event_loop(None)
227
228 # Extract parameters from the environment in order to run our test
229 vca_host = os.getenv('VCA_HOST', '127.0.0.1')
230 vca_port = os.getenv('VCA_PORT', 17070)
231 vca_user = os.getenv('VCA_USER', 'admin')
232 vca_charms = os.getenv('VCA_CHARMS', None)
233 vca_secret = os.getenv('VCA_SECRET', None)
234 self.n2vc = N2VC(
235 log=self.log,
236 server=vca_host,
237 port=vca_port,
238 user=vca_user,
239 secret=vca_secret,
240 artifacts=vca_charms,
241 )
242
243 def tearDown(self):
244 self.loop.run_until_complete(self.n2vc.logout())
245
246 def get_vnf_descriptor(self, descriptor):
247 vnfd = vnfd_catalog.vnfd()
248 try:
249 data = yaml.load(descriptor)
250 pybindJSONDecoder.load_ietf_json(data, None, None, obj=vnfd)
251 except ValueError:
252 assert False
253 return vnfd
254
255 def get_ns_descriptor(self, descriptor):
256 nsd = nsd_catalog.nsd()
257 try:
258 data = yaml.load(descriptor)
259 pybindJSONDecoder.load_ietf_json(data, None, None, obj=nsd)
260 except ValueError:
261 assert False
262 return nsd
263
264 # def test_descriptor(self):
265 # """Test loading and parsing a descriptor."""
266 # nsd = self.get_ns_descriptor(NSD_YAML)
267 # vnfd = self.get_vnf_descriptor(VNFD_VCA_YAML)
268 # if vnfd and nsd:
269 # pass
270
271 # def test_yang_to_dict(self):
272 # # Test the conversion of the native object returned by pybind to a dict
273 # # Extract parameters from the environment in order to run our test
274 #
275 # nsd = self.get_ns_descriptor(NSD_YAML)
276 # new = yang_to_dict(nsd)
277 # self.assertEqual(NSD_DICT, new)
278
279 def n2vc_callback(self, model_name, application_name, workload_status, task=None):
280 """We pass the vnfd when setting up the callback, so expect it to be
281 returned as a tuple."""
282 if workload_status and not task:
283 self.log.debug("Callback: workload status \"{}\"".format(workload_status))
284
285 if workload_status in ["blocked"]:
286 task = asyncio.ensure_future(
287 self.n2vc.ExecutePrimitive(
288 model_name,
289 application_name,
290 "config",
291 None,
292 params={
293 'ssh-hostname': '10.195.8.78',
294 'ssh-username': 'ubuntu',
295 'ssh-password': 'ubuntu'
296 }
297 )
298 )
299 task.add_done_callback(functools.partial(self.n2vc_callback, None, None, None))
300 pass
301 elif workload_status in ["active"]:
302 self.log.debug("Removing charm")
303 task = asyncio.ensure_future(
304 self.n2vc.RemoveCharms(model_name, application_name, self.n2vc_callback, model_name, application_name)
305 )
306 task.add_done_callback(functools.partial(self.n2vc_callback, None, None, None))
307 elif task:
308 if task.done():
309 self.loop.stop()
310
311 def test_deploy_application(self):
312 stream_handler = logging.StreamHandler(sys.stdout)
313 self.log.addHandler(stream_handler)
314 try:
315 self.log.info("Log handler installed")
316 nsd = NSD_DICT
317 vnfd_ping = VNFD_PING_DICT
318 vnfd_pong = VNFD_PONG_DICT
319 if nsd and vnfd_ping and vnfd_pong:
320 vca_charms = os.getenv('VCA_CHARMS', None)
321
322 config = vnfd_ping['vnf-configuration']
323 self.assertIsNotNone(config)
324
325 juju = config['juju']
326 self.assertIsNotNone(juju)
327
328 charm = juju['charm']
329 self.assertIsNotNone(charm)
330
331 charm_dir = "{}/{}".format(vca_charms, charm)
332 # n.callback_status = self.callback_status
333
334 # Setting this to an IP that will fail the initial config.
335 # This will be detected in the callback, which will execute
336 # the "config" primitive with the right IP address.
337 params = {
338 'rw_mgmt_ip': '127.0.0.1'
339 }
340
341 # self.loop.run_until_complete(n.CreateNetworkService(nsd))
342 # task = asyncio.ensure_future(n.DeployCharms(vnfd, nsd=nsd, artifacts=charm_dir))
343 # task = asyncio.ensure_future(n.DeployCharms(vnfd, nsd=nsd, artifacts=charm_dir))
344 ns_name = "default"
345
346 ping_vnf_name = self.n2vc.FormatApplicationName(ns_name, vnfd_ping['name'])
347 pong_vnf_name = self.n2vc.FormatApplicationName(ns_name, vnfd_pong['name'])
348
349 self.loop.run_until_complete(self.n2vc.DeployCharms(ns_name, ping_vnf_name, vnfd_ping, charm_dir, params, {}, self.n2vc_callback))
350 self.loop.run_until_complete(self.n2vc.DeployCharms(ns_name, pong_vnf_name, vnfd_pong, charm_dir, params, {}, self.n2vc_callback))
351 self.loop.run_forever()
352
353 # self.loop.run_until_complete(n.GetMetrics(vnfd, nsd=nsd))
354 # Test actions
355 # ExecutePrimitive(self, nsd, vnfd, vnf_member_index, primitive, callback, *callback_args, **params):
356
357 # self.loop.run_until_complete(n.DestroyNetworkService(nsd))
358
359 # self.loop.run_until_complete(self.n2vc.logout())
360 finally:
361 self.log.removeHandler(stream_handler)
362
363 # def test_deploy_application(self):
364 #
365 # nsd = self.get_ns_descriptor(NSD_YAML)
366 # vnfd = self.get_vnf_descriptor(VNFD_VCA_YAML)
367 # if nsd and vnfd:
368 # # 1) Test that we're parsing the data correctly
369 # for vnfd_yang in vnfd.vnfd_catalog.vnfd.itervalues():
370 # vnfd_rec = vnfd_yang.get()
371 # # Each vnfd may have a charm
372 # # print(vnfd)
373 # config = vnfd_rec.get('vnf-configuration')
374 # self.assertIsNotNone(config)
375 #
376 # juju = config.get('juju')
377 # self.assertIsNotNone(juju)
378 #
379 # charm = juju.get('charm')
380 # self.assertIsNotNone(charm)
381 #
382 # # 2) Exercise the data by deploying the charms
383 #
384 # # Extract parameters from the environment in order to run our test
385 # vca_host = os.getenv('VCA_HOST', '127.0.0.1')
386 # vca_port = os.getenv('VCA_PORT', 17070)
387 # vca_user = os.getenv('VCA_USER', 'admin')
388 # vca_charms = os.getenv('VCA_CHARMS', None)
389 # vca_secret = os.getenv('VCA_SECRET', None)
390 # # n = N2VC(
391 # # server='10.195.8.254',
392 # # port=17070,
393 # # user='admin',
394 # # secret='74e7aa0cc9cb294de3af294bd76b4604'
395 # # )
396 # n = N2VC(
397 # server=vca_host,
398 # port=vca_port,
399 # user=vca_user,
400 # secret=vca_secret,
401 # artifacts=vca_charms,
402 # )
403 #
404 # n.callback_status = self.callback_status
405 #
406 # self.loop.run_until_complete(n.CreateNetworkService(nsd))
407 # self.loop.run_until_complete(n.DeployCharms(vnfd, nsd=nsd))
408 # # self.loop.run_until_complete(n.GetMetrics(vnfd, nsd=nsd))
409 #
410 # # self.loop.run_until_complete(n.RemoveCharms(nsd, vnfd))
411 # self.loop.run_until_complete(n.DestroyNetworkService(nsd))
412 #
413 # self.loop.run_until_complete(n.logout())
414 # n = None
415
416 def callback_status(self, nsd, vnfd, workload_status):
417 """An example callback.
418
419 This is an example of how a client using N2VC can receive periodic
420 updates on the status of a vnfd
421 """
422 # print(nsd)
423 # print(vnfd)
424 print("Workload status: {}".format(workload_status))
425
426 def test_deploy_multivdu_application(self):
427 """Deploy a multi-vdu vnf that uses multiple charms."""
428 pass
429
430 def test_remove_application(self):
431 pass
432
433 def test_get_metrics(self):
434 pass