Bug 502 improvements
[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 unittest
8 import yaml
9 from n2vc.vnf import N2VC
10
11 NSD_YAML = """
12 nsd:nsd-catalog:
13 nsd:
14 - id: multicharmvdu-ns
15 name: multicharmvdu-ns
16 short-name: multicharmvdu-ns
17 description: NS with 2 VNFs multicharmvdu-vnf connected by datanet and mgmtnet VLs
18 version: '1.0'
19 logo: osm.png
20 constituent-vnfd:
21 - vnfd-id-ref: multicharmvdu-vnf
22 member-vnf-index: '1'
23 - vnfd-id-ref: multicharmvdu-vnf
24 member-vnf-index: '2'
25 vld:
26 - id: mgmtnet
27 name: mgmtnet
28 short-name: mgmtnet
29 type: ELAN
30 mgmt-network: 'true'
31 vim-network-name: mgmt
32 vnfd-connection-point-ref:
33 - vnfd-id-ref: multicharmvdu-vnf
34 member-vnf-index-ref: '1'
35 vnfd-connection-point-ref: vnf-mgmt
36 - vnfd-id-ref: multicharmvdu-vnf
37 member-vnf-index-ref: '2'
38 vnfd-connection-point-ref: vnf-mgmt
39 - id: datanet
40 name: datanet
41 short-name: datanet
42 type: ELAN
43 vnfd-connection-point-ref:
44 - vnfd-id-ref: multicharmvdu-vnf
45 member-vnf-index-ref: '1'
46 vnfd-connection-point-ref: vnf-data
47 - vnfd-id-ref: multicharmvdu-vnf
48 member-vnf-index-ref: '2'
49 vnfd-connection-point-ref: vnf-data
50 """
51
52 VNFD_YAML = """
53 vnfd:vnfd-catalog:
54 vnfd:
55 - id: multicharmvdu-vnf
56 name: multicharmvdu-vnf
57 short-name: multicharmvdu-vnf
58 version: '1.0'
59 description: A VNF consisting of 2 VDUs w/charms connected to an internal VL, and one VDU with cloud-init
60 logo: osm.png
61 connection-point:
62 - id: vnf-mgmt
63 name: vnf-mgmt
64 short-name: vnf-mgmt
65 type: VPORT
66 - id: vnf-data
67 name: vnf-data
68 short-name: vnf-data
69 type: VPORT
70 mgmt-interface:
71 cp: vnf-mgmt
72 internal-vld:
73 - id: internal
74 name: internal
75 short-name: internal
76 type: ELAN
77 internal-connection-point:
78 - id-ref: mgmtVM-internal
79 - id-ref: dataVM-internal
80 vdu:
81 - id: mgmtVM
82 name: mgmtVM
83 image: xenial
84 count: '1'
85 vm-flavor:
86 vcpu-count: '1'
87 memory-mb: '1024'
88 storage-gb: '10'
89 interface:
90 - name: mgmtVM-eth0
91 position: '1'
92 type: EXTERNAL
93 virtual-interface:
94 type: VIRTIO
95 external-connection-point-ref: vnf-mgmt
96 - name: mgmtVM-eth1
97 position: '2'
98 type: INTERNAL
99 virtual-interface:
100 type: VIRTIO
101 internal-connection-point-ref: mgmtVM-internal
102 internal-connection-point:
103 - id: mgmtVM-internal
104 name: mgmtVM-internal
105 short-name: mgmtVM-internal
106 type: VPORT
107 cloud-init-file: cloud-config.txt
108 vdu-configuration:
109 juju:
110 charm: simple
111 initial-config-primitive:
112 - seq: '1'
113 name: config
114 parameter:
115 - name: ssh-hostname
116 value: <rw_mgmt_ip>
117 - name: ssh-username
118 value: ubuntu
119 - name: ssh-password
120 value: osm4u
121 - seq: '2'
122 name: touch
123 parameter:
124 - name: filename
125 value: '/home/ubuntu/first-touch-mgmtVM'
126 config-primitive:
127 - name: touch
128 parameter:
129 - name: filename
130 data-type: STRING
131 default-value: '/home/ubuntu/touched'
132
133 - id: dataVM
134 name: dataVM
135 image: xenial
136 count: '1'
137 vm-flavor:
138 vcpu-count: '1'
139 memory-mb: '1024'
140 storage-gb: '10'
141 interface:
142 - name: dataVM-eth0
143 position: '1'
144 type: INTERNAL
145 virtual-interface:
146 type: VIRTIO
147 internal-connection-point-ref: dataVM-internal
148 - name: dataVM-xe0
149 position: '2'
150 type: EXTERNAL
151 virtual-interface:
152 type: VIRTIO
153 external-connection-point-ref: vnf-data
154 internal-connection-point:
155 - id: dataVM-internal
156 name: dataVM-internal
157 short-name: dataVM-internal
158 type: VPORT
159 vdu-configuration:
160 juju:
161 charm: simple
162 initial-config-primitive:
163 - seq: '1'
164 name: config
165 parameter:
166 - name: ssh-hostname
167 value: <rw_mgmt_ip>
168 - name: ssh-username
169 value: ubuntu
170 - name: ssh-password
171 value: osm4u
172 - seq: '2'
173 name: touch
174 parameter:
175 - name: filename
176 value: '/home/ubuntu/first-touch-dataVM'
177 config-primitive:
178 - name: touch
179 parameter:
180 - name: filename
181 data-type: STRING
182 default-value: '/home/ubuntu/touched'
183 """
184
185 class PythonTest(unittest.TestCase):
186 n2vc = None
187
188 def setUp(self):
189
190 self.log = logging.getLogger()
191 self.log.level = logging.DEBUG
192
193 self.loop = asyncio.get_event_loop()
194
195 # self.loop = asyncio.new_event_loop()
196 # asyncio.set_event_loop(None)
197
198 # Extract parameters from the environment in order to run our test
199 vca_host = os.getenv('VCA_HOST', '127.0.0.1')
200 vca_port = os.getenv('VCA_PORT', 17070)
201 vca_user = os.getenv('VCA_USER', 'admin')
202 vca_charms = os.getenv('VCA_CHARMS', None)
203 vca_secret = os.getenv('VCA_SECRET', None)
204 self.n2vc = N2VC(
205 log=self.log,
206 server=vca_host,
207 port=vca_port,
208 user=vca_user,
209 secret=vca_secret,
210 artifacts=vca_charms,
211 )
212
213 def tearDown(self):
214 self.loop.run_until_complete(self.n2vc.logout())
215
216 def get_descriptor(self, descriptor):
217 desc = None
218 try:
219 tmp = yaml.load(descriptor)
220
221 # Remove the envelope
222 root = list(tmp.keys())[0]
223 if root == "nsd:nsd-catalog":
224 desc = tmp['nsd:nsd-catalog']['nsd'][0]
225 elif root == "vnfd:vnfd-catalog":
226 desc = tmp['vnfd:vnfd-catalog']['vnfd'][0]
227 except ValueError:
228 assert False
229 return desc
230
231 def n2vc_callback(self, model_name, application_name, workload_status, task=None):
232 """We pass the vnfd when setting up the callback, so expect it to be
233 returned as a tuple."""
234 if workload_status and not task:
235 self.log.debug("Callback: workload status \"{}\"".format(workload_status))
236
237 if workload_status in ["blocked"]:
238 task = asyncio.ensure_future(
239 self.n2vc.ExecutePrimitive(
240 model_name,
241 application_name,
242 "config",
243 None,
244 params={
245 'ssh-hostname': '10.195.8.78',
246 'ssh-username': 'ubuntu',
247 'ssh-password': 'ubuntu'
248 }
249 )
250 )
251 task.add_done_callback(functools.partial(self.n2vc_callback, None, None, None))
252 pass
253 elif workload_status in ["active"]:
254 self.log.debug("Removing charm")
255 task = asyncio.ensure_future(
256 self.n2vc.RemoveCharms(model_name, application_name, self.n2vc_callback)
257 )
258 task.add_done_callback(functools.partial(self.n2vc_callback, None, None, None))
259
260 def test_deploy_application(self):
261 stream_handler = logging.StreamHandler(sys.stdout)
262 self.log.addHandler(stream_handler)
263 try:
264 self.log.info("Log handler installed")
265 nsd = self.get_descriptor(NSD_YAML)
266 vnfd = self.get_descriptor(VNFD_YAML)
267
268 if nsd and vnfd:
269
270 vca_charms = os.getenv('VCA_CHARMS', None)
271
272 params = {}
273 vnf_index = 0
274
275 def deploy():
276 """An inner function to do the deployment of a charm from
277 either a vdu or vnf.
278 """
279 charm_dir = "{}/{}".format(vca_charms, charm)
280
281 # Setting this to an IP that will fail the initial config.
282 # This will be detected in the callback, which will execute
283 # the "config" primitive with the right IP address.
284 params['rw_mgmt_ip'] = '10.195.8.78'
285
286 # self.loop.run_until_complete(n.CreateNetworkService(nsd))
287 ns_name = "default"
288
289 vnf_name = self.n2vc.FormatApplicationName(
290 ns_name,
291 vnfd['name'],
292 str(vnf_index),
293 )
294
295 self.loop.run_until_complete(
296 self.n2vc.DeployCharms(
297 ns_name,
298 vnf_name,
299 vnfd,
300 charm_dir,
301 params,
302 {},
303 self.n2vc_callback
304 )
305 )
306
307 # Check if the VDUs in this VNF have a charm
308 for vdu in vnfd['vdu']:
309 vdu_config = vdu.get('vdu-configuration')
310 if vdu_config:
311 juju = vdu_config['juju']
312 self.assertIsNotNone(juju)
313
314 charm = juju['charm']
315 self.assertIsNotNone(charm)
316
317 params['initial-config-primitive'] = vdu_config['initial-config-primitive']
318
319 deploy()
320 vnf_index += 1
321
322 # Check if this VNF has a charm
323 vnf_config = vnfd.get("vnf-configuration")
324 if vnf_config:
325 juju = vnf_config['juju']
326 self.assertIsNotNone(juju)
327
328 charm = juju['charm']
329 self.assertIsNotNone(charm)
330
331 params['initial-config-primitive'] = vnf_config['initial-config-primitive']
332
333 deploy()
334 vnf_index += 1
335
336 self.loop.run_forever()
337
338 # self.loop.run_until_complete(n.GetMetrics(vnfd, nsd=nsd))
339
340 # Test actions
341 # ExecutePrimitive(self, nsd, vnfd, vnf_member_index, primitive, callback, *callback_args, **params):
342
343 # self.loop.run_until_complete(n.DestroyNetworkService(nsd))
344
345 # self.loop.run_until_complete(self.n2vc.logout())
346 finally:
347 self.log.removeHandler(stream_handler)