5 The N2VC library provides an OSM-centric interface to the VCA. This enables any OSM module (SO, LCM, osmclient) to use a standard pattern for communicating with Juju and the charms responsible for configuring a VNF.
7 N2VC relies on the IM module, enforcing compliance with the OSM Information Model.
11 This library is in active development for OSM Release FOUR. The interface is subject to change prior to release.
14 - Create the N2VC API (in progress)
15 - Create a Python library implementing the N2VC API (in progress)
16 - Implement N2VC API in SO
17 - Implement N2VC API in lcm
18 - Add support for N2VC in OSMClient
22 Because this is still in heavy development, there are a few manual steps required to use this library.
26 # This list is incomplete
27 apt install python3-nose
30 ### Install LXD and Juju
32 In order to run the test(s) included in N2VC, you'll need to install Juju locally.
34 *Note: It's not necessary to install the juju library via pip3; N2VC uses a version bundled within the modules/ directory.*
38 snap install juju --classic
45 There are currently a few limitations with regard to metrics in Juju.
46 1. Metrics are polled by the Controller every five minutes. This interval is not modifiable
47 2. The Juju API and CLI only expose the most recently polled metric, so it's necessary to poll the N2VC `GetMetrics` method more often, and discard duplicate values.
51 A basic test has been written to exercise the functionality of the library, and to serve as a demonstration of how to use it.
53 ### Export settings to run test
55 Export a few environment variables so the test knows where to find the VCA, and the compiled pingpong charm from the devops repository.
58 # The directory where the Juju configuration is stored
59 export VCA_PATH=~/.local/share/juju
61 # You can find the ip of the VCA by running `juju status -m controller` and looking for the DNS for Machine 0
62 export VCA_HOST=`juju show-controller --format=json | jq -r '.osm["details"]["api-endpoints"][0]'|awk -F: '{print $1}'`
65 # You can find these variables in ~/.local/share/juju/accounts.yaml
67 export VCA_SECRET=PASSWORD
69 export LXD_HOST=`ifconfig lxdbr0 | grep 'inet '| cut -d: -f2 | awk '{ print $2}'`
75 *Note: There is a bug in the cleanup of the N2VC/Juju that will throw an exception after the test has finished. This is on the list of things to fix for R4 and should not impact your tests or integration.*
78 nosetests3 --nocapture tests/test_python.py
83 Many. This is still in active development for Release FOUR.
85 - An exception is thrown after using N2VC, probably related to the internal AllWatcher used by juju.Model. This shouldn't break usage of N2VC, but it is ugly and needs to be fixed.
88 Exception ignored in: <generator object WebSocketCommonProtocol.close_connection at 0x7f29a3b3f780>
89 Traceback (most recent call last):
90 File "/home/stone/.local/lib/python3.6/site-packages/websockets/protocol.py", line 743, in close_connection
91 if (yield from self.wait_for_connection_lost()):
92 File "/home/stone/.local/lib/python3.6/site-packages/websockets/protocol.py", line 768, in wait_for_connection_lost
93 self.timeout, loop=self.loop)
94 File "/usr/lib/python3.6/asyncio/tasks.py", line 342, in wait_for
95 timeout_handle = loop.call_later(timeout, _release_waiter, waiter)
96 File "/usr/lib/python3.6/asyncio/base_events.py", line 543, in call_later
97 timer = self.call_at(self.time() + delay, callback, *args)
98 File "/usr/lib/python3.6/asyncio/base_events.py", line 553, in call_at
100 File "/usr/lib/python3.6/asyncio/base_events.py", line 357, in _check_closed
101 raise RuntimeError('Event loop is closed')
102 RuntimeError: Event loop is closed
103 Exception ignored in: <generator object Queue.get at 0x7f29a2ac6938>
104 Traceback (most recent call last):
105 File "/usr/lib/python3.6/asyncio/queues.py", line 169, in get
106 getter.cancel() # Just in case getter is not done yet.
107 File "/usr/lib/python3.6/asyncio/base_events.py", line 574, in call_soon
109 File "/usr/lib/python3.6/asyncio/base_events.py", line 357, in _check_closed
110 raise RuntimeError('Event loop is closed')
111 RuntimeError: Event loop is closed
112 Exception ignored in: <coroutine object AllWatcherFacade.Next at 0x7f29a3bd9990>
113 Traceback (most recent call last):
114 File "/home/stone/src/osm/N2VC/modules/libjuju/juju/client/facade.py", line 412, in wrapper
115 reply = await f(*args, **kwargs)
116 File "/home/stone/src/osm/N2VC/modules/libjuju/juju/client/_client1.py", line 59, in Next
117 reply = await self.rpc(msg)
118 File "/home/stone/src/osm/N2VC/modules/libjuju/juju/client/overrides.py", line 104, in rpc
119 result = await self.connection.rpc(msg, encoder=TypeEncoder)
120 File "/home/stone/src/osm/N2VC/modules/libjuju/juju/client/connection.py", line 306, in rpc
121 result = await self._recv(msg['request-id'])
122 File "/home/stone/src/osm/N2VC/modules/libjuju/juju/client/connection.py", line 208, in _recv
123 return await self.messages.get(request_id)
124 File "/home/stone/src/osm/N2VC/modules/libjuju/juju/utils.py", line 61, in get
125 value = await self._queues[id].get()
126 File "/usr/lib/python3.6/asyncio/queues.py", line 169, in get
127 getter.cancel() # Just in case getter is not done yet.
128 File "/usr/lib/python3.6/asyncio/base_events.py", line 574, in call_soon
130 File "/usr/lib/python3.6/asyncio/base_events.py", line 357, in _check_closed
131 raise RuntimeError('Event loop is closed')
132 RuntimeError: Event loop is closed
137 To update the libjuju module:
139 Needs to be fully tested:
142 git subtree pull --prefix=modules/libjuju/ --squash libjuju master
143 <resolve any merge conflicts>