e8265ee0fb585cc10a2b5a19b9fc11dd40852cd4
[sim/o1-interface.git] / docs / overview.rst
1 .. This work is licensed under a Creative Commons Attribution 4.0 International License.
2 .. SPDX-License-Identifier: CC-BY-4.0
3 .. Copyright (C) 2019 highstreet technologies GmbH and others
4
5
6 sim/o1-interface Overview
7 ==========================
8
9 # Network Topology Simulator (NTS) | next generation
10
11 The Network Topology Simulator is a framework that allows simulating devices that expose a management interface through a NETCONF/YANG interface.
12
13 ## Description
14
15 ### Overview
16
17 The NETCONF/YANG management interface is simulated, and any YANG models can be loaded by the framework to be exposed. Random data is generated based on the specific models, such that each simulated device presents different data on its management interface.
18
19 The NTS framework is based on several open-source projects:
20 * [cJSON](https://github.com/DaveGamble/cJSON)
21 * [libcurl](https://curl.haxx.se)
22 * [libyang](https://github.com/CESNET/libyang)
23 * [sysrepo](https://github.com/sysrepo/sysrepo)
24 * [libnetconf2](https://github.com/CESNET/libnetconf2)
25 * [Netopeer2](https://github.com/CESNET/Netopeer2) 
26
27 The NTS Manager can be used to specify the simulation details and to manage the simulation environment at runtime.
28
29 Each simulated device is represented as a docker container, where the NETCONF Server is running. The creation and deletion of docker containers associated with simulated devices is handled by the NTS Manager. The NTS Manager is also running as a docker container and exposes a NETCONF/YANG interface to control the simulation.
30
31 ### NTS Manager
32
33 The purpose of the NTS Manager is to ease the utilization of the NTS framework. It enables the user to interact with the simulation framework through a NETCONF/YANG interface. The user has the ability to modify the simulation parameters at runtime and to see the status of the current state of the NTS. The NETCONF/YANG interface will be detailed below.
34
35 ```
36 module: nts-manager
37   +--rw simulation
38      +--rw network-functions
39      |  +--rw network-function* [function-type]
40      |     +--rw function-type                    identityref
41      |     +--rw started-instances                uint16
42      |     +--rw mounted-instances                uint16
43      |     +--rw mount-point-addressing-method?   enumeration
44      |     +--rw docker-instance-name             string
45      |     +--rw docker-version-tag               string
46      |     +--rw docker-repository                string
47      |     +--rw fault-generation
48      |     |  +--rw fault-delay-list* [index]
49      |     |  |  +--rw index           uint16
50      |     |  |  +--rw delay-period?   uint16
51      |     |  +--ro fault-count {faults-status}?
52      |     |     +--ro normal?     uint32
53      |     |     +--ro warning?    uint32
54      |     |     +--ro minor?      uint32
55      |     |     +--ro major?      uint32
56      |     |     +--ro critical?   uint32
57      |     +--rw netconf
58      |     |  +--rw faults-enabled?   boolean
59      |     |  +--rw call-home?        boolean
60      |     +--rw ves
61      |     |  +--rw faults-enabled?     boolean
62      |     |  +--rw pnf-registration?   boolean
63      |     |  +--rw heartbeat-period?   uint16
64      |     +--ro instances
65      |        +--ro instance* [name]
66      |           +--ro mount-point-addressing-method?   enumeration
67      |           +--ro name                             string
68      |           +--ro networking
69      |              +--ro docker-ip?     inet:ip-address
70      |              +--ro docker-port*   inet:port-number
71      |              +--ro host-ip?       inet:ip-address
72      |              +--ro host-port*     inet:port-number
73      +--rw sdn-controller
74      |  +--rw controller-ip?                       inet:ip-address
75      |  +--rw controller-port?                     inet:port-number
76      |  +--rw controller-netconf-call-home-port?   inet:port-number
77      |  +--rw controller-username?                 string
78      |  +--rw controller-password?                 string
79      +--rw ves-endpoint
80      |  +--rw ves-endpoint-protocol?      enumeration
81      |  +--rw ves-endpoint-ip?            inet:ip-address
82      |  +--rw ves-endpoint-port?          inet:port-number
83      |  +--rw ves-endpoint-auth-method?   authentication-method-type
84      |  +--rw ves-endpoint-username?      string
85      |  +--rw ves-endpoint-password?      string
86      |  +--rw ves-endpoint-certificate?   string
87      +--ro base-port?           inet:port-number
88      +--ro ssh-connections?     uint8
89      +--ro tls-connections?     uint8
90      +--ro cpu-usage?           percent
91      +--ro mem-usage?           uint32
92 ```
93
94 #### Detailed information about the YANG attributes
95
96 Under **simulation** there are 3 configuration containers and a couple of statistics leafs:
97 * **network-functions** - represents the simulation data, which will be best described below
98 * **sdn-controller** - this container groups the configuration related to the ODL based SDN controller that the simulated devices can connect to
99     * **controller-ip** - the IP address of the ODL based SDN controller where the simulated devices can be mounted. Both IPv4 and IPv6 are supported
100     * **controller-port** - the port of the ODL based SDN controller
101     * **controller-netconf-call-home-port** - the NETCONF Call Home port of the ODL based SDN controller
102     * **controller-username** - the username to be used when connecting to the ODL based SDN controller
103     * **controller-password** - the password to be used when connecting to the ODL based SDN controller
104 * **ves-endpoint** - this container groups the configuration related to the VES endpoint where the VES messages are targeted
105     * **ves-endpoint-protocol** - the protocol of the VES endpoint where VES messages are targeted
106     * **ves-endpoint-ip** - the IP address of the VES endpoint where VES messages are targeted
107     * **ves-endpoint-port** - the port address of the VES endpoint where VES messages are targeted
108     * **ves-endpoint-auth-method** - the authentication method to be used when sending the VES message to the VES endpoint. Possible values are:
109         + *no-auth* - no authentication
110         + *cert-only* - certificate only authentication in this case the certificate to be used for the communication must be configured
111         + *basic-auth* - classic username/password authentication in this case both the username and password need to be configured
112         + *cert-basic-auth* - authentication that uses both username/password and a certificate all three values need to be configured in this case
113     * **ves-endpoint-username** - the username to be used when authenticating to the VES endpoint
114     * **ves-endpoint-password** - the password to be used when authenticating to the VES endpoint
115     * **ves-endpoint-certificate** - the certificate to be used when authenticating to the VES endpoint
116 * base-port - status node indicating the start port for mapping the simulated network functions; ports are assigned in an increasing order starting from this base port
117 * ssh-connections - status node indicating the number of SSH Endpoints each network function instance exposes
118 * tls-connections - status node indicating the number of TLS Endpoints each network function instance exposes
119 * cpu-usage - status node indicating the **total** CPU usage of the simulation
120 * mem-usage - status node indicating the **total** memory usage of the simulation
121
122 Under the **network-functions** there is the **network-function** list. This list is automatically populated by the NTS Manager at start time with the available network functions. No changes at the actual list are allowed (adding or removing elements), only the changes of the properties of the elements have effect. The structure of an element of this list is described below:
123 * **function-type** - the function type
124 * **started-devices** - represents the number of simulated devices. The default value is 0, meaning that when the NTS is started, there are no simulated devices. When this value is increased to **n**, the NTS Manager starts docker containers in order to reach **n** simulated devices. If the value is decreased to **k**, the NTS Manager will remove docker containers in a LIFO manner, until the number of simulated devices reaches **k**
125 * **mounted-devices** - represents the number of devices to be mounted to an ODL based SDN Controller. The same phylosophy as in the case of the previous leaf applies. If this number is increased, the number of ODL mountpoints increases. Else, the simulated devices are being unmounted from ODL. The number of mounted devices cannot exceed the number of started devices. The details about the ODL controller where to mount/unmount are given by the **sdn-controller** container
126 * **mount-point-addressing-method** - addressing method of the mount point. Possible values are:
127     + *docker-mapping* - [default value] future started simulated devices will be mapped on the Docker container
128     + *host-mapping* - future started simulated devices will me mapped on the host's IP address and port based on *base-port*
129 * **docker-instance-name** - the prefix for future simulated devices (to this name a dash and an increasing number is added)
130 * **docker-version-tag** - a specific version tag for the Docker container to be ran. if empty, the latest version is ran
131 * **docker-repository** - the prefix for containing the Docker repository information. if local repository is used, value can be either blank or *local*
132 * **fault-generation** - container which groups the fault generation features, explained later
133 * **netconf** - container with settings for enabling or disabling netconf features
134     * **faults-enabled** - enable or disable faults over netconf
135     * **call-home** - enable the NETCONF Call Home feature. If set to 'true', each simulated device, when booting up, will try to Call Home to the SDN Controller.
136 * **ves** - container with settings for enabling or disabling VES features
137     * **faults-enabled** - enable or disable faults over VES
138     * **pnf-registration** - enable PNF registration on start
139     * **heartbeat-period** - the number of seconds between VES heartbeat messages
140     
141 #### Manager datastore changes mode of operation
142
143 Changing any value from **sdn-controller** or **ves-endpoint** containers will be propagated to all running simulated network functions, and all new ones will use the values here. In the same manner, triggering any changes to the **fault-generation**, **netconf** and **ves** settings in a network function element from the *network-function* list will automatically propagate to all running network functions of the same *function-type*. However, changing the *docker-\** leafs of the *network-function* won't propagate, as they're only used as settings for starting new network functions.
144
145 ### NTS network function 
146
147 The NTS network function represents the actual simulated device.
148
149 ```
150 module: nts-network-function
151   +--rw simulation
152      +--rw network-function
153      |  +--rw mount-point-addressing-method?   enumeration
154      |  +--rw fault-generation
155      |  |  +--rw fault-delay-list* [index]
156      |  |  |  +--rw index           uint16
157      |  |  |  +--rw delay-period?   uint16
158      |  |  +--ro fault-count {faults-status}?
159      |  |     +--ro normal?     uint32
160      |  |     +--ro warning?    uint32
161      |  |     +--ro minor?      uint32
162      |  |     +--ro major?      uint32
163      |  |     +--ro critical?   uint32
164      |  +--rw netconf
165      |  |  +--rw faults-enabled?   boolean
166      |  |  +--rw call-home?        boolean
167      |  +--rw ves
168      |     +--rw faults-enabled?     boolean
169      |     +--rw pnf-registration?   boolean
170      |     +--rw heartbeat-period?   uint16
171      +--rw sdn-controller
172      |  +--rw controller-ip?                       inet:ip-address
173      |  +--rw controller-port?                     inet:port-number
174      |  +--rw controller-netconf-call-home-port?   inet:port-number
175      |  +--rw controller-username?                 string
176      |  +--rw controller-password?                 string
177      +--rw ves-endpoint
178         +--rw ves-endpoint-protocol?      enumeration
179         +--rw ves-endpoint-ip?            inet:ip-address
180         +--rw ves-endpoint-port?          inet:port-number
181         +--rw ves-endpoint-auth-method?   authentication-method-type
182         +--rw ves-endpoint-username?      string
183         +--rw ves-endpoint-password?      string
184         +--rw ves-endpoint-certificate?   string
185
186   rpcs:
187     +---x datastore-random-populate
188     |  +--ro output
189     |     +--ro status    enumeration
190     +---x feature-control
191     |  +---w input
192     |  |  +---w features    ntsc:feature-type
193     |  +--ro output
194     |     +--ro status    enumeration
195     +---x invoke-notification
196     |  +---w input
197     |  |  +---w notification-format    enumeration
198     |  |  +---w notification-object    string
199     |  +--ro output
200     |     +--ro status    enumeration
201     +---x invoke-ves-pm-file-ready
202     |  +---w input
203     |  |  +---w file-location    string
204     |  +--ro output
205     |     +--ro status    enumeration
206     +---x clear-fault-counters
207        +--ro output
208           +--ro status    enumeration
209 ```
210
211 #### Detailed information about the YANG attributes
212
213 All de details and mechanisms of the **network-function** container are explained in the **NTS Manager** section. Besides this container, there are also a couple of RPCs defined:
214 * **datastore-random-populate** - calling this will trigger the network function to populate all its datastore with random data, and based on the *config.json* defined rules
215 * **feature-control** - calling this will enable selected features. currently available features are:
216     * **ves-file-ready** - enables VES file ready, and stats a FTP and a SFTP server on the network function
217     * **ves-heartbeat** - enabled VES heartbeat feature
218     * **ves-pnf-registration** - enables VES PNF registration
219     * **manual-notification-generation** - enables the manual notification generation feature
220     * **netconf-call-home** - enables NETCONF's Call Home feature
221     * **web-cut-through** - enables web cut through, adding the info to the ietf-system module
222 * **invoke-notification** - this RPC is used for forcing a simulated device to send a NETCONF notification, as defined by the user. 
223     - The **input** needed by the RPC:
224         - **notification-format** - can be either *json* or *xml*
225         - **notification-object** - this is a string containing the notification object that we are trying to send from the simulated device, in JSON format. **Please note that the user has the responsibility to ensure that the JSON object is valid, according to the definition of the notification in the YANG module.** There is no possibility to see what was wrong when trying to send an incorrect notification. The RPC will only respond with an "ERROR" status in that case, without further information. E.g. of a JSON containing a notification object of type ***otdr-scan-result*** defined in the ***org-openroadm-device*** YANG module: ***{"org-openroadm-device:otdr-scan-result":{"status":"Successful","status-message":"Scan result was successful","result-file":"/home/result-file.txt"}}***. **Please note that the notification object contains also the name of the YANG model defning it, as a namespace, as seen in the example.**
226     - The **output** returned by the RPC:
227         - **status** - if the notification was send successfully by the simulated device, the RPC will return a **SUCCESS** value. Else, the RPC will return a **ERROR** value.
228 * **invoke-ves-pm-file-ready** - as name impiles, it invokes a file ready VES request, with a specified *file-location*
229 * **clear-fault-counters** - clears all counters for the fault generation system. see **Fault generation** below.
230
231 #### Network function operation
232
233 Under usual operation, the network functions are managed by the manager which will perform the operations listed below. However, if a user chooses to, it can manually start up a network function, and manage it via NETCONF (datastore and RPCs).
234 1. Create and start Docker container
235 2. Set the VES and SDN controller data via NETCONF
236 3. Invoke **datastore-random-populate** RPC to populate the datastore
237 4. Invoke **feature-control**, enabling **ALL** the features.
238
239 #### Datastore random population
240
241 The datastore will be populated with random values on each of its leafs. However, certain there is some control on the population itself, which can be found in *config.json*, which is commented. Please note that the nodes below should be main nodes in *config.json*:
242 ```
243 "debug-max-string-size" : 50,       //max size of string. if not set, default is 255
244     
245 "populate-rules" : {
246     "excluded-modules": [           //modules to be excluded from populating
247         "sysrepo",
248         "sysrepo-monitoring",
249         "ietf-yang-library",
250         "ietf-netconf-acm",
251         "ietf-netconf-monitoring",
252         "nc-notifications",
253         "ietf-keystore",
254         "ietf-truststore",
255         "ietf-system",
256         "ietf-netconf-server"
257     ],
258     
259     "default-list-instances": 1,    //default number of instances a list or a leaflist should be populated with
260     "custom-list-instances" : [     //custom number of list instances. instance is schema name, and should reflect a list or a leaflist
261         {"/ietf-interfaces:interfaces/interface": 2}, //2 instances of this. if 0, list will be excluded from populating
262     ],
263     "restrict-schema" : [           //restrictions to certain schema nodes to a set of values (so no random here)
264         {"/ietf-interfaces:interfaces/interface/type" : ["iana-if-type:ethernetCsmacd", "other-value"]},
265         {"/ietf-interfaces:interfaces/interface/name" : ["name1", "name2"]}
266     ]
267 }
268 ```
269
270 #### Fault generation
271
272 Fault generation is controlled using a combination of JSON and YANG settings.
273 From the JSON perspective, the settings are as below:
274 ```
275 "alarm-rules" : {
276     "yang-notif-template" : "<xml ... %%severity%%  $$time$$  %%custom1%%>",
277     "choosing-method" : "random | linear",
278     "alarms" : [
279         {
280             //ves mandatory fields
281             "condition" : "",
282             "object"    : "",
283             "severity"  : "",
284             "date-time" : "$$time$$",
285             "specific-problem" : "",
286
287             //template custom fileds
288             "custom1" : "",
289             "custom2" : ""
290         }
291         ...
292         {
293             ...
294         }
295     ]
296 }
297 ```
298 * **alarm-rules** node should be a main node in *config.json* for the respective network function in order for the fault generation to be enabled
299     * **yang-notif-template** - template of the yang notification model in current network function. can be "" to disable notifications. must always be present
300     * **choosing-method** - method to choose the alarm. can be either *linear* or *random*, and must always be present
301     * **alarms** list of alarms to choose from by "choosing-method". it can contain any number of fields, custom ones, along with the mandatory VES fields presented below:
302         * **condition**
303         * **object**
304         * **severity** - should correspond to VES defined: NORMAL, WARNING, MINOR, MAJOR, CRITICAL (case sensitive)
305         * **date-time**
306         * **specific-problem**
307
308 On the **yang-notif-template** and on any of the fields, there are two options for creating "dynamic" content (also see example above):
309 * **variables** - any field put in between %% will be replaced with the field's value
310 * **functions** - function names are put in between $$. Available functions are:
311     * **time** - returns current timestamp in a YANG date-time format
312     * **uint8_counter** - a unique 8-bit counter, starting from 0, each time this function is found, the counter is automatically increased; when going above the max value, it will reset from 0
313     * **uint16_counter** - a unique 16-bit counter, starting from 0, each time this function is found, the counter is automatically increased; when going above the max value, it will reset from 0
314     * **uint32_counter** - a unique 32-bit counter, starting from 0, each time this function is found, the counter is automatically increased; when going above the max value, it will reset from 0
315
316 It is worth to mention that the replacement is done within any field, of any field. This means that it is possible to have nested fields and functions. See example for better understanding.
317
318 From the YANG perspective, one can control whether faults are enabled or disabled independently via NETCONF and/or VES, through their respective containers described in the sections above. The YANG **fault-generation** container contains:
319 * **fault-delay-list** - a list with elements which consists of *index* (unimportant, but needs to be unique) and *delay-period* which represents the number of seconds in between the current fault and the next fault. Please note that the fault is chosen from and based on the settings esablished in *config.json*
320 * **fault-count** - the status of the faults encountered by the network function; it is not present in the manager's schema
321
322 In order to clear the **fault-count** counters, on the **network-function** module there is a **clear-fault-counters** RPC which can be called via NETCONF.
323
324 ### NTS Application
325
326 Either of the two main functionalities (*manager* and *network-function*) are implemented by the same binary application. Besides this functionality, the application can also do some utility functions, which can be used if the application is ran from the CLI (command line interface), along with some parameters.
327
328 #### CLI paramters
329 The paramers are described below:
330 - --help - shows the help (also described here)
331 - --docker-init - is automatically used by Docker when building the images to install modules and enable features. Described in the next chapter. **Do not run manually**
332 - the two main modes:
333     - --manager - runs in manager mode
334     - --network-function - runs in network function mode
335 - global settings, which can be used with **ANY** of the other operating modes:
336     - --operational-only - used in testing. do not use the RUNNING datastore, only do the population on OPERATIONAL datastore
337     - --fixed-rand - used in testing. specify a fixed value seed for the randomness
338     - --verbose - set the verbose level. can range from 0 to 2, default is 1
339     - --workspace - set the current working workspace. the workspace must contain the *config* and *log* folders    
340 - test modes - do not use
341 - utilitary functions:
342     - --ls - list all modules in the datastore with their attributes
343     - --schema - list the schema of an xpath given as parameter
344     - --populate - populate the datastore upon starting
345     - --enable-features - enable all features upon starting, after (if requested) the populating was done
346     - --nc-server-init - initialize netconf server
347     - --loop - after everything is done, run an endless loop
348
349 #### Docker container initialization
350
351 The NTS app is responsible for initializing the Docker container upon build. What it actually does is described below:
352 1. Install modules located in the *deploy/yang/* folder recusively
353     - note that if a module requires startup data (mandatory data), this can be acheived by having an **XML** file with this data along the YANG file. For example, if, let's say *ietf-interfaces.yang* would require startup date, there must be a *ietf-interfaces.xml* located in the same folder.
354 2. Enable all YANG features of the modules, unless specifically excluded
355
356 If the initialization failes, the result is returned to the Docker builder, so the build will fail, and user can see the output. Docker initialization can be customized from the *config.json* file, as described below. The example is self-expainatory, and the *docker-rules* node needs to be a main node of *config.json*:
357
358 ```
359 "docker-rules": {
360     "excluded-modules": [          //excluded modules from installing
361         "module1",
362         "module2"
363     ],
364     "excluded-features": [         //excluded features from installing
365         "feature1",
366         "feature2"
367     ]
368 }
369 ```
370
371 ## Usage
372
373 The NTS Manager can be used to start any type of simulated network function.
374
375 ### Building the images
376
377 The `nts_build.sh` script should be used for building the docker images needed by the NTS to the local machine. This will create docker images for the Manager and for each type of simulated network function.
378
379 The user can also directly use the already built docker images, that are pushed to the highstreet docker repository. This can be done by using the `nts_pull_highstreet_repo.sh` script, which will pull all the images locally.
380
381 ### Starting the NTS Manager
382
383 The **nts-manager-ng** can be started using the docker-compose file in this repo. The file assumes that the docker images were pulled from the highstreet docker repository.
384
385 ```
386 docker-compose up
387 ```
388
389 Before starting, the user should set the environment variables defined in the docker-compose file according to his needs:
390 * **NETCONF_NTS_HOST_IP**: an IP address from the host, which should be used by systems outside the local machine to address the simulators;
391 * **NETCONF_NTS_HOST_BASE_PORT**: the port from where the allocation for the simulated network functions should start;
392 * **IPv6_ENABLED**: should be set to `true` if IPv6 is enabled in the docker daemon and the user wants to use IPv6 to address the simulated  network functions.
393
394 ## Release notes
395
396 ### version 1.0.3
397
398 [fixed] fixed issues where ODL could not parse the correct versions for yang files
399
400 ### version 1.0.2
401 - [fixed] bug that occured when trying to start a wrong instance (bad docker-repository or docker-tag)
402 - [fixed] when populating the fault-delay-list, if the sum of all the faults was 0, the network funciton kept on generating faults and crashed
403
404 ### version 1.0.1
405 - [feature-add] added web-cut-through feature
406 - [fixed] mount-point-addressing-method was mistakenly changing after starting
407
408 ### version 1.0.0
409 Initial release.