Improved integration tests
[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 # You can find the ip of the VCA by running `juju status -m controller` and looking for the DNS for Machine 0
59 export VCA_HOST=
60 export VCA_PORT=17070
61 # You can find these variables in ~/.local/share/juju/accounts.yaml
62 export VCA_USER=admin
63 export VCA_SECRET=PASSWORD
64 ```
65
66 ### Run the test(s)
67
68 *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.*
69
70 ```bash
71 nosetests3 --nocapture tests/test_python.py
72 ```
73
74 ## Known Issues
75
76 Many. This is still in active development for Release FOUR.
77
78 - 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.
79
80 ```
81 Exception ignored in: <generator object WebSocketCommonProtocol.close_connection at 0x7f29a3b3f780>                                     
82 Traceback (most recent call last):                                  
83   File "/home/stone/.local/lib/python3.6/site-packages/websockets/protocol.py", line 743, in close_connection                           
84     if (yield from self.wait_for_connection_lost()):                
85   File "/home/stone/.local/lib/python3.6/site-packages/websockets/protocol.py", line 768, in wait_for_connection_lost                   
86     self.timeout, loop=self.loop)
87   File "/usr/lib/python3.6/asyncio/tasks.py", line 342, in wait_for
88     timeout_handle = loop.call_later(timeout, _release_waiter, waiter)                                                                  
89   File "/usr/lib/python3.6/asyncio/base_events.py", line 543, in call_later                                                             
90     timer = self.call_at(self.time() + delay, callback, *args)      
91   File "/usr/lib/python3.6/asyncio/base_events.py", line 553, in call_at                                                                
92     self._check_closed()          
93   File "/usr/lib/python3.6/asyncio/base_events.py", line 357, in _check_closed                                                          
94     raise RuntimeError('Event loop is closed')                      
95 RuntimeError: Event loop is closed                                  
96 Exception ignored in: <generator object Queue.get at 0x7f29a2ac6938>                                                                    
97 Traceback (most recent call last):                                  
98   File "/usr/lib/python3.6/asyncio/queues.py", line 169, in get     
99     getter.cancel()  # Just in case getter is not done yet.         
100   File "/usr/lib/python3.6/asyncio/base_events.py", line 574, in call_soon                                                              
101     self._check_closed()          
102   File "/usr/lib/python3.6/asyncio/base_events.py", line 357, in _check_closed                                                          
103     raise RuntimeError('Event loop is closed')                      
104 RuntimeError: Event loop is closed                                  
105 Exception ignored in: <coroutine object AllWatcherFacade.Next at 0x7f29a3bd9990>                                                        
106 Traceback (most recent call last):                                  
107   File "/home/stone/src/osm/N2VC/modules/libjuju/juju/client/facade.py", line 412, in wrapper                                           
108     reply = await f(*args, **kwargs)                                
109   File "/home/stone/src/osm/N2VC/modules/libjuju/juju/client/_client1.py", line 59, in Next                                             
110     reply = await self.rpc(msg)   
111   File "/home/stone/src/osm/N2VC/modules/libjuju/juju/client/overrides.py", line 104, in rpc                                            
112     result = await self.connection.rpc(msg, encoder=TypeEncoder)    
113   File "/home/stone/src/osm/N2VC/modules/libjuju/juju/client/connection.py", line 306, in rpc                                           
114     result = await self._recv(msg['request-id'])                    
115   File "/home/stone/src/osm/N2VC/modules/libjuju/juju/client/connection.py", line 208, in _recv                                         
116     return await self.messages.get(request_id)                      
117   File "/home/stone/src/osm/N2VC/modules/libjuju/juju/utils.py", line 61, in get                                                        
118     value = await self._queues[id].get()                            
119   File "/usr/lib/python3.6/asyncio/queues.py", line 169, in get     
120     getter.cancel()  # Just in case getter is not done yet.         
121   File "/usr/lib/python3.6/asyncio/base_events.py", line 574, in call_soon                                                              
122     self._check_closed()          
123   File "/usr/lib/python3.6/asyncio/base_events.py", line 357, in _check_closed                                                          
124     raise RuntimeError('Event loop is closed')                      
125 RuntimeError: Event loop is closed
126 ```
127
128 ## Modules
129
130 To update the libjuju module:
131
132 Needs to be fully tested:
133 ```bash
134 git checkout master
135 git subtree pull --prefix=modules/libjuju/ --squash libjuju master
136 <resolve any merge conflicts>
137 git merge --continue
138 ```