dc0f747b11a48d7f3daf585e94731f03888a88c1
[osm/N2VC.git] / README.md
1 # N2VC
2
3 ## Objective
4
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.
6
7 N2VC relies on the IM module, enforcing compliance with the OSM Information Model.
8
9 ## Caveats
10
11 This library is in active development for OSM Release FOUR. The interface is subject to change prior to release.
12
13 ## Roadmap
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
19
20 ## Requirements
21
22 Because this is still in heavy development, there are a few manual steps required to use this library.
23
24
25 ```
26 # This list is incomplete
27 apt install python3-nose
28 ```
29
30 ### Install LXD and Juju
31
32 In order to run the test(s) included in N2VC, you'll need to install Juju locally.
33
34 *Note: It's not necessary to install the juju library via pip3; N2VC uses a version bundled within the modules/ directory.*
35
36 ```bash
37 snap install lxd
38 snap install juju --classic
39 ```
40
41 ## Metrics
42
43 ### Limitations
44
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.
48
49
50 ## Testing
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.
52
53 ### Export settings to run test
54
55 Export a few environment variables so the test knows where to find the VCA, and the compiled pingpong charm from the devops repository.
56
57 ```bash
58 # The directory where the Juju configuration is stored
59 export VCA_PATH=~/.local/share/juju
60
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}'`
63 export VCA_PORT=17070
64
65 # You can find these variables in ~/.local/share/juju/accounts.yaml
66 export VCA_USER=admin
67 export VCA_SECRET=PASSWORD
68
69 export LXD_HOST=`ifconfig lxdbr0  | grep 'inet '| cut -d: -f2 | awk '{ print $2}'`
70 export LXD_SECRET=
71 ```
72
73 ### Run the test(s)
74
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.*
76
77 ```bash
78 nosetests3 --nocapture tests/test_python.py
79 ```
80
81 ## Known Issues
82
83 Many. This is still in active development for Release FOUR.
84
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.
86
87 ```
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                                                                
99     self._check_closed()          
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                                                              
108     self._check_closed()          
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                                                              
129     self._check_closed()          
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
133 ```
134
135 ## Modules
136
137 To update the libjuju module:
138
139 Needs to be fully tested:
140 ```bash
141 git checkout master
142 git subtree pull --prefix=modules/libjuju/ --squash libjuju master
143 <resolve any merge conflicts>
144 git merge --continue
145 ```