blob: 5bb4325d76837c3c6174b2ae5fa8494aa6f3c3c2 [file] [log] [blame]
Adam Israelc3e6c2e2018-03-01 09:31:50 -05001# A simple test to exercise the libraries' functionality
2import asyncio
3import functools
4import os
5import sys
6import logging
Adam Israelc3e6c2e2018-03-01 09:31:50 -05007import unittest
8import yaml
9from n2vc.vnf import N2VC
10
11NSD_YAML = """
Adam Israel88a49632018-04-10 13:04:57 -060012nsd:nsd-catalog:
Adam Israelc3e6c2e2018-03-01 09:31:50 -050013 nsd:
Adam Israel88a49632018-04-10 13:04:57 -060014 - 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
Adam Israelc3e6c2e2018-03-01 09:31:50 -050020 constituent-vnfd:
Adam Israel88a49632018-04-10 13:04:57 -060021 - vnfd-id-ref: multicharmvdu-vnf
22 member-vnf-index: '1'
23 - vnfd-id-ref: multicharmvdu-vnf
24 member-vnf-index: '2'
Adam Israelc3e6c2e2018-03-01 09:31:50 -050025 vld:
Adam Israel88a49632018-04-10 13:04:57 -060026 - id: mgmtnet
27 name: mgmtnet
28 short-name: mgmtnet
Adam Israelc3e6c2e2018-03-01 09:31:50 -050029 type: ELAN
Adam Israelc3e6c2e2018-03-01 09:31:50 -050030 mgmt-network: 'true'
Adam Israel88a49632018-04-10 13:04:57 -060031 vim-network-name: mgmt
Adam Israelc3e6c2e2018-03-01 09:31:50 -050032 vnfd-connection-point-ref:
Adam Israel88a49632018-04-10 13:04:57 -060033 - 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
Adam Israelc3e6c2e2018-03-01 09:31:50 -050042 type: ELAN
Adam Israelc3e6c2e2018-03-01 09:31:50 -050043 vnfd-connection-point-ref:
Adam Israel88a49632018-04-10 13:04:57 -060044 - 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
Adam Israelc3e6c2e2018-03-01 09:31:50 -050050"""
51
Adam Israel88a49632018-04-10 13:04:57 -060052VNFD_YAML = """
53vnfd:vnfd-catalog:
Adam Israelc3e6c2e2018-03-01 09:31:50 -050054 vnfd:
Adam Israel88a49632018-04-10 13:04:57 -060055 - 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
Adam Israelc3e6c2e2018-03-01 09:31:50 -050061 connection-point:
Adam Israel88a49632018-04-10 13:04:57 -060062 - id: vnf-mgmt
63 name: vnf-mgmt
64 short-name: vnf-mgmt
Adam Israelc3e6c2e2018-03-01 09:31:50 -050065 type: VPORT
Adam Israel88a49632018-04-10 13:04:57 -060066 - id: vnf-data
67 name: vnf-data
68 short-name: vnf-data
Adam Israelc3e6c2e2018-03-01 09:31:50 -050069 type: VPORT
Adam Israelc3e6c2e2018-03-01 09:31:50 -050070 mgmt-interface:
Adam Israel88a49632018-04-10 13:04:57 -060071 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
Adam Israelc3e6c2e2018-03-01 09:31:50 -050080 vdu:
Adam Israel88a49632018-04-10 13:04:57 -060081 - id: mgmtVM
82 name: mgmtVM
83 image: xenial
Adam Israelc3e6c2e2018-03-01 09:31:50 -050084 count: '1'
Adam Israelc3e6c2e2018-03-01 09:31:50 -050085 vm-flavor:
Adam Israelc3e6c2e2018-03-01 09:31:50 -050086 vcpu-count: '1'
Adam Israel88a49632018-04-10 13:04:57 -060087 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'
Adam Israelc3e6c2e2018-03-01 09:31:50 -0500183"""
184
Adam Israelc3e6c2e2018-03-01 09:31:50 -0500185class PythonTest(unittest.TestCase):
186 n2vc = None
187
188 def setUp(self):
189
190 self.log = logging.getLogger()
191 self.log.level = logging.DEBUG
192
Adam Israel88a49632018-04-10 13:04:57 -0600193 self.loop = asyncio.get_event_loop()
194
195 # self.loop = asyncio.new_event_loop()
196 # asyncio.set_event_loop(None)
Adam Israelc3e6c2e2018-03-01 09:31:50 -0500197
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
Adam Israel88a49632018-04-10 13:04:57 -0600216 def get_descriptor(self, descriptor):
217 desc = None
Adam Israelc3e6c2e2018-03-01 09:31:50 -0500218 try:
Adam Israel88a49632018-04-10 13:04:57 -0600219 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]
Adam Israelc3e6c2e2018-03-01 09:31:50 -0500227 except ValueError:
228 assert False
Adam Israel88a49632018-04-10 13:04:57 -0600229 return desc
Adam Israelc3e6c2e2018-03-01 09:31:50 -0500230
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(
Adam Israel88a49632018-04-10 13:04:57 -0600256 self.n2vc.RemoveCharms(model_name, application_name, self.n2vc_callback)
Adam Israelc3e6c2e2018-03-01 09:31:50 -0500257 )
258 task.add_done_callback(functools.partial(self.n2vc_callback, None, None, None))
Adam Israelc3e6c2e2018-03-01 09:31:50 -0500259
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")
Adam Israel88a49632018-04-10 13:04:57 -0600265 nsd = self.get_descriptor(NSD_YAML)
266 vnfd = self.get_descriptor(VNFD_YAML)
267
268 if nsd and vnfd:
269
Adam Israelc3e6c2e2018-03-01 09:31:50 -0500270 vca_charms = os.getenv('VCA_CHARMS', None)
271
Adam Israel88a49632018-04-10 13:04:57 -0600272 params = {}
273 vnf_index = 0
Adam Israelc3e6c2e2018-03-01 09:31:50 -0500274
Adam Israel88a49632018-04-10 13:04:57 -0600275 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)
Adam Israelc3e6c2e2018-03-01 09:31:50 -0500280
Adam Israel88a49632018-04-10 13:04:57 -0600281 # 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'
Adam Israelc3e6c2e2018-03-01 09:31:50 -0500285
Adam Israel88a49632018-04-10 13:04:57 -0600286 # self.loop.run_until_complete(n.CreateNetworkService(nsd))
287 ns_name = "default"
Adam Israelc3e6c2e2018-03-01 09:31:50 -0500288
Adam Israel88a49632018-04-10 13:04:57 -0600289 vnf_name = self.n2vc.FormatApplicationName(
290 ns_name,
291 vnfd['name'],
292 str(vnf_index),
293 )
Adam Israelc3e6c2e2018-03-01 09:31:50 -0500294
Adam Israel88a49632018-04-10 13:04:57 -0600295 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 )
Adam Israelc3e6c2e2018-03-01 09:31:50 -0500306
Adam Israel88a49632018-04-10 13:04:57 -0600307 # 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)
Adam Israelc3e6c2e2018-03-01 09:31:50 -0500313
Adam Israel88a49632018-04-10 13:04:57 -0600314 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
Adam Israelc3e6c2e2018-03-01 09:31:50 -0500336 self.loop.run_forever()
337
338 # self.loop.run_until_complete(n.GetMetrics(vnfd, nsd=nsd))
Adam Israel88a49632018-04-10 13:04:57 -0600339
Adam Israelc3e6c2e2018-03-01 09:31:50 -0500340 # 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)