<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://osm.etsi.org/wikipub/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Cardosoi</id>
	<title>OSM Public Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://osm.etsi.org/wikipub/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Cardosoi"/>
	<link rel="alternate" type="text/html" href="https://osm.etsi.org/wikipub/index.php/Special:Contributions/Cardosoi"/>
	<updated>2026-05-06T17:01:26Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.1</generator>
	<entry>
		<id>https://osm.etsi.org/wikipub/index.php?title=OSM_RO_VNFFG_implementation&amp;diff=2422</id>
		<title>OSM RO VNFFG implementation</title>
		<link rel="alternate" type="text/html" href="https://osm.etsi.org/wikipub/index.php?title=OSM_RO_VNFFG_implementation&amp;diff=2422"/>
		<updated>2018-03-16T14:36:08Z</updated>

		<summary type="html">&lt;p&gt;Cardosoi: Completed first version of VNFFG implementation doc&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Virtual Network Function Forwarding Graph Descriptor (VNFFGD) in OSM ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:vnffg_fig1.png|700px|Figure 1: VNFFGD Data Model from OSM R2 Information Model.]]&lt;br /&gt;
&lt;br /&gt;
VNFFGD is a well-defined data model from ETSI NFV (http://www.etsi.org/deliver/etsi_gs/NFV-IFA/001_099/014/02.01.01_60/gs_NFV-IFA014v020101p.pdf) which was subsequently adopted by OSM in its own informational model (https://osm.etsi.org/wikipub/images/2/26/OSM_R2_Information_Model.pdf).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;So how is VNFFG architected in OSM, specifically RO, and how is that communicated to the VIM layer by making use of standard Service Function Chaining?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:vnffg_fig2.png|700px|Figure 2: OSM R3 Architecture overlaid with changes made for VNFFGD support (in see numbers).]]&lt;br /&gt;
&lt;br /&gt;
All of the changes to enable VNFFG support in OSM have been applied to the RO (Resource Orchestrator) module, the fundamental component that needs such support (since it interacts with VIMs and/or SDN controllers). Additional VNFFG-related changes should be enabled in other projects, such as the Service Orchestrator.&lt;br /&gt;
&lt;br /&gt;
Figure 2 above shows the overall OSM architecture and delineates 4 components that were changed within the RO in order to support VNFFGD to VIM-level SFC.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== API Service &amp;amp; Utilities ===&lt;br /&gt;
&lt;br /&gt;
Best categorized as being part of the API Service &amp;amp; Utilities (changed element #1) in Figure 2, YAML template examples of a Network Service with a VNFFG and a new VNF have been added to the examples folder of the OSM RO:&lt;br /&gt;
&amp;lt;pre&amp;gt;scenarios/examples/v3_3vnf_2vdu_1vnffg_nsd.yaml&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;vnfs/examples/v3_2vdu_vnfd.yaml&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Figure 3 below outlines the example VNFFG and also, in light green, that it could expand to multiple Rendered Service Paths (RSPs).&lt;br /&gt;
&lt;br /&gt;
[[File:vnffg_fig3.png|700px|Figure 3: Example of a VNFFG (dark green delimits the example VNFFG contributed).]]&lt;br /&gt;
&lt;br /&gt;
The VNFFGD is composed of multiple RSPs (Rendered Service Paths, or Network Forwarding Paths in pure ETSI NFV terminology), and each of those states what VNFs should process the traffic and what actual traffic should be processed (the Classifier). A Classifier is a list of match attributes, and they can be traffic classifications such as HTTP. By definition, a VNF can have multiple VDUs which are, essentially, instances or units of that VNF – mainly used for scaling.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Resource Orchestrator Engine ===&lt;br /&gt;
&lt;br /&gt;
The database definition and migration present in &amp;lt;code&amp;gt;database_utils/migrate_mano_db.sh&amp;lt;/code&amp;gt; have been changed to support the storing of VNFFGD and related models.  They are logically part of the Resource Orchestrator Engine, outlined as changed element #2 in the figure above.&lt;br /&gt;
&lt;br /&gt;
Also part of this component is the NFVO engine itself, split between &amp;lt;code&amp;gt;nfvo.py&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;nfvo_db.py&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;vim_thread.py&amp;lt;/code&amp;gt;.&lt;br /&gt;
Regarding the first two, changes were made to process the new VNFFG element of a Network Service Descriptor (NSD), provided via YAML file, and store its information in internal database tables, also mapping to existing descriptors such as VNFDs. An HTTP server runs automatically and interacts with the Resource Orchestrator Engine to provide/request data.&lt;br /&gt;
Regarding &amp;lt;code&amp;gt;vim_thread.py&amp;lt;/code&amp;gt;, changes were made so that, when a Network Scenario Instance is created, it is able to process existing NSDs that include a VNFFGD. This module’s role is to call the VIM Plugin component outlined in Figure 2 and, to support VNFFGD, special calls have to be made to the VIM Plugin. Essentially, the upper part of Resource Orchestrator Engine will insert tasks in the VIM thread, so that it can call VIM connector’s normalized interface for the creation of networks, functions, service function chains (the eventual transformation of a VNFFG), etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== VIM Plugin ===&lt;br /&gt;
&lt;br /&gt;
Or VIM Connector, aims at providing a unified, abstract interface for the calling of typical VIM operations, such as creating compute units or network functions on a Virtual Infrastructure Manager or Cloud Management System. OSM allows different VIMs to be plugged in, and this is the plug point for those. This component has been changed to provide a unified Service Function Chaining interface, which will be called by the VIM thread after the Resource Orchestrator Engine has translated the VNFFGD into specific tasks to be carried by the VIM thread.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== OpenStack VIM Plugin ===&lt;br /&gt;
&lt;br /&gt;
A specific implementation of the Service Function Chaining interface added to the abstract VIM plugin was developed for OpenStack. This implementation calls the OpenStack Queen&#039;s networking-sfc API (https://docs.openstack.org/networking-sfc/queens) which leverages previous endeavours the team has done, namely the NSH dataplane support when using the Neutron Open vSwitch driver, making OSM an NFV Orchestrator able to instantiate NSH-based SFCs via the definition of a VNFFGD. This brings together efforts from ETSI NFV and IETF SFC.&lt;br /&gt;
&lt;br /&gt;
For reference, the VIM Plugin interface for SFC contains the following methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def new_classification(self, name, ctype, definition)&lt;br /&gt;
def get_classification(self, classification_id)&lt;br /&gt;
def get_classification_list(self, filter_dict={})&lt;br /&gt;
def delete_classification(self, classification_id)&lt;br /&gt;
def new_sfi(self, name, ingress_ports, egress_ports, sfc_encap=True)&lt;br /&gt;
def get_sfi(self, sfi_id)&lt;br /&gt;
def get_sfi_list(self, filter_dict={})&lt;br /&gt;
def delete_sfi(self, sfi_id)&lt;br /&gt;
def new_sf(self, name, sfis, sfc_encap=True)&lt;br /&gt;
def get_sf(self, sf_id)&lt;br /&gt;
def get_sf_list(self, filter_dict={})&lt;br /&gt;
def delete_sf(self, sf_id)&lt;br /&gt;
def new_sfp(self, name, classifications, sfs, sfc_encap=True, spi=None)&lt;br /&gt;
def get_sfp(self, sfp_id)&lt;br /&gt;
def get_sfp_list(self, filter_dict={})&lt;br /&gt;
def delete_sfp(self, sfp_id)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which use IETF SFC terminology, given that this is an appropriate level to apply IETF SFC concepts (service plane and SFC domain)&lt;/div&gt;</summary>
		<author><name>Cardosoi</name></author>
	</entry>
	<entry>
		<id>https://osm.etsi.org/wikipub/index.php?title=OSM_RO_VNFFG_implementation&amp;diff=2421</id>
		<title>OSM RO VNFFG implementation</title>
		<link rel="alternate" type="text/html" href="https://osm.etsi.org/wikipub/index.php?title=OSM_RO_VNFFG_implementation&amp;diff=2421"/>
		<updated>2018-03-16T14:07:52Z</updated>

		<summary type="html">&lt;p&gt;Cardosoi: Updated images&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Virtual Network Function Forwarding Graph Descriptor (VNFFGD) in OSM ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:vnffg_fig1.png|600px|Figure 1: VNFFGD Data Model from OSM R2 Information Model.]]&lt;br /&gt;
[[File:vnffg_fig2.png|600px|Figure 2: OSM R3 Architecture overlaid with changes made for VNFFGD support (in see numbers).]]&lt;br /&gt;
[[File:vnffg_fig3.png|600px|Figure 3: Example of a VNFFG (dark green delimits the example VNFFG contributed).]]&lt;/div&gt;</summary>
		<author><name>Cardosoi</name></author>
	</entry>
	<entry>
		<id>https://osm.etsi.org/wikipub/index.php?title=File:Vnffg_fig3.png&amp;diff=2420</id>
		<title>File:Vnffg fig3.png</title>
		<link rel="alternate" type="text/html" href="https://osm.etsi.org/wikipub/index.php?title=File:Vnffg_fig3.png&amp;diff=2420"/>
		<updated>2018-03-16T14:04:13Z</updated>

		<summary type="html">&lt;p&gt;Cardosoi: Example of a VNFFG (dark green delimits the example VNFFG contributed).&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Example of a VNFFG (dark green delimits the example VNFFG contributed).&lt;/div&gt;</summary>
		<author><name>Cardosoi</name></author>
	</entry>
	<entry>
		<id>https://osm.etsi.org/wikipub/index.php?title=File:Vnffg_fig2.png&amp;diff=2419</id>
		<title>File:Vnffg fig2.png</title>
		<link rel="alternate" type="text/html" href="https://osm.etsi.org/wikipub/index.php?title=File:Vnffg_fig2.png&amp;diff=2419"/>
		<updated>2018-03-16T14:03:33Z</updated>

		<summary type="html">&lt;p&gt;Cardosoi: Example of a VNFFG (dark green delimits the example VNFFG contributed).&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Example of a VNFFG (dark green delimits the example VNFFG contributed).&lt;/div&gt;</summary>
		<author><name>Cardosoi</name></author>
	</entry>
	<entry>
		<id>https://osm.etsi.org/wikipub/index.php?title=File:Vnffg_fig1.png&amp;diff=2418</id>
		<title>File:Vnffg fig1.png</title>
		<link rel="alternate" type="text/html" href="https://osm.etsi.org/wikipub/index.php?title=File:Vnffg_fig1.png&amp;diff=2418"/>
		<updated>2018-03-16T14:03:10Z</updated>

		<summary type="html">&lt;p&gt;Cardosoi: OSM R3 Architecture overlaid with changes made for VNFFGD support (in see numbers).&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;OSM R3 Architecture overlaid with changes made for VNFFGD support (in see numbers).&lt;/div&gt;</summary>
		<author><name>Cardosoi</name></author>
	</entry>
	<entry>
		<id>https://osm.etsi.org/wikipub/index.php?title=OSM_RO_VNFFG_implementation&amp;diff=2417</id>
		<title>OSM RO VNFFG implementation</title>
		<link rel="alternate" type="text/html" href="https://osm.etsi.org/wikipub/index.php?title=OSM_RO_VNFFG_implementation&amp;diff=2417"/>
		<updated>2018-03-16T14:02:32Z</updated>

		<summary type="html">&lt;p&gt;Cardosoi: all image references&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Virtual Network Function Forwarding Graph Descriptor (VNFFGD) in OSM ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:vnffg_fig1.png||Figure 1: VNFFGD Data Model from OSM R2 Information Model.]]&lt;br /&gt;
[[File:vnffg_fig2.png||Figure 2: OSM R3 Architecture overlaid with changes made for VNFFGD support (in see numbers).]]&lt;br /&gt;
[[File:vnffg_fig3.png||Figure 3: Example of a VNFFG (dark green delimits the example VNFFG contributed).]]&lt;/div&gt;</summary>
		<author><name>Cardosoi</name></author>
	</entry>
	<entry>
		<id>https://osm.etsi.org/wikipub/index.php?title=OSM_RO_VNFFG_implementation&amp;diff=2416</id>
		<title>OSM RO VNFFG implementation</title>
		<link rel="alternate" type="text/html" href="https://osm.etsi.org/wikipub/index.php?title=OSM_RO_VNFFG_implementation&amp;diff=2416"/>
		<updated>2018-03-16T13:56:56Z</updated>

		<summary type="html">&lt;p&gt;Cardosoi: testing figure add&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Virtual Network Function Forwarding Graph Descriptor (VNFFGD) in OSM ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Example.jpg||Figure 1: VNFFGD Data Model from OSM R2 Information Model]]&lt;/div&gt;</summary>
		<author><name>Cardosoi</name></author>
	</entry>
	<entry>
		<id>https://osm.etsi.org/wikipub/index.php?title=OSM_RO_VNFFG_implementation&amp;diff=2415</id>
		<title>OSM RO VNFFG implementation</title>
		<link rel="alternate" type="text/html" href="https://osm.etsi.org/wikipub/index.php?title=OSM_RO_VNFFG_implementation&amp;diff=2415"/>
		<updated>2018-03-16T13:54:24Z</updated>

		<summary type="html">&lt;p&gt;Cardosoi: reserving page for VNFFG&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Cardosoi</name></author>
	</entry>
	<entry>
		<id>https://osm.etsi.org/wikipub/index.php?title=Developer_HowTo_for_RO_Module&amp;diff=1838</id>
		<title>Developer HowTo for RO Module</title>
		<link rel="alternate" type="text/html" href="https://osm.etsi.org/wikipub/index.php?title=Developer_HowTo_for_RO_Module&amp;diff=1838"/>
		<updated>2017-10-23T13:01:30Z</updated>

		<summary type="html">&lt;p&gt;Cardosoi: /* RO Client modules */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Getting Started==&lt;br /&gt;
The RO Module is implemented by openmano. The recommended Linux distribution for development is Ubuntu 16.04 LTS Server. PyCharm is a nice and easy to use tool for development and debugging.&lt;br /&gt;
&lt;br /&gt;
The step [[Release_1_Installation]] installs all OSM modules in containers. However, for development, a virtual machine may be more suitable. To install the openmano module you can run a script that installs the required packages, clone the project from &#039;&#039;git clones https://osm.etsi.org/gerrit/osm/RO&#039;&#039; and configures openmano client and other utility scripts at path&lt;br /&gt;
 wget -O install-openmano.sh &amp;quot;https://osm.etsi.org/gitweb/?p=osm/RO.git;a=blob_plain;f=scripts/install-openmano.sh&amp;quot;&lt;br /&gt;
 chmod +x install-openmano.sh&lt;br /&gt;
 sudo ./install-openmano.sh -q --develop   #-h for help&lt;br /&gt;
&lt;br /&gt;
See also and follow [[Workflow_with_OSM_tools#Clone_your_project]]&lt;br /&gt;
&lt;br /&gt;
New code features must be incorporated to master:&lt;br /&gt;
 git checkout master&lt;br /&gt;
Generate a &amp;quot;.gitignore&amp;quot;, you can use the &#039;&#039;.gitignore-common&#039;&#039; example that skips PyCharm and Eclipse files&lt;br /&gt;
 cp RO/.gitignore-common RO/.gitignore&lt;br /&gt;
 #edit to include your local files to ignore&lt;br /&gt;
Prepare your git environment to push with a proper user/email, push to gerrit. See and configure:&lt;br /&gt;
&amp;lt;p&amp;gt;[[Workflow_with_OSM_tools#Configure_your_Git_environment]]&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;[[Workflow_with_OSM_tools#Commit_changes_to_your_local_project]]&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;[[ Workflow_with_OSM_tools#Push_your_contribution_to_Gerrit]]&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programming Language==&lt;br /&gt;
The RO module uses Python2. However Python3 conventions for a possible future migration should be used as far as possible. For example:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! BAD Python2&lt;br /&gt;
! OK  Python2 compatible with python3&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;format test string %s number %d&amp;quot; % (st, num)&lt;br /&gt;
| &amp;quot;format test string {} number {}&amp;quot;.format(st, num)&lt;br /&gt;
|-&lt;br /&gt;
| print a, b, c&lt;br /&gt;
| print(a,b,c)&lt;br /&gt;
|-&lt;br /&gt;
| except Exception, e&lt;br /&gt;
| except Exception as e&lt;br /&gt;
|-&lt;br /&gt;
| if type(x) == X:&lt;br /&gt;
| if isinstance(x,X):&lt;br /&gt;
|}&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Descriptors can be YAML (prefered because more readable and allow comments) or JSON&lt;br /&gt;
&lt;br /&gt;
==Code Style==&lt;br /&gt;
Please follow PEP8 style guide for all the Python code.&lt;br /&gt;
&lt;br /&gt;
===Logging===&lt;br /&gt;
Use the appropriate logging levels when logging the messages. An example is shown below:&lt;br /&gt;
    self.logger.debug(&amp;quot;Changing state to %s&amp;quot;, next_state)&lt;br /&gt;
&lt;br /&gt;
Logging levels (general and per module) are specified at &#039;&#039;&#039;openmanod.cfg&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Try to use few useful logs, not verbose, that brings useful information. For example, in case of fail getting a server, the complete URL should be provided.&lt;br /&gt;
&lt;br /&gt;
Avoid several logs together&lt;br /&gt;
&lt;br /&gt;
  WRONG:&lt;br /&gt;
  self.looger.debug(&amp;quot;Entering in method A&amp;quot;)&lt;br /&gt;
  self.logger.debug(&amp;quot;Contacting server&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  RIGHT:&lt;br /&gt;
  self.logger.debug(&amp;quot;method A, contacting server %s&amp;quot;, url)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the traceback is needed(call stack that generate the exception) , use the &amp;quot;exc_info=True&amp;quot; parameter&lt;br /&gt;
  self.logger.error(&amp;quot;Exception %s when ...&amp;quot;, exception, exc_info=True)&lt;br /&gt;
&lt;br /&gt;
===Exceptions===&lt;br /&gt;
Code must be wrote in a way that functions and methods raise an exception when something goes wrong, instead of returning a negative or false value.&lt;br /&gt;
&lt;br /&gt;
Example&lt;br /&gt;
  WRONG&lt;br /&gt;
    def get_ip_address():&lt;br /&gt;
        ...&lt;br /&gt;
        if fail:&lt;br /&gt;
            return False, &amp;quot;Fail because xxx&amp;quot;&lt;br /&gt;
        return True, ip&lt;br /&gt;
    &lt;br /&gt;
    ...&lt;br /&gt;
    result, ip = get_ip_address()&lt;br /&gt;
    if not result:&lt;br /&gt;
        return False, &amp;quot;Cannot get ip address...&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  RIGHT&lt;br /&gt;
    def get_ip_address():&lt;br /&gt;
        ...&lt;br /&gt;
        if fail:&lt;br /&gt;
            raise customException(&amp;quot;Fail because ...&amp;quot;)&lt;br /&gt;
        return ip&lt;br /&gt;
    &lt;br /&gt;
    ...&lt;br /&gt;
    try:&lt;br /&gt;
        ip = get_ip_address()&lt;br /&gt;
        ...&lt;br /&gt;
    except customException as e:&lt;br /&gt;
        raise customException2(str(e))&lt;br /&gt;
&lt;br /&gt;
==Directory Organization==&lt;br /&gt;
The code organized into the following high level directories: &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/&#039;&#039;&#039; contains the entry server file &#039;&#039;openmanod&#039;&#039; and client &#039;&#039;openmano&#039;&#039; code &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/osm_ro&#039;&#039;&#039; contains the RO server code files &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/test&#039;&#039;&#039; contains scripts and code for testing &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/database_utils&#039;&#039;&#039; contains scripts for database creation, dumping and migration &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/scripts&#039;&#039;&#039; general scripts, as installation, execution, reporting &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/scenarios&#039;&#039;&#039; examples and templates of network scnario descriptors &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/vnfs&#039;&#039;&#039; examples and templates of VNF descriptors &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==RO Architecture==&lt;br /&gt;
[[File:OpenmanoArchitecture.png|400px]]&lt;br /&gt;
&lt;br /&gt;
===RO Server modules===&lt;br /&gt;
The RO module contains the following modules&lt;br /&gt;
* &#039;&#039;&#039;openmanod&#039;&#039;&#039; is the main program. It reads the configuration file (openmanod.cfg) and execute the httpserver and wait for the end&lt;br /&gt;
* &#039;&#039;&#039;httpserver.py&#039;&#039;&#039; is a thread that implements the northbound API interface, uses python bottle module. Calls main engine methods to perform the tasks&lt;br /&gt;
* &#039;&#039;&#039;nfvo.py&#039;&#039;&#039; is the main engine, implementing all the methods for the creation, deletion and management of vnfs, scenarios and instances. Operations against a VIM are asynchornous. ACTIONs to be done are stored at database before returning ok to the client&lt;br /&gt;
* &#039;&#039;&#039;nfvo_db.py&#039;&#039;&#039; is the module in charge of database operations. Uses base &#039;&#039;&#039;db_base.py&#039;&#039;&#039;. Database is managed with MySQLdb python library&lt;br /&gt;
* &#039;&#039;&#039;openmano_schemas.py&#039;&#039;&#039; is a dictionary schemas used to validate API request and response content using jsonschema library&lt;br /&gt;
* &#039;&#039;&#039;vim_thread.py&#039;&#039;&#039; There is a thread per VIM and credentials. It performs basic tasks of creating/deleting VM, networks, flavors, etc. In addition it refreshes the VM and network status. It calls vimconn.py methods &lt;br /&gt;
* &#039;&#039;&#039;vimconn.py&#039;&#039;&#039; is the base class for the VIM plugin. It contains the definition of the methods to be implemented. The inherited &#039;&#039;&#039;vimconn_openstack.py&#039;&#039;&#039;, &#039;&#039;&#039;vimconn_openvim.py&#039;&#039;&#039;, &#039;&#039;&#039;vimconn_vmware&#039;&#039;&#039; and &#039;&#039;&#039;vimconn_aws&#039;&#039;&#039; implements the operations against the concrete VIM type. OpenStack plugin uses the python-*client libraries, meanwhile Openvim plugin uses direct http requests.&lt;br /&gt;
* &#039;&#039;&#039;console_proxy_thread.py&#039;&#039;&#039; is a thread that implements a TCP/IP proxy for the console access to a VIM&lt;br /&gt;
&lt;br /&gt;
===RO Client modules===&lt;br /&gt;
Other modules not part of the server are:&lt;br /&gt;
* &#039;&#039;&#039;openmano&#039;&#039;&#039; is a CLI client&lt;br /&gt;
* &#039;&#039;&#039;openmanoclient.py&#039;&#039;&#039; is a client python library for managing openmano server&lt;br /&gt;
&lt;br /&gt;
===ACTIONS and TASKS===&lt;br /&gt;
ACTIONS are a a group of tasks performed against a a concrete instance-scenarios (NS record). The creation and deletion of the instance-scenario itself is an action. As it is asynchonous, NBI returns an &amp;quot;Action_id&amp;quot; that can be used to check the status. For each action, nfvo.py generates individual tasks for the related VIMs. Tasks are both stored at database and sent to the related vim_thread.py. A task has a concrete relation with a VIM, e.g. create/delete a VM, a network, ... look for a flavor, network, ...&lt;br /&gt;
&lt;br /&gt;
===Database content===&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
==Database changes==&lt;br /&gt;
Database schema can be changed if needed. It is recomended to use a graphical tool (e.g. Heidy) to change database and change it back and copy the SQL commands. Make this steps:&lt;br /&gt;
&lt;br /&gt;
1. openmanod: increment __version__, version_date and database_version&lt;br /&gt;
2. database_utils/migrate_mano_db.sh. See the three &amp;quot;TODO&amp;quot;&lt;br /&gt;
2a. Increment LAST_DB_VERSION&lt;br /&gt;
2b. Annotate a comment to have a track of versions: [ $OPENMANO_VER_NUM -ge 50XX ] &amp;amp;&amp;amp; DB_VERSION=XX  #0.5.XX =&amp;gt;  XX&lt;br /&gt;
3c. Generate new methods function upgrade_to_XX() and function downgrade_from_XX. Insert here the sql commands. Last sql command over schema_version is quite important to detect the database version.&lt;br /&gt;
&lt;br /&gt;
Test several upgrades/downgrades to version 20 with &amp;quot;migrate_mano_db.sh&amp;quot; and &amp;quot;migrate_mano_db.sh 20&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Package dependency osm-im==&lt;br /&gt;
It is under IM repository. It contains the OSM models. Used models at RO are under &amp;lt;IM&amp;gt;/models/yang/vnfd.yang and &amp;lt;IM&amp;gt;/models/yang/nsd.yang. More modules will be incorporated in the future.&lt;br /&gt;
&lt;br /&gt;
When IM is maked, pyangbind generates python source files imported at RO. They are used to validate and load a yaml/json VNFD and NSD catalog descriptor.&lt;br /&gt;
&lt;br /&gt;
Method pybindJSONDecoder.load_ietf_json from pyangbind is used to parse and load the descriptor. A structure of nested YANG classes are generated and used at &amp;lt;RO&amp;gt;/osm_ro/nfvo.py methods new_vnfd_v3 and new_nsd_v3. RO supports backward compatibility with old format descriptors. NBI (osm_ro/httpserver.py) uses .../v3/... at URL to diferenciate between old and new descriptors. CLI (openmano) detects automatically if the descriptor is in old format or in OSM format to send the request to the server using the old URL or the new &amp;quot;v3&amp;quot; URL&lt;br /&gt;
&lt;br /&gt;
===Installation===&lt;br /&gt;
The OSM binary installation install this package. In case of needed you can install/update it manually by:&lt;br /&gt;
&lt;br /&gt;
  apt-get update&lt;br /&gt;
  apt-get install make git python python-pip tox debhelper python-bitarray python-lxml&lt;br /&gt;
  pip install --upgrade pip&lt;br /&gt;
  # If not inside a container. Use &amp;quot;sudo -HE&amp;quot; to get root privileges for pip installation&lt;br /&gt;
  pip install pyangbind stdeb&lt;br /&gt;
  git clone https://osm.etsi.org/gerrit/osm/IM&lt;br /&gt;
  make -C IM clean all&lt;br /&gt;
  dpkg -i IM/deb_dist/python-pyang_*.deb&lt;br /&gt;
  dpkg -i IM/deb_dist/python-pyangbind_*.deb&lt;br /&gt;
  dpkg -i IM/deb_dist/python-osm-im_*.deb&lt;br /&gt;
  # Use this line to check if it is installed and where  &lt;br /&gt;
  python -c &#039;import osm_im; print osm_im.__path__[0]&#039;&lt;br /&gt;
&lt;br /&gt;
==Package dependency lib-osm-openvim==&lt;br /&gt;
&lt;br /&gt;
It is under openvim repository. RO uses a library for the SDN assist that is in charge of performing the underlay dataplane connectivity using an openflow controller. osm-openvim and lib-osm-openvim are diffent, though they share same pieces of code. lib-osm-openvim uses a different database name (mano_vim_db) so that openvim can be installed in the same virtual machine or container (openvim uses vim_db database name) &lt;br /&gt;
&lt;br /&gt;
TODO complete where RO uses it&lt;br /&gt;
&lt;br /&gt;
===Installation===&lt;br /&gt;
The OSM binary installation install this package. In case of needed you can install/update it manually by:&lt;br /&gt;
&lt;br /&gt;
  apt-get update&lt;br /&gt;
  apt-get install make git python tox libmysqlclient-dev&lt;br /&gt;
  git clone https://osm.etsi.org/gerrit/osm/openvim&lt;br /&gt;
  git -C openvim checkout 005a9dc  # this is temporal, because last version contains error at Makefile&lt;br /&gt;
  make -C openvim lite&lt;br /&gt;
  # Use this line to check if it is installed and where  &lt;br /&gt;
  python -c &#039;import lib_osm_openvim; print lib_osm_openvim.__path__[0]&#039;&lt;br /&gt;
  # Install database of ovim library&lt;br /&gt;
  OSMLIBOVIM_PATH=`python -c &#039;import lib_osm_openvim; print lib_osm_openvim.__path__[0]&#039;`&lt;br /&gt;
  # -U and -P are the admin database user/password. Normally &amp;quot;-U root&amp;quot; without password &amp;quot;executed as root&amp;quot;&lt;br /&gt;
  ${OSMLIBOVIM_PATH}/database_utils/install-db-server.sh -U root [-P passwd] -u mano -p manopw -d mano_vim_db --updatedb&lt;br /&gt;
&lt;br /&gt;
==CLI client==&lt;br /&gt;
&lt;br /&gt;
The RO code contains a python CLI (openmano) that allows friently command execution. This CLI client can run on a separate machine where openmano server is running. &amp;quot;openmano config&amp;quot; indicates where the server is (by default localhost)&lt;br /&gt;
&lt;br /&gt;
==Northbound Interface==&lt;br /&gt;
&lt;br /&gt;
The RO uses a REST API with YAML/JSON content. The primitives are explained [[RO Northbound Interface|here]]&lt;br /&gt;
&lt;br /&gt;
==Running Unit Tests==&lt;br /&gt;
&lt;br /&gt;
===Launching RO===&lt;br /&gt;
Openmano can run as systemd service. (Can be installed with &#039;&#039;&#039;./scripts/install-openmano-service.sh -f RO&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
Or can be run inside a screen (the prefered method for developpers). The script to easily launch/remove is &#039;&#039;&#039;./scripts/service-openmano.sh&#039;&#039;&#039;. Execute with -h to see options&lt;br /&gt;
&lt;br /&gt;
Note that the general OSM install script, installs openmano inside a container and code run at folder /opt/openmano (instead of $HOME/openmano)&lt;br /&gt;
&lt;br /&gt;
===Tests===&lt;br /&gt;
Many of openmano operations rely on an external VIM. Without external infraestructure it is recomended to use openvim in &amp;quot;test&amp;quot; (fake) mode. Install it in the same machine where openmano is located with [[OpenVIM_installation_(Release_One)#Installation]]&lt;br /&gt;
&lt;br /&gt;
Run &#039;&#039;./test/basictest&#039;&#039; for a initial test. Type -h to see options. For testing using openvim just run &amp;lt;pre&amp;gt; . ./test/basictest.sh --force --screen --init-openvim &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating a new VIM plugin==&lt;br /&gt;
&lt;br /&gt;
Choose a name, eg. XXX&lt;br /&gt;
&lt;br /&gt;
Create a new python module vimconn_XXX.py derived from vimconn.py class. Implement the relevant functions. You have several connectors already created to be used as example as openstack and openvim. Openstack connector uses the python openstack client libraries, meanwhile openvim connector uses direct http requests.&lt;br /&gt;
&lt;br /&gt;
DO NOT change the method names, parameters or parameter content. Openmano use the same methods for all the VIMs and they cannot be changed to accomodate VIM specifics. VIM specifics must be solved inside the connector.&lt;br /&gt;
&lt;br /&gt;
The new module can need specific configuration for the VIM that it is passed as a dictionary in the &#039;&#039;config&#039;&#039; variable at constructor. For example, in the case of openstack, &#039;&#039;config&#039;&#039; variable is used for: enabling/disabling port_security_enable, specifying the name of the physical network used for dataplane, regions, etc. The &#039;&#039;config&#039;&#039; variable is the right place to specify those needed parameters not provided by openmano at the methods that form part of the VIM configuration. See [[Openstack configuration (Release TWO)#Add openstack toOSM]] and [[Configuring AWS for OSM Release TWO#Add AWS to OSM]] for examples &lt;br /&gt;
&lt;br /&gt;
Integration with the main project is automatic, just create a new datacenter of type XXX and this module will be automatically loaded. No other module of the main program need to be updated.&lt;br /&gt;
&lt;br /&gt;
    openmano tenant-create osm  # if not already done&lt;br /&gt;
    export OPENMANO_TENANT=osm&lt;br /&gt;
    openmano datacenter-create &amp;lt;vim-name&amp;gt; &amp;lt;access-URL&amp;gt;  --type=XXX --config &amp;lt;specific config&amp;gt;&lt;br /&gt;
    # if fails the cause can be a librery you need not installed or an error upon importing. Try tho import it in a python client&lt;br /&gt;
    # example of &amp;lt;specific config&amp;gt; text: &amp;quot;{dataplane_physical_net: physnet_sriov, port_security_enabled: False}&amp;quot;&lt;br /&gt;
    openmano datacenter-attach &amp;lt;vim-name&amp;gt; --vim-tenant-name=&amp;lt;tenant-to-use-by-openmano&amp;gt; --user=&amp;lt;tenant-user&amp;gt; --password=&amp;lt;tenant-password&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can test it using the &#039;&#039;&#039;test/test_RO.py&#039;&#039;&#039; file:&lt;br /&gt;
    # Create manually an image &amp;lt;image&amp;gt; and a management network &amp;lt;net-mgmt&amp;gt; at your VIM&lt;br /&gt;
    ./test/test_RO.py deploy --help&lt;br /&gt;
    # e.g. ./test/test_RO.py deploy -n &amp;lt;net-mgmt&amp;gt; -t osm -i &amp;lt;image&amp;gt; -d &amp;lt;vim-name&amp;gt; --timeout=30 --test simple_linux,simple_multi_vnfc,simple_2_vnf&lt;br /&gt;
    ./test/test_RO.py vimconn --help&lt;/div&gt;</summary>
		<author><name>Cardosoi</name></author>
	</entry>
	<entry>
		<id>https://osm.etsi.org/wikipub/index.php?title=Developer_HowTo_for_RO_Module&amp;diff=1837</id>
		<title>Developer HowTo for RO Module</title>
		<link rel="alternate" type="text/html" href="https://osm.etsi.org/wikipub/index.php?title=Developer_HowTo_for_RO_Module&amp;diff=1837"/>
		<updated>2017-10-23T13:00:35Z</updated>

		<summary type="html">&lt;p&gt;Cardosoi: /* RO Server modules */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Getting Started==&lt;br /&gt;
The RO Module is implemented by openmano. The recommended Linux distribution for development is Ubuntu 16.04 LTS Server. PyCharm is a nice and easy to use tool for development and debugging.&lt;br /&gt;
&lt;br /&gt;
The step [[Release_1_Installation]] installs all OSM modules in containers. However, for development, a virtual machine may be more suitable. To install the openmano module you can run a script that installs the required packages, clone the project from &#039;&#039;git clones https://osm.etsi.org/gerrit/osm/RO&#039;&#039; and configures openmano client and other utility scripts at path&lt;br /&gt;
 wget -O install-openmano.sh &amp;quot;https://osm.etsi.org/gitweb/?p=osm/RO.git;a=blob_plain;f=scripts/install-openmano.sh&amp;quot;&lt;br /&gt;
 chmod +x install-openmano.sh&lt;br /&gt;
 sudo ./install-openmano.sh -q --develop   #-h for help&lt;br /&gt;
&lt;br /&gt;
See also and follow [[Workflow_with_OSM_tools#Clone_your_project]]&lt;br /&gt;
&lt;br /&gt;
New code features must be incorporated to master:&lt;br /&gt;
 git checkout master&lt;br /&gt;
Generate a &amp;quot;.gitignore&amp;quot;, you can use the &#039;&#039;.gitignore-common&#039;&#039; example that skips PyCharm and Eclipse files&lt;br /&gt;
 cp RO/.gitignore-common RO/.gitignore&lt;br /&gt;
 #edit to include your local files to ignore&lt;br /&gt;
Prepare your git environment to push with a proper user/email, push to gerrit. See and configure:&lt;br /&gt;
&amp;lt;p&amp;gt;[[Workflow_with_OSM_tools#Configure_your_Git_environment]]&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;[[Workflow_with_OSM_tools#Commit_changes_to_your_local_project]]&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;[[ Workflow_with_OSM_tools#Push_your_contribution_to_Gerrit]]&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programming Language==&lt;br /&gt;
The RO module uses Python2. However Python3 conventions for a possible future migration should be used as far as possible. For example:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! BAD Python2&lt;br /&gt;
! OK  Python2 compatible with python3&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;format test string %s number %d&amp;quot; % (st, num)&lt;br /&gt;
| &amp;quot;format test string {} number {}&amp;quot;.format(st, num)&lt;br /&gt;
|-&lt;br /&gt;
| print a, b, c&lt;br /&gt;
| print(a,b,c)&lt;br /&gt;
|-&lt;br /&gt;
| except Exception, e&lt;br /&gt;
| except Exception as e&lt;br /&gt;
|-&lt;br /&gt;
| if type(x) == X:&lt;br /&gt;
| if isinstance(x,X):&lt;br /&gt;
|}&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Descriptors can be YAML (prefered because more readable and allow comments) or JSON&lt;br /&gt;
&lt;br /&gt;
==Code Style==&lt;br /&gt;
Please follow PEP8 style guide for all the Python code.&lt;br /&gt;
&lt;br /&gt;
===Logging===&lt;br /&gt;
Use the appropriate logging levels when logging the messages. An example is shown below:&lt;br /&gt;
    self.logger.debug(&amp;quot;Changing state to %s&amp;quot;, next_state)&lt;br /&gt;
&lt;br /&gt;
Logging levels (general and per module) are specified at &#039;&#039;&#039;openmanod.cfg&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Try to use few useful logs, not verbose, that brings useful information. For example, in case of fail getting a server, the complete URL should be provided.&lt;br /&gt;
&lt;br /&gt;
Avoid several logs together&lt;br /&gt;
&lt;br /&gt;
  WRONG:&lt;br /&gt;
  self.looger.debug(&amp;quot;Entering in method A&amp;quot;)&lt;br /&gt;
  self.logger.debug(&amp;quot;Contacting server&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  RIGHT:&lt;br /&gt;
  self.logger.debug(&amp;quot;method A, contacting server %s&amp;quot;, url)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the traceback is needed(call stack that generate the exception) , use the &amp;quot;exc_info=True&amp;quot; parameter&lt;br /&gt;
  self.logger.error(&amp;quot;Exception %s when ...&amp;quot;, exception, exc_info=True)&lt;br /&gt;
&lt;br /&gt;
===Exceptions===&lt;br /&gt;
Code must be wrote in a way that functions and methods raise an exception when something goes wrong, instead of returning a negative or false value.&lt;br /&gt;
&lt;br /&gt;
Example&lt;br /&gt;
  WRONG&lt;br /&gt;
    def get_ip_address():&lt;br /&gt;
        ...&lt;br /&gt;
        if fail:&lt;br /&gt;
            return False, &amp;quot;Fail because xxx&amp;quot;&lt;br /&gt;
        return True, ip&lt;br /&gt;
    &lt;br /&gt;
    ...&lt;br /&gt;
    result, ip = get_ip_address()&lt;br /&gt;
    if not result:&lt;br /&gt;
        return False, &amp;quot;Cannot get ip address...&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  RIGHT&lt;br /&gt;
    def get_ip_address():&lt;br /&gt;
        ...&lt;br /&gt;
        if fail:&lt;br /&gt;
            raise customException(&amp;quot;Fail because ...&amp;quot;)&lt;br /&gt;
        return ip&lt;br /&gt;
    &lt;br /&gt;
    ...&lt;br /&gt;
    try:&lt;br /&gt;
        ip = get_ip_address()&lt;br /&gt;
        ...&lt;br /&gt;
    except customException as e:&lt;br /&gt;
        raise customException2(str(e))&lt;br /&gt;
&lt;br /&gt;
==Directory Organization==&lt;br /&gt;
The code organized into the following high level directories: &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/&#039;&#039;&#039; contains the entry server file &#039;&#039;openmanod&#039;&#039; and client &#039;&#039;openmano&#039;&#039; code &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/osm_ro&#039;&#039;&#039; contains the RO server code files &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/test&#039;&#039;&#039; contains scripts and code for testing &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/database_utils&#039;&#039;&#039; contains scripts for database creation, dumping and migration &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/scripts&#039;&#039;&#039; general scripts, as installation, execution, reporting &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/scenarios&#039;&#039;&#039; examples and templates of network scnario descriptors &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/vnfs&#039;&#039;&#039; examples and templates of VNF descriptors &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==RO Architecture==&lt;br /&gt;
[[File:OpenmanoArchitecture.png|400px]]&lt;br /&gt;
&lt;br /&gt;
===RO Server modules===&lt;br /&gt;
The RO module contains the following modules&lt;br /&gt;
* &#039;&#039;&#039;openmanod&#039;&#039;&#039; is the main program. It reads the configuration file (openmanod.cfg) and execute the httpserver and wait for the end&lt;br /&gt;
* &#039;&#039;&#039;httpserver.py&#039;&#039;&#039; is a thread that implements the northbound API interface, uses python bottle module. Calls main engine methods to perform the tasks&lt;br /&gt;
* &#039;&#039;&#039;nfvo.py&#039;&#039;&#039; is the main engine, implementing all the methods for the creation, deletion and management of vnfs, scenarios and instances. Operations against a VIM are asynchornous. ACTIONs to be done are stored at database before returning ok to the client&lt;br /&gt;
* &#039;&#039;&#039;nfvo_db.py&#039;&#039;&#039; is the module in charge of database operations. Uses base &#039;&#039;&#039;db_base.py&#039;&#039;&#039;. Database is managed with MySQLdb python library&lt;br /&gt;
* &#039;&#039;&#039;openmano_schemas.py&#039;&#039;&#039; is a dictionary schemas used to validate API request and response content using jsonschema library&lt;br /&gt;
* &#039;&#039;&#039;vim_thread.py&#039;&#039;&#039; There is a thread per VIM and credentials. It performs basic tasks of creating/deleting VM, networks, flavors, etc. In addition it refreshes the VM and network status. It calls vimconn.py methods &lt;br /&gt;
* &#039;&#039;&#039;vimconn.py&#039;&#039;&#039; is the base class for the VIM plugin. It contains the definition of the methods to be implemented. The inherited &#039;&#039;&#039;vimconn_openstack.py&#039;&#039;&#039;, &#039;&#039;&#039;vimconn_openvim.py&#039;&#039;&#039;, &#039;&#039;&#039;vimconn_vmware&#039;&#039;&#039; and &#039;&#039;&#039;vimconn_aws&#039;&#039;&#039; implements the operations against the concrete VIM type. OpenStack plugin uses the python-*client libraries, meanwhile Openvim plugin uses direct http requests.&lt;br /&gt;
* &#039;&#039;&#039;console_proxy_thread.py&#039;&#039;&#039; is a thread that implements a TCP/IP proxy for the console access to a VIM&lt;br /&gt;
&lt;br /&gt;
===RO Client modules===&lt;br /&gt;
Other modules not part of the server are:&lt;br /&gt;
* &#039;&#039;&#039;openmnao&#039;&#039;&#039; is a CLI client&lt;br /&gt;
* &#039;&#039;&#039;openmanoclient.py&#039;&#039;&#039; is a client python library for managing openmano server&lt;br /&gt;
&lt;br /&gt;
===ACTIONS and TASKS===&lt;br /&gt;
ACTIONS are a a group of tasks performed against a a concrete instance-scenarios (NS record). The creation and deletion of the instance-scenario itself is an action. As it is asynchonous, NBI returns an &amp;quot;Action_id&amp;quot; that can be used to check the status. For each action, nfvo.py generates individual tasks for the related VIMs. Tasks are both stored at database and sent to the related vim_thread.py. A task has a concrete relation with a VIM, e.g. create/delete a VM, a network, ... look for a flavor, network, ...&lt;br /&gt;
&lt;br /&gt;
===Database content===&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
==Database changes==&lt;br /&gt;
Database schema can be changed if needed. It is recomended to use a graphical tool (e.g. Heidy) to change database and change it back and copy the SQL commands. Make this steps:&lt;br /&gt;
&lt;br /&gt;
1. openmanod: increment __version__, version_date and database_version&lt;br /&gt;
2. database_utils/migrate_mano_db.sh. See the three &amp;quot;TODO&amp;quot;&lt;br /&gt;
2a. Increment LAST_DB_VERSION&lt;br /&gt;
2b. Annotate a comment to have a track of versions: [ $OPENMANO_VER_NUM -ge 50XX ] &amp;amp;&amp;amp; DB_VERSION=XX  #0.5.XX =&amp;gt;  XX&lt;br /&gt;
3c. Generate new methods function upgrade_to_XX() and function downgrade_from_XX. Insert here the sql commands. Last sql command over schema_version is quite important to detect the database version.&lt;br /&gt;
&lt;br /&gt;
Test several upgrades/downgrades to version 20 with &amp;quot;migrate_mano_db.sh&amp;quot; and &amp;quot;migrate_mano_db.sh 20&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Package dependency osm-im==&lt;br /&gt;
It is under IM repository. It contains the OSM models. Used models at RO are under &amp;lt;IM&amp;gt;/models/yang/vnfd.yang and &amp;lt;IM&amp;gt;/models/yang/nsd.yang. More modules will be incorporated in the future.&lt;br /&gt;
&lt;br /&gt;
When IM is maked, pyangbind generates python source files imported at RO. They are used to validate and load a yaml/json VNFD and NSD catalog descriptor.&lt;br /&gt;
&lt;br /&gt;
Method pybindJSONDecoder.load_ietf_json from pyangbind is used to parse and load the descriptor. A structure of nested YANG classes are generated and used at &amp;lt;RO&amp;gt;/osm_ro/nfvo.py methods new_vnfd_v3 and new_nsd_v3. RO supports backward compatibility with old format descriptors. NBI (osm_ro/httpserver.py) uses .../v3/... at URL to diferenciate between old and new descriptors. CLI (openmano) detects automatically if the descriptor is in old format or in OSM format to send the request to the server using the old URL or the new &amp;quot;v3&amp;quot; URL&lt;br /&gt;
&lt;br /&gt;
===Installation===&lt;br /&gt;
The OSM binary installation install this package. In case of needed you can install/update it manually by:&lt;br /&gt;
&lt;br /&gt;
  apt-get update&lt;br /&gt;
  apt-get install make git python python-pip tox debhelper python-bitarray python-lxml&lt;br /&gt;
  pip install --upgrade pip&lt;br /&gt;
  # If not inside a container. Use &amp;quot;sudo -HE&amp;quot; to get root privileges for pip installation&lt;br /&gt;
  pip install pyangbind stdeb&lt;br /&gt;
  git clone https://osm.etsi.org/gerrit/osm/IM&lt;br /&gt;
  make -C IM clean all&lt;br /&gt;
  dpkg -i IM/deb_dist/python-pyang_*.deb&lt;br /&gt;
  dpkg -i IM/deb_dist/python-pyangbind_*.deb&lt;br /&gt;
  dpkg -i IM/deb_dist/python-osm-im_*.deb&lt;br /&gt;
  # Use this line to check if it is installed and where  &lt;br /&gt;
  python -c &#039;import osm_im; print osm_im.__path__[0]&#039;&lt;br /&gt;
&lt;br /&gt;
==Package dependency lib-osm-openvim==&lt;br /&gt;
&lt;br /&gt;
It is under openvim repository. RO uses a library for the SDN assist that is in charge of performing the underlay dataplane connectivity using an openflow controller. osm-openvim and lib-osm-openvim are diffent, though they share same pieces of code. lib-osm-openvim uses a different database name (mano_vim_db) so that openvim can be installed in the same virtual machine or container (openvim uses vim_db database name) &lt;br /&gt;
&lt;br /&gt;
TODO complete where RO uses it&lt;br /&gt;
&lt;br /&gt;
===Installation===&lt;br /&gt;
The OSM binary installation install this package. In case of needed you can install/update it manually by:&lt;br /&gt;
&lt;br /&gt;
  apt-get update&lt;br /&gt;
  apt-get install make git python tox libmysqlclient-dev&lt;br /&gt;
  git clone https://osm.etsi.org/gerrit/osm/openvim&lt;br /&gt;
  git -C openvim checkout 005a9dc  # this is temporal, because last version contains error at Makefile&lt;br /&gt;
  make -C openvim lite&lt;br /&gt;
  # Use this line to check if it is installed and where  &lt;br /&gt;
  python -c &#039;import lib_osm_openvim; print lib_osm_openvim.__path__[0]&#039;&lt;br /&gt;
  # Install database of ovim library&lt;br /&gt;
  OSMLIBOVIM_PATH=`python -c &#039;import lib_osm_openvim; print lib_osm_openvim.__path__[0]&#039;`&lt;br /&gt;
  # -U and -P are the admin database user/password. Normally &amp;quot;-U root&amp;quot; without password &amp;quot;executed as root&amp;quot;&lt;br /&gt;
  ${OSMLIBOVIM_PATH}/database_utils/install-db-server.sh -U root [-P passwd] -u mano -p manopw -d mano_vim_db --updatedb&lt;br /&gt;
&lt;br /&gt;
==CLI client==&lt;br /&gt;
&lt;br /&gt;
The RO code contains a python CLI (openmano) that allows friently command execution. This CLI client can run on a separate machine where openmano server is running. &amp;quot;openmano config&amp;quot; indicates where the server is (by default localhost)&lt;br /&gt;
&lt;br /&gt;
==Northbound Interface==&lt;br /&gt;
&lt;br /&gt;
The RO uses a REST API with YAML/JSON content. The primitives are explained [[RO Northbound Interface|here]]&lt;br /&gt;
&lt;br /&gt;
==Running Unit Tests==&lt;br /&gt;
&lt;br /&gt;
===Launching RO===&lt;br /&gt;
Openmano can run as systemd service. (Can be installed with &#039;&#039;&#039;./scripts/install-openmano-service.sh -f RO&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
Or can be run inside a screen (the prefered method for developpers). The script to easily launch/remove is &#039;&#039;&#039;./scripts/service-openmano.sh&#039;&#039;&#039;. Execute with -h to see options&lt;br /&gt;
&lt;br /&gt;
Note that the general OSM install script, installs openmano inside a container and code run at folder /opt/openmano (instead of $HOME/openmano)&lt;br /&gt;
&lt;br /&gt;
===Tests===&lt;br /&gt;
Many of openmano operations rely on an external VIM. Without external infraestructure it is recomended to use openvim in &amp;quot;test&amp;quot; (fake) mode. Install it in the same machine where openmano is located with [[OpenVIM_installation_(Release_One)#Installation]]&lt;br /&gt;
&lt;br /&gt;
Run &#039;&#039;./test/basictest&#039;&#039; for a initial test. Type -h to see options. For testing using openvim just run &amp;lt;pre&amp;gt; . ./test/basictest.sh --force --screen --init-openvim &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating a new VIM plugin==&lt;br /&gt;
&lt;br /&gt;
Choose a name, eg. XXX&lt;br /&gt;
&lt;br /&gt;
Create a new python module vimconn_XXX.py derived from vimconn.py class. Implement the relevant functions. You have several connectors already created to be used as example as openstack and openvim. Openstack connector uses the python openstack client libraries, meanwhile openvim connector uses direct http requests.&lt;br /&gt;
&lt;br /&gt;
DO NOT change the method names, parameters or parameter content. Openmano use the same methods for all the VIMs and they cannot be changed to accomodate VIM specifics. VIM specifics must be solved inside the connector.&lt;br /&gt;
&lt;br /&gt;
The new module can need specific configuration for the VIM that it is passed as a dictionary in the &#039;&#039;config&#039;&#039; variable at constructor. For example, in the case of openstack, &#039;&#039;config&#039;&#039; variable is used for: enabling/disabling port_security_enable, specifying the name of the physical network used for dataplane, regions, etc. The &#039;&#039;config&#039;&#039; variable is the right place to specify those needed parameters not provided by openmano at the methods that form part of the VIM configuration. See [[Openstack configuration (Release TWO)#Add openstack toOSM]] and [[Configuring AWS for OSM Release TWO#Add AWS to OSM]] for examples &lt;br /&gt;
&lt;br /&gt;
Integration with the main project is automatic, just create a new datacenter of type XXX and this module will be automatically loaded. No other module of the main program need to be updated.&lt;br /&gt;
&lt;br /&gt;
    openmano tenant-create osm  # if not already done&lt;br /&gt;
    export OPENMANO_TENANT=osm&lt;br /&gt;
    openmano datacenter-create &amp;lt;vim-name&amp;gt; &amp;lt;access-URL&amp;gt;  --type=XXX --config &amp;lt;specific config&amp;gt;&lt;br /&gt;
    # if fails the cause can be a librery you need not installed or an error upon importing. Try tho import it in a python client&lt;br /&gt;
    # example of &amp;lt;specific config&amp;gt; text: &amp;quot;{dataplane_physical_net: physnet_sriov, port_security_enabled: False}&amp;quot;&lt;br /&gt;
    openmano datacenter-attach &amp;lt;vim-name&amp;gt; --vim-tenant-name=&amp;lt;tenant-to-use-by-openmano&amp;gt; --user=&amp;lt;tenant-user&amp;gt; --password=&amp;lt;tenant-password&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can test it using the &#039;&#039;&#039;test/test_RO.py&#039;&#039;&#039; file:&lt;br /&gt;
    # Create manually an image &amp;lt;image&amp;gt; and a management network &amp;lt;net-mgmt&amp;gt; at your VIM&lt;br /&gt;
    ./test/test_RO.py deploy --help&lt;br /&gt;
    # e.g. ./test/test_RO.py deploy -n &amp;lt;net-mgmt&amp;gt; -t osm -i &amp;lt;image&amp;gt; -d &amp;lt;vim-name&amp;gt; --timeout=30 --test simple_linux,simple_multi_vnfc,simple_2_vnf&lt;br /&gt;
    ./test/test_RO.py vimconn --help&lt;/div&gt;</summary>
		<author><name>Cardosoi</name></author>
	</entry>
	<entry>
		<id>https://osm.etsi.org/wikipub/index.php?title=Developer_HowTo_for_RO_Module&amp;diff=1836</id>
		<title>Developer HowTo for RO Module</title>
		<link rel="alternate" type="text/html" href="https://osm.etsi.org/wikipub/index.php?title=Developer_HowTo_for_RO_Module&amp;diff=1836"/>
		<updated>2017-10-23T10:07:39Z</updated>

		<summary type="html">&lt;p&gt;Cardosoi: /* Installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Getting Started==&lt;br /&gt;
The RO Module is implemented by openmano. The recommended Linux distribution for development is Ubuntu 16.04 LTS Server. PyCharm is a nice and easy to use tool for development and debugging.&lt;br /&gt;
&lt;br /&gt;
The step [[Release_1_Installation]] installs all OSM modules in containers. However, for development, a virtual machine may be more suitable. To install the openmano module you can run a script that installs the required packages, clone the project from &#039;&#039;git clones https://osm.etsi.org/gerrit/osm/RO&#039;&#039; and configures openmano client and other utility scripts at path&lt;br /&gt;
 wget -O install-openmano.sh &amp;quot;https://osm.etsi.org/gitweb/?p=osm/RO.git;a=blob_plain;f=scripts/install-openmano.sh&amp;quot;&lt;br /&gt;
 chmod +x install-openmano.sh&lt;br /&gt;
 sudo ./install-openmano.sh -q --develop   #-h for help&lt;br /&gt;
&lt;br /&gt;
See also and follow [[Workflow_with_OSM_tools#Clone_your_project]]&lt;br /&gt;
&lt;br /&gt;
New code features must be incorporated to master:&lt;br /&gt;
 git checkout master&lt;br /&gt;
Generate a &amp;quot;.gitignore&amp;quot;, you can use the &#039;&#039;.gitignore-common&#039;&#039; example that skips PyCharm and Eclipse files&lt;br /&gt;
 cp RO/.gitignore-common RO/.gitignore&lt;br /&gt;
 #edit to include your local files to ignore&lt;br /&gt;
Prepare your git environment to push with a proper user/email, push to gerrit. See and configure:&lt;br /&gt;
&amp;lt;p&amp;gt;[[Workflow_with_OSM_tools#Configure_your_Git_environment]]&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;[[Workflow_with_OSM_tools#Commit_changes_to_your_local_project]]&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;[[ Workflow_with_OSM_tools#Push_your_contribution_to_Gerrit]]&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programming Language==&lt;br /&gt;
The RO module uses Python2. However Python3 conventions for a possible future migration should be used as far as possible. For example:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! BAD Python2&lt;br /&gt;
! OK  Python2 compatible with python3&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;format test string %s number %d&amp;quot; % (st, num)&lt;br /&gt;
| &amp;quot;format test string {} number {}&amp;quot;.format(st, num)&lt;br /&gt;
|-&lt;br /&gt;
| print a, b, c&lt;br /&gt;
| print(a,b,c)&lt;br /&gt;
|-&lt;br /&gt;
| except Exception, e&lt;br /&gt;
| except Exception as e&lt;br /&gt;
|-&lt;br /&gt;
| if type(x) == X:&lt;br /&gt;
| if isinstance(x,X):&lt;br /&gt;
|}&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Descriptors can be YAML (prefered because more readable and allow comments) or JSON&lt;br /&gt;
&lt;br /&gt;
==Code Style==&lt;br /&gt;
Please follow PEP8 style guide for all the Python code.&lt;br /&gt;
&lt;br /&gt;
===Logging===&lt;br /&gt;
Use the appropriate logging levels when logging the messages. An example is shown below:&lt;br /&gt;
    self.logger.debug(&amp;quot;Changing state to %s&amp;quot;, next_state)&lt;br /&gt;
&lt;br /&gt;
Logging levels (general and per module) are specified at &#039;&#039;&#039;openmanod.cfg&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Try to use few useful logs, not verbose, that brings useful information. For example, in case of fail getting a server, the complete URL should be provided.&lt;br /&gt;
&lt;br /&gt;
Avoid several logs together&lt;br /&gt;
&lt;br /&gt;
  WRONG:&lt;br /&gt;
  self.looger.debug(&amp;quot;Entering in method A&amp;quot;)&lt;br /&gt;
  self.logger.debug(&amp;quot;Contacting server&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  RIGHT:&lt;br /&gt;
  self.logger.debug(&amp;quot;method A, contacting server %s&amp;quot;, url)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the traceback is needed(call stack that generate the exception) , use the &amp;quot;exc_info=True&amp;quot; parameter&lt;br /&gt;
  self.logger.error(&amp;quot;Exception %s when ...&amp;quot;, exception, exc_info=True)&lt;br /&gt;
&lt;br /&gt;
===Exceptions===&lt;br /&gt;
Code must be wrote in a way that functions and methods raise an exception when something goes wrong, instead of returning a negative or false value.&lt;br /&gt;
&lt;br /&gt;
Example&lt;br /&gt;
  WRONG&lt;br /&gt;
    def get_ip_address():&lt;br /&gt;
        ...&lt;br /&gt;
        if fail:&lt;br /&gt;
            return False, &amp;quot;Fail because xxx&amp;quot;&lt;br /&gt;
        return True, ip&lt;br /&gt;
    &lt;br /&gt;
    ...&lt;br /&gt;
    result, ip = get_ip_address()&lt;br /&gt;
    if not result:&lt;br /&gt;
        return False, &amp;quot;Cannot get ip address...&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  RIGHT&lt;br /&gt;
    def get_ip_address():&lt;br /&gt;
        ...&lt;br /&gt;
        if fail:&lt;br /&gt;
            raise customException(&amp;quot;Fail because ...&amp;quot;)&lt;br /&gt;
        return ip&lt;br /&gt;
    &lt;br /&gt;
    ...&lt;br /&gt;
    try:&lt;br /&gt;
        ip = get_ip_address()&lt;br /&gt;
        ...&lt;br /&gt;
    except customException as e:&lt;br /&gt;
        raise customException2(str(e))&lt;br /&gt;
&lt;br /&gt;
==Directory Organization==&lt;br /&gt;
The code organized into the following high level directories: &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/&#039;&#039;&#039; contains the entry server file &#039;&#039;openmanod&#039;&#039; and client &#039;&#039;openmano&#039;&#039; code &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/osm_ro&#039;&#039;&#039; contains the RO server code files &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/test&#039;&#039;&#039; contains scripts and code for testing &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/database_utils&#039;&#039;&#039; contains scripts for database creation, dumping and migration &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/scripts&#039;&#039;&#039; general scripts, as installation, execution, reporting &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/scenarios&#039;&#039;&#039; examples and templates of network scnario descriptors &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/vnfs&#039;&#039;&#039; examples and templates of VNF descriptors &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==RO Architecture==&lt;br /&gt;
[[File:OpenmanoArchitecture.png|400px]]&lt;br /&gt;
&lt;br /&gt;
===RO Server modules===&lt;br /&gt;
The RO module contains the following modules&lt;br /&gt;
* &#039;&#039;&#039;openmanod&#039;&#039;&#039; is the main program. It reads the configuration file (openmanod.cfg) and execute the httpserver and wait for the end&lt;br /&gt;
* &#039;&#039;&#039;httpserver.py&#039;&#039;&#039; is a thread that implements the northbound API interface, uses python bottle module. Calls main engine methods to perform the tasks&lt;br /&gt;
* &#039;&#039;&#039;nfvo.py&#039;&#039;&#039; is the main engine, implementing all the methods for the creation, deletion and management of vnfs, scenarios and instances. Operations against a VIM are asynchornous. ACTIONs to be done are stored at database before returning ok to the client&lt;br /&gt;
* &#039;&#039;&#039;nfvo_db.py&#039;&#039;&#039; is the module in charge of database operations. Uses base &#039;&#039;&#039;db_base.py&#039;&#039;&#039;. Database is managed with MySQLdb python library&lt;br /&gt;
* &#039;&#039;&#039;openmano_schemas.py&#039;&#039;&#039; is a dictionary schemas used to validate API request and response content using jsonschema library&lt;br /&gt;
* &#039;&#039;&#039;vim_thread.py&#039;&#039;&#039; There is a thread per VIM and credentials. It performs basic tasks of creating/deleting VM, networks, flavors, etc. In addition it refreshes the VM and network status. It calls vimconn.py methods &lt;br /&gt;
* &#039;&#039;&#039;vimconn.py&#039;&#039;&#039; is the base class for the VIM plugin. It contains the definition of the methods to be implemented. The inherited &#039;&#039;&#039;vimconn_openstack.py&#039;&#039;&#039;, &#039;&#039;&#039;vimconn_openvim.py&#039;&#039;&#039;, &#039;&#039;&#039;vimconn_vmware&#039;&#039;&#039; and &#039;&#039;&#039;vimconn_aws&#039;&#039;&#039; implements the operations against the concrete VIM type. Openstack plugin uses the client-python libraris, meanwhile Openvim plugin uses direct http requests.&lt;br /&gt;
* &#039;&#039;&#039;console_proxy_thread.py&#039;&#039;&#039; is a thread that implements a TCP/IP proxy for the console access to a VIM&lt;br /&gt;
&lt;br /&gt;
===RO Client modules===&lt;br /&gt;
Other modules not part of the server are:&lt;br /&gt;
* &#039;&#039;&#039;openmnao&#039;&#039;&#039; is a CLI client&lt;br /&gt;
* &#039;&#039;&#039;openmanoclient.py&#039;&#039;&#039; is a client python library for managing openmano server&lt;br /&gt;
&lt;br /&gt;
===ACTIONS and TASKS===&lt;br /&gt;
ACTIONS are a a group of tasks performed against a a concrete instance-scenarios (NS record). The creation and deletion of the instance-scenario itself is an action. As it is asynchonous, NBI returns an &amp;quot;Action_id&amp;quot; that can be used to check the status. For each action, nfvo.py generates individual tasks for the related VIMs. Tasks are both stored at database and sent to the related vim_thread.py. A task has a concrete relation with a VIM, e.g. create/delete a VM, a network, ... look for a flavor, network, ...&lt;br /&gt;
&lt;br /&gt;
===Database content===&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
==Database changes==&lt;br /&gt;
Database schema can be changed if needed. It is recomended to use a graphical tool (e.g. Heidy) to change database and change it back and copy the SQL commands. Make this steps:&lt;br /&gt;
&lt;br /&gt;
1. openmanod: increment __version__, version_date and database_version&lt;br /&gt;
2. database_utils/migrate_mano_db.sh. See the three &amp;quot;TODO&amp;quot;&lt;br /&gt;
2a. Increment LAST_DB_VERSION&lt;br /&gt;
2b. Annotate a comment to have a track of versions: [ $OPENMANO_VER_NUM -ge 50XX ] &amp;amp;&amp;amp; DB_VERSION=XX  #0.5.XX =&amp;gt;  XX&lt;br /&gt;
3c. Generate new methods function upgrade_to_XX() and function downgrade_from_XX. Insert here the sql commands. Last sql command over schema_version is quite important to detect the database version.&lt;br /&gt;
&lt;br /&gt;
Test several upgrades/downgrades to version 20 with &amp;quot;migrate_mano_db.sh&amp;quot; and &amp;quot;migrate_mano_db.sh 20&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Package dependency osm-im==&lt;br /&gt;
It is under IM repository. It contains the OSM models. Used models at RO are under &amp;lt;IM&amp;gt;/models/yang/vnfd.yang and &amp;lt;IM&amp;gt;/models/yang/nsd.yang. More modules will be incorporated in the future.&lt;br /&gt;
&lt;br /&gt;
When IM is maked, pyangbind generates python source files imported at RO. They are used to validate and load a yaml/json VNFD and NSD catalog descriptor.&lt;br /&gt;
&lt;br /&gt;
Method pybindJSONDecoder.load_ietf_json from pyangbind is used to parse and load the descriptor. A structure of nested YANG classes are generated and used at &amp;lt;RO&amp;gt;/osm_ro/nfvo.py methods new_vnfd_v3 and new_nsd_v3. RO supports backward compatibility with old format descriptors. NBI (osm_ro/httpserver.py) uses .../v3/... at URL to diferenciate between old and new descriptors. CLI (openmano) detects automatically if the descriptor is in old format or in OSM format to send the request to the server using the old URL or the new &amp;quot;v3&amp;quot; URL&lt;br /&gt;
&lt;br /&gt;
===Installation===&lt;br /&gt;
The OSM binary installation install this package. In case of needed you can install/update it manually by:&lt;br /&gt;
&lt;br /&gt;
  apt-get update&lt;br /&gt;
  apt-get install make git python python-pip tox debhelper python-bitarray python-lxml&lt;br /&gt;
  pip install --upgrade pip&lt;br /&gt;
  # If not inside a container. Use &amp;quot;sudo -HE&amp;quot; to get root privileges for pip installation&lt;br /&gt;
  pip install pyangbind stdeb&lt;br /&gt;
  git clone https://osm.etsi.org/gerrit/osm/IM&lt;br /&gt;
  make -C IM clean all&lt;br /&gt;
  dpkg -i IM/deb_dist/python-pyang_*.deb&lt;br /&gt;
  dpkg -i IM/deb_dist/python-pyangbind_*.deb&lt;br /&gt;
  dpkg -i IM/deb_dist/python-osm-im_*.deb&lt;br /&gt;
  # Use this line to check if it is installed and where  &lt;br /&gt;
  python -c &#039;import osm_im; print osm_im.__path__[0]&#039;&lt;br /&gt;
&lt;br /&gt;
==Package dependency lib-osm-openvim==&lt;br /&gt;
&lt;br /&gt;
It is under openvim repository. RO uses a library for the SDN assist that is in charge of performing the underlay dataplane connectivity using an openflow controller. osm-openvim and lib-osm-openvim are diffent, though they share same pieces of code. lib-osm-openvim uses a different database name (mano_vim_db) so that openvim can be installed in the same virtual machine or container (openvim uses vim_db database name) &lt;br /&gt;
&lt;br /&gt;
TODO complete where RO uses it&lt;br /&gt;
&lt;br /&gt;
===Installation===&lt;br /&gt;
The OSM binary installation install this package. In case of needed you can install/update it manually by:&lt;br /&gt;
&lt;br /&gt;
  apt-get update&lt;br /&gt;
  apt-get install make git python tox libmysqlclient-dev&lt;br /&gt;
  git clone https://osm.etsi.org/gerrit/osm/openvim&lt;br /&gt;
  git -C openvim checkout 005a9dc  # this is temporal, because last version contains error at Makefile&lt;br /&gt;
  make -C openvim lite&lt;br /&gt;
  # Use this line to check if it is installed and where  &lt;br /&gt;
  python -c &#039;import lib_osm_openvim; print lib_osm_openvim.__path__[0]&#039;&lt;br /&gt;
  # Install database of ovim library&lt;br /&gt;
  OSMLIBOVIM_PATH=`python -c &#039;import lib_osm_openvim; print lib_osm_openvim.__path__[0]&#039;`&lt;br /&gt;
  # -U and -P are the admin database user/password. Normally &amp;quot;-U root&amp;quot; without password &amp;quot;executed as root&amp;quot;&lt;br /&gt;
  ${OSMLIBOVIM_PATH}/database_utils/install-db-server.sh -U root [-P passwd] -u mano -p manopw -d mano_vim_db --updatedb&lt;br /&gt;
&lt;br /&gt;
==CLI client==&lt;br /&gt;
&lt;br /&gt;
The RO code contains a python CLI (openmano) that allows friently command execution. This CLI client can run on a separate machine where openmano server is running. &amp;quot;openmano config&amp;quot; indicates where the server is (by default localhost)&lt;br /&gt;
&lt;br /&gt;
==Northbound Interface==&lt;br /&gt;
&lt;br /&gt;
The RO uses a REST API with YAML/JSON content. The primitives are explained [[RO Northbound Interface|here]]&lt;br /&gt;
&lt;br /&gt;
==Running Unit Tests==&lt;br /&gt;
&lt;br /&gt;
===Launching RO===&lt;br /&gt;
Openmano can run as systemd service. (Can be installed with &#039;&#039;&#039;./scripts/install-openmano-service.sh -f RO&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
Or can be run inside a screen (the prefered method for developpers). The script to easily launch/remove is &#039;&#039;&#039;./scripts/service-openmano.sh&#039;&#039;&#039;. Execute with -h to see options&lt;br /&gt;
&lt;br /&gt;
Note that the general OSM install script, installs openmano inside a container and code run at folder /opt/openmano (instead of $HOME/openmano)&lt;br /&gt;
&lt;br /&gt;
===Tests===&lt;br /&gt;
Many of openmano operations rely on an external VIM. Without external infraestructure it is recomended to use openvim in &amp;quot;test&amp;quot; (fake) mode. Install it in the same machine where openmano is located with [[OpenVIM_installation_(Release_One)#Installation]]&lt;br /&gt;
&lt;br /&gt;
Run &#039;&#039;./test/basictest&#039;&#039; for a initial test. Type -h to see options. For testing using openvim just run &amp;lt;pre&amp;gt; . ./test/basictest.sh --force --screen --init-openvim &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating a new VIM plugin==&lt;br /&gt;
&lt;br /&gt;
Choose a name, eg. XXX&lt;br /&gt;
&lt;br /&gt;
Create a new python module vimconn_XXX.py derived from vimconn.py class. Implement the relevant functions. You have several connectors already created to be used as example as openstack and openvim. Openstack connector uses the python openstack client libraries, meanwhile openvim connector uses direct http requests.&lt;br /&gt;
&lt;br /&gt;
DO NOT change the method names, parameters or parameter content. Openmano use the same methods for all the VIMs and they cannot be changed to accomodate VIM specifics. VIM specifics must be solved inside the connector.&lt;br /&gt;
&lt;br /&gt;
The new module can need specific configuration for the VIM that it is passed as a dictionary in the &#039;&#039;config&#039;&#039; variable at constructor. For example, in the case of openstack, &#039;&#039;config&#039;&#039; variable is used for: enabling/disabling port_security_enable, specifying the name of the physical network used for dataplane, regions, etc. The &#039;&#039;config&#039;&#039; variable is the right place to specify those needed parameters not provided by openmano at the methods that form part of the VIM configuration. See [[Openstack configuration (Release TWO)#Add openstack toOSM]] and [[Configuring AWS for OSM Release TWO#Add AWS to OSM]] for examples &lt;br /&gt;
&lt;br /&gt;
Integration with the main project is automatic, just create a new datacenter of type XXX and this module will be automatically loaded. No other module of the main program need to be updated.&lt;br /&gt;
&lt;br /&gt;
    openmano tenant-create osm  # if not already done&lt;br /&gt;
    export OPENMANO_TENANT=osm&lt;br /&gt;
    openmano datacenter-create &amp;lt;vim-name&amp;gt; &amp;lt;access-URL&amp;gt;  --type=XXX --config &amp;lt;specific config&amp;gt;&lt;br /&gt;
    # if fails the cause can be a librery you need not installed or an error upon importing. Try tho import it in a python client&lt;br /&gt;
    # example of &amp;lt;specific config&amp;gt; text: &amp;quot;{dataplane_physical_net: physnet_sriov, port_security_enabled: False}&amp;quot;&lt;br /&gt;
    openmano datacenter-attach &amp;lt;vim-name&amp;gt; --vim-tenant-name=&amp;lt;tenant-to-use-by-openmano&amp;gt; --user=&amp;lt;tenant-user&amp;gt; --password=&amp;lt;tenant-password&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can test it using the &#039;&#039;&#039;test/test_RO.py&#039;&#039;&#039; file:&lt;br /&gt;
    # Create manually an image &amp;lt;image&amp;gt; and a management network &amp;lt;net-mgmt&amp;gt; at your VIM&lt;br /&gt;
    ./test/test_RO.py deploy --help&lt;br /&gt;
    # e.g. ./test/test_RO.py deploy -n &amp;lt;net-mgmt&amp;gt; -t osm -i &amp;lt;image&amp;gt; -d &amp;lt;vim-name&amp;gt; --timeout=30 --test simple_linux,simple_multi_vnfc,simple_2_vnf&lt;br /&gt;
    ./test/test_RO.py vimconn --help&lt;/div&gt;</summary>
		<author><name>Cardosoi</name></author>
	</entry>
	<entry>
		<id>https://osm.etsi.org/wikipub/index.php?title=Developer_HowTo_for_RO_Module&amp;diff=1835</id>
		<title>Developer HowTo for RO Module</title>
		<link rel="alternate" type="text/html" href="https://osm.etsi.org/wikipub/index.php?title=Developer_HowTo_for_RO_Module&amp;diff=1835"/>
		<updated>2017-10-23T10:06:54Z</updated>

		<summary type="html">&lt;p&gt;Cardosoi: Correction installation command list (working fine now) /* Installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Getting Started==&lt;br /&gt;
The RO Module is implemented by openmano. The recommended Linux distribution for development is Ubuntu 16.04 LTS Server. PyCharm is a nice and easy to use tool for development and debugging.&lt;br /&gt;
&lt;br /&gt;
The step [[Release_1_Installation]] installs all OSM modules in containers. However, for development, a virtual machine may be more suitable. To install the openmano module you can run a script that installs the required packages, clone the project from &#039;&#039;git clones https://osm.etsi.org/gerrit/osm/RO&#039;&#039; and configures openmano client and other utility scripts at path&lt;br /&gt;
 wget -O install-openmano.sh &amp;quot;https://osm.etsi.org/gitweb/?p=osm/RO.git;a=blob_plain;f=scripts/install-openmano.sh&amp;quot;&lt;br /&gt;
 chmod +x install-openmano.sh&lt;br /&gt;
 sudo ./install-openmano.sh -q --develop   #-h for help&lt;br /&gt;
&lt;br /&gt;
See also and follow [[Workflow_with_OSM_tools#Clone_your_project]]&lt;br /&gt;
&lt;br /&gt;
New code features must be incorporated to master:&lt;br /&gt;
 git checkout master&lt;br /&gt;
Generate a &amp;quot;.gitignore&amp;quot;, you can use the &#039;&#039;.gitignore-common&#039;&#039; example that skips PyCharm and Eclipse files&lt;br /&gt;
 cp RO/.gitignore-common RO/.gitignore&lt;br /&gt;
 #edit to include your local files to ignore&lt;br /&gt;
Prepare your git environment to push with a proper user/email, push to gerrit. See and configure:&lt;br /&gt;
&amp;lt;p&amp;gt;[[Workflow_with_OSM_tools#Configure_your_Git_environment]]&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;[[Workflow_with_OSM_tools#Commit_changes_to_your_local_project]]&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;[[ Workflow_with_OSM_tools#Push_your_contribution_to_Gerrit]]&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programming Language==&lt;br /&gt;
The RO module uses Python2. However Python3 conventions for a possible future migration should be used as far as possible. For example:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! BAD Python2&lt;br /&gt;
! OK  Python2 compatible with python3&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;format test string %s number %d&amp;quot; % (st, num)&lt;br /&gt;
| &amp;quot;format test string {} number {}&amp;quot;.format(st, num)&lt;br /&gt;
|-&lt;br /&gt;
| print a, b, c&lt;br /&gt;
| print(a,b,c)&lt;br /&gt;
|-&lt;br /&gt;
| except Exception, e&lt;br /&gt;
| except Exception as e&lt;br /&gt;
|-&lt;br /&gt;
| if type(x) == X:&lt;br /&gt;
| if isinstance(x,X):&lt;br /&gt;
|}&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Descriptors can be YAML (prefered because more readable and allow comments) or JSON&lt;br /&gt;
&lt;br /&gt;
==Code Style==&lt;br /&gt;
Please follow PEP8 style guide for all the Python code.&lt;br /&gt;
&lt;br /&gt;
===Logging===&lt;br /&gt;
Use the appropriate logging levels when logging the messages. An example is shown below:&lt;br /&gt;
    self.logger.debug(&amp;quot;Changing state to %s&amp;quot;, next_state)&lt;br /&gt;
&lt;br /&gt;
Logging levels (general and per module) are specified at &#039;&#039;&#039;openmanod.cfg&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Try to use few useful logs, not verbose, that brings useful information. For example, in case of fail getting a server, the complete URL should be provided.&lt;br /&gt;
&lt;br /&gt;
Avoid several logs together&lt;br /&gt;
&lt;br /&gt;
  WRONG:&lt;br /&gt;
  self.looger.debug(&amp;quot;Entering in method A&amp;quot;)&lt;br /&gt;
  self.logger.debug(&amp;quot;Contacting server&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  RIGHT:&lt;br /&gt;
  self.logger.debug(&amp;quot;method A, contacting server %s&amp;quot;, url)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the traceback is needed(call stack that generate the exception) , use the &amp;quot;exc_info=True&amp;quot; parameter&lt;br /&gt;
  self.logger.error(&amp;quot;Exception %s when ...&amp;quot;, exception, exc_info=True)&lt;br /&gt;
&lt;br /&gt;
===Exceptions===&lt;br /&gt;
Code must be wrote in a way that functions and methods raise an exception when something goes wrong, instead of returning a negative or false value.&lt;br /&gt;
&lt;br /&gt;
Example&lt;br /&gt;
  WRONG&lt;br /&gt;
    def get_ip_address():&lt;br /&gt;
        ...&lt;br /&gt;
        if fail:&lt;br /&gt;
            return False, &amp;quot;Fail because xxx&amp;quot;&lt;br /&gt;
        return True, ip&lt;br /&gt;
    &lt;br /&gt;
    ...&lt;br /&gt;
    result, ip = get_ip_address()&lt;br /&gt;
    if not result:&lt;br /&gt;
        return False, &amp;quot;Cannot get ip address...&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  RIGHT&lt;br /&gt;
    def get_ip_address():&lt;br /&gt;
        ...&lt;br /&gt;
        if fail:&lt;br /&gt;
            raise customException(&amp;quot;Fail because ...&amp;quot;)&lt;br /&gt;
        return ip&lt;br /&gt;
    &lt;br /&gt;
    ...&lt;br /&gt;
    try:&lt;br /&gt;
        ip = get_ip_address()&lt;br /&gt;
        ...&lt;br /&gt;
    except customException as e:&lt;br /&gt;
        raise customException2(str(e))&lt;br /&gt;
&lt;br /&gt;
==Directory Organization==&lt;br /&gt;
The code organized into the following high level directories: &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/&#039;&#039;&#039; contains the entry server file &#039;&#039;openmanod&#039;&#039; and client &#039;&#039;openmano&#039;&#039; code &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/osm_ro&#039;&#039;&#039; contains the RO server code files &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/test&#039;&#039;&#039; contains scripts and code for testing &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/database_utils&#039;&#039;&#039; contains scripts for database creation, dumping and migration &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/scripts&#039;&#039;&#039; general scripts, as installation, execution, reporting &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/scenarios&#039;&#039;&#039; examples and templates of network scnario descriptors &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/vnfs&#039;&#039;&#039; examples and templates of VNF descriptors &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==RO Architecture==&lt;br /&gt;
[[File:OpenmanoArchitecture.png|400px]]&lt;br /&gt;
&lt;br /&gt;
===RO Server modules===&lt;br /&gt;
The RO module contains the following modules&lt;br /&gt;
* &#039;&#039;&#039;openmanod&#039;&#039;&#039; is the main program. It reads the configuration file (openmanod.cfg) and execute the httpserver and wait for the end&lt;br /&gt;
* &#039;&#039;&#039;httpserver.py&#039;&#039;&#039; is a thread that implements the northbound API interface, uses python bottle module. Calls main engine methods to perform the tasks&lt;br /&gt;
* &#039;&#039;&#039;nfvo.py&#039;&#039;&#039; is the main engine, implementing all the methods for the creation, deletion and management of vnfs, scenarios and instances. Operations against a VIM are asynchornous. ACTIONs to be done are stored at database before returning ok to the client&lt;br /&gt;
* &#039;&#039;&#039;nfvo_db.py&#039;&#039;&#039; is the module in charge of database operations. Uses base &#039;&#039;&#039;db_base.py&#039;&#039;&#039;. Database is managed with MySQLdb python library&lt;br /&gt;
* &#039;&#039;&#039;openmano_schemas.py&#039;&#039;&#039; is a dictionary schemas used to validate API request and response content using jsonschema library&lt;br /&gt;
* &#039;&#039;&#039;vim_thread.py&#039;&#039;&#039; There is a thread per VIM and credentials. It performs basic tasks of creating/deleting VM, networks, flavors, etc. In addition it refreshes the VM and network status. It calls vimconn.py methods &lt;br /&gt;
* &#039;&#039;&#039;vimconn.py&#039;&#039;&#039; is the base class for the VIM plugin. It contains the definition of the methods to be implemented. The inherited &#039;&#039;&#039;vimconn_openstack.py&#039;&#039;&#039;, &#039;&#039;&#039;vimconn_openvim.py&#039;&#039;&#039;, &#039;&#039;&#039;vimconn_vmware&#039;&#039;&#039; and &#039;&#039;&#039;vimconn_aws&#039;&#039;&#039; implements the operations against the concrete VIM type. Openstack plugin uses the client-python libraris, meanwhile Openvim plugin uses direct http requests.&lt;br /&gt;
* &#039;&#039;&#039;console_proxy_thread.py&#039;&#039;&#039; is a thread that implements a TCP/IP proxy for the console access to a VIM&lt;br /&gt;
&lt;br /&gt;
===RO Client modules===&lt;br /&gt;
Other modules not part of the server are:&lt;br /&gt;
* &#039;&#039;&#039;openmnao&#039;&#039;&#039; is a CLI client&lt;br /&gt;
* &#039;&#039;&#039;openmanoclient.py&#039;&#039;&#039; is a client python library for managing openmano server&lt;br /&gt;
&lt;br /&gt;
===ACTIONS and TASKS===&lt;br /&gt;
ACTIONS are a a group of tasks performed against a a concrete instance-scenarios (NS record). The creation and deletion of the instance-scenario itself is an action. As it is asynchonous, NBI returns an &amp;quot;Action_id&amp;quot; that can be used to check the status. For each action, nfvo.py generates individual tasks for the related VIMs. Tasks are both stored at database and sent to the related vim_thread.py. A task has a concrete relation with a VIM, e.g. create/delete a VM, a network, ... look for a flavor, network, ...&lt;br /&gt;
&lt;br /&gt;
===Database content===&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
==Database changes==&lt;br /&gt;
Database schema can be changed if needed. It is recomended to use a graphical tool (e.g. Heidy) to change database and change it back and copy the SQL commands. Make this steps:&lt;br /&gt;
&lt;br /&gt;
1. openmanod: increment __version__, version_date and database_version&lt;br /&gt;
2. database_utils/migrate_mano_db.sh. See the three &amp;quot;TODO&amp;quot;&lt;br /&gt;
2a. Increment LAST_DB_VERSION&lt;br /&gt;
2b. Annotate a comment to have a track of versions: [ $OPENMANO_VER_NUM -ge 50XX ] &amp;amp;&amp;amp; DB_VERSION=XX  #0.5.XX =&amp;gt;  XX&lt;br /&gt;
3c. Generate new methods function upgrade_to_XX() and function downgrade_from_XX. Insert here the sql commands. Last sql command over schema_version is quite important to detect the database version.&lt;br /&gt;
&lt;br /&gt;
Test several upgrades/downgrades to version 20 with &amp;quot;migrate_mano_db.sh&amp;quot; and &amp;quot;migrate_mano_db.sh 20&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Package dependency osm-im==&lt;br /&gt;
It is under IM repository. It contains the OSM models. Used models at RO are under &amp;lt;IM&amp;gt;/models/yang/vnfd.yang and &amp;lt;IM&amp;gt;/models/yang/nsd.yang. More modules will be incorporated in the future.&lt;br /&gt;
&lt;br /&gt;
When IM is maked, pyangbind generates python source files imported at RO. They are used to validate and load a yaml/json VNFD and NSD catalog descriptor.&lt;br /&gt;
&lt;br /&gt;
Method pybindJSONDecoder.load_ietf_json from pyangbind is used to parse and load the descriptor. A structure of nested YANG classes are generated and used at &amp;lt;RO&amp;gt;/osm_ro/nfvo.py methods new_vnfd_v3 and new_nsd_v3. RO supports backward compatibility with old format descriptors. NBI (osm_ro/httpserver.py) uses .../v3/... at URL to diferenciate between old and new descriptors. CLI (openmano) detects automatically if the descriptor is in old format or in OSM format to send the request to the server using the old URL or the new &amp;quot;v3&amp;quot; URL&lt;br /&gt;
&lt;br /&gt;
===Installation===&lt;br /&gt;
The OSM binary installation install this package. In case of needed you can install/update it manually by:&lt;br /&gt;
&lt;br /&gt;
  apt-get update&lt;br /&gt;
  apt-get install make git python python-pip tox debhelper python-bitarray python-lxml&lt;br /&gt;
  pip install --upgrade pip&lt;br /&gt;
  # If not inside a container. Use &amp;quot;sudo -HE&amp;quot; to get root privileges for pip installation&lt;br /&gt;
  pip install pyangbind stdeb&lt;br /&gt;
  git clone https://osm.etsi.org/gerrit/osm/IM&lt;br /&gt;
  make -C IM clean all&lt;br /&gt;
  dpkg -i IM/deb_dist/python-pyang*.deb&lt;br /&gt;
  dpkg -i IM/deb_dist/python-pyangbind*.deb&lt;br /&gt;
  dpkg -i IM/deb_dist/python-osm-im*.deb&lt;br /&gt;
  # Use this line to check if it is installed and where  &lt;br /&gt;
  python -c &#039;import osm_im; print osm_im.__path__[0]&#039;&lt;br /&gt;
&lt;br /&gt;
==Package dependency lib-osm-openvim==&lt;br /&gt;
&lt;br /&gt;
It is under openvim repository. RO uses a library for the SDN assist that is in charge of performing the underlay dataplane connectivity using an openflow controller. osm-openvim and lib-osm-openvim are diffent, though they share same pieces of code. lib-osm-openvim uses a different database name (mano_vim_db) so that openvim can be installed in the same virtual machine or container (openvim uses vim_db database name) &lt;br /&gt;
&lt;br /&gt;
TODO complete where RO uses it&lt;br /&gt;
&lt;br /&gt;
===Installation===&lt;br /&gt;
The OSM binary installation install this package. In case of needed you can install/update it manually by:&lt;br /&gt;
&lt;br /&gt;
  apt-get update&lt;br /&gt;
  apt-get install make git python tox libmysqlclient-dev&lt;br /&gt;
  git clone https://osm.etsi.org/gerrit/osm/openvim&lt;br /&gt;
  git -C openvim checkout 005a9dc  # this is temporal, because last version contains error at Makefile&lt;br /&gt;
  make -C openvim lite&lt;br /&gt;
  # Use this line to check if it is installed and where  &lt;br /&gt;
  python -c &#039;import lib_osm_openvim; print lib_osm_openvim.__path__[0]&#039;&lt;br /&gt;
  # Install database of ovim library&lt;br /&gt;
  OSMLIBOVIM_PATH=`python -c &#039;import lib_osm_openvim; print lib_osm_openvim.__path__[0]&#039;`&lt;br /&gt;
  # -U and -P are the admin database user/password. Normally &amp;quot;-U root&amp;quot; without password &amp;quot;executed as root&amp;quot;&lt;br /&gt;
  ${OSMLIBOVIM_PATH}/database_utils/install-db-server.sh -U root [-P passwd] -u mano -p manopw -d mano_vim_db --updatedb&lt;br /&gt;
&lt;br /&gt;
==CLI client==&lt;br /&gt;
&lt;br /&gt;
The RO code contains a python CLI (openmano) that allows friently command execution. This CLI client can run on a separate machine where openmano server is running. &amp;quot;openmano config&amp;quot; indicates where the server is (by default localhost)&lt;br /&gt;
&lt;br /&gt;
==Northbound Interface==&lt;br /&gt;
&lt;br /&gt;
The RO uses a REST API with YAML/JSON content. The primitives are explained [[RO Northbound Interface|here]]&lt;br /&gt;
&lt;br /&gt;
==Running Unit Tests==&lt;br /&gt;
&lt;br /&gt;
===Launching RO===&lt;br /&gt;
Openmano can run as systemd service. (Can be installed with &#039;&#039;&#039;./scripts/install-openmano-service.sh -f RO&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
Or can be run inside a screen (the prefered method for developpers). The script to easily launch/remove is &#039;&#039;&#039;./scripts/service-openmano.sh&#039;&#039;&#039;. Execute with -h to see options&lt;br /&gt;
&lt;br /&gt;
Note that the general OSM install script, installs openmano inside a container and code run at folder /opt/openmano (instead of $HOME/openmano)&lt;br /&gt;
&lt;br /&gt;
===Tests===&lt;br /&gt;
Many of openmano operations rely on an external VIM. Without external infraestructure it is recomended to use openvim in &amp;quot;test&amp;quot; (fake) mode. Install it in the same machine where openmano is located with [[OpenVIM_installation_(Release_One)#Installation]]&lt;br /&gt;
&lt;br /&gt;
Run &#039;&#039;./test/basictest&#039;&#039; for a initial test. Type -h to see options. For testing using openvim just run &amp;lt;pre&amp;gt; . ./test/basictest.sh --force --screen --init-openvim &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating a new VIM plugin==&lt;br /&gt;
&lt;br /&gt;
Choose a name, eg. XXX&lt;br /&gt;
&lt;br /&gt;
Create a new python module vimconn_XXX.py derived from vimconn.py class. Implement the relevant functions. You have several connectors already created to be used as example as openstack and openvim. Openstack connector uses the python openstack client libraries, meanwhile openvim connector uses direct http requests.&lt;br /&gt;
&lt;br /&gt;
DO NOT change the method names, parameters or parameter content. Openmano use the same methods for all the VIMs and they cannot be changed to accomodate VIM specifics. VIM specifics must be solved inside the connector.&lt;br /&gt;
&lt;br /&gt;
The new module can need specific configuration for the VIM that it is passed as a dictionary in the &#039;&#039;config&#039;&#039; variable at constructor. For example, in the case of openstack, &#039;&#039;config&#039;&#039; variable is used for: enabling/disabling port_security_enable, specifying the name of the physical network used for dataplane, regions, etc. The &#039;&#039;config&#039;&#039; variable is the right place to specify those needed parameters not provided by openmano at the methods that form part of the VIM configuration. See [[Openstack configuration (Release TWO)#Add openstack toOSM]] and [[Configuring AWS for OSM Release TWO#Add AWS to OSM]] for examples &lt;br /&gt;
&lt;br /&gt;
Integration with the main project is automatic, just create a new datacenter of type XXX and this module will be automatically loaded. No other module of the main program need to be updated.&lt;br /&gt;
&lt;br /&gt;
    openmano tenant-create osm  # if not already done&lt;br /&gt;
    export OPENMANO_TENANT=osm&lt;br /&gt;
    openmano datacenter-create &amp;lt;vim-name&amp;gt; &amp;lt;access-URL&amp;gt;  --type=XXX --config &amp;lt;specific config&amp;gt;&lt;br /&gt;
    # if fails the cause can be a librery you need not installed or an error upon importing. Try tho import it in a python client&lt;br /&gt;
    # example of &amp;lt;specific config&amp;gt; text: &amp;quot;{dataplane_physical_net: physnet_sriov, port_security_enabled: False}&amp;quot;&lt;br /&gt;
    openmano datacenter-attach &amp;lt;vim-name&amp;gt; --vim-tenant-name=&amp;lt;tenant-to-use-by-openmano&amp;gt; --user=&amp;lt;tenant-user&amp;gt; --password=&amp;lt;tenant-password&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can test it using the &#039;&#039;&#039;test/test_RO.py&#039;&#039;&#039; file:&lt;br /&gt;
    # Create manually an image &amp;lt;image&amp;gt; and a management network &amp;lt;net-mgmt&amp;gt; at your VIM&lt;br /&gt;
    ./test/test_RO.py deploy --help&lt;br /&gt;
    # e.g. ./test/test_RO.py deploy -n &amp;lt;net-mgmt&amp;gt; -t osm -i &amp;lt;image&amp;gt; -d &amp;lt;vim-name&amp;gt; --timeout=30 --test simple_linux,simple_multi_vnfc,simple_2_vnf&lt;br /&gt;
    ./test/test_RO.py vimconn --help&lt;/div&gt;</summary>
		<author><name>Cardosoi</name></author>
	</entry>
	<entry>
		<id>https://osm.etsi.org/wikipub/index.php?title=Developer_HowTo_for_RO_Module&amp;diff=1834</id>
		<title>Developer HowTo for RO Module</title>
		<link rel="alternate" type="text/html" href="https://osm.etsi.org/wikipub/index.php?title=Developer_HowTo_for_RO_Module&amp;diff=1834"/>
		<updated>2017-10-23T09:44:36Z</updated>

		<summary type="html">&lt;p&gt;Cardosoi: E.g. Proxy might be set in environment, so keep environment on sude/* Installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Getting Started==&lt;br /&gt;
The RO Module is implemented by openmano. The recommended Linux distribution for development is Ubuntu 16.04 LTS Server. PyCharm is a nice and easy to use tool for development and debugging.&lt;br /&gt;
&lt;br /&gt;
The step [[Release_1_Installation]] installs all OSM modules in containers. However, for development, a virtual machine may be more suitable. To install the openmano module you can run a script that installs the required packages, clone the project from &#039;&#039;git clones https://osm.etsi.org/gerrit/osm/RO&#039;&#039; and configures openmano client and other utility scripts at path&lt;br /&gt;
 wget -O install-openmano.sh &amp;quot;https://osm.etsi.org/gitweb/?p=osm/RO.git;a=blob_plain;f=scripts/install-openmano.sh&amp;quot;&lt;br /&gt;
 chmod +x install-openmano.sh&lt;br /&gt;
 sudo ./install-openmano.sh -q --develop   #-h for help&lt;br /&gt;
&lt;br /&gt;
See also and follow [[Workflow_with_OSM_tools#Clone_your_project]]&lt;br /&gt;
&lt;br /&gt;
New code features must be incorporated to master:&lt;br /&gt;
 git checkout master&lt;br /&gt;
Generate a &amp;quot;.gitignore&amp;quot;, you can use the &#039;&#039;.gitignore-common&#039;&#039; example that skips PyCharm and Eclipse files&lt;br /&gt;
 cp RO/.gitignore-common RO/.gitignore&lt;br /&gt;
 #edit to include your local files to ignore&lt;br /&gt;
Prepare your git environment to push with a proper user/email, push to gerrit. See and configure:&lt;br /&gt;
&amp;lt;p&amp;gt;[[Workflow_with_OSM_tools#Configure_your_Git_environment]]&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;[[Workflow_with_OSM_tools#Commit_changes_to_your_local_project]]&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;[[ Workflow_with_OSM_tools#Push_your_contribution_to_Gerrit]]&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programming Language==&lt;br /&gt;
The RO module uses Python2. However Python3 conventions for a possible future migration should be used as far as possible. For example:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! BAD Python2&lt;br /&gt;
! OK  Python2 compatible with python3&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;format test string %s number %d&amp;quot; % (st, num)&lt;br /&gt;
| &amp;quot;format test string {} number {}&amp;quot;.format(st, num)&lt;br /&gt;
|-&lt;br /&gt;
| print a, b, c&lt;br /&gt;
| print(a,b,c)&lt;br /&gt;
|-&lt;br /&gt;
| except Exception, e&lt;br /&gt;
| except Exception as e&lt;br /&gt;
|-&lt;br /&gt;
| if type(x) == X:&lt;br /&gt;
| if isinstance(x,X):&lt;br /&gt;
|}&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Descriptors can be YAML (prefered because more readable and allow comments) or JSON&lt;br /&gt;
&lt;br /&gt;
==Code Style==&lt;br /&gt;
Please follow PEP8 style guide for all the Python code.&lt;br /&gt;
&lt;br /&gt;
===Logging===&lt;br /&gt;
Use the appropriate logging levels when logging the messages. An example is shown below:&lt;br /&gt;
    self.logger.debug(&amp;quot;Changing state to %s&amp;quot;, next_state)&lt;br /&gt;
&lt;br /&gt;
Logging levels (general and per module) are specified at &#039;&#039;&#039;openmanod.cfg&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Try to use few useful logs, not verbose, that brings useful information. For example, in case of fail getting a server, the complete URL should be provided.&lt;br /&gt;
&lt;br /&gt;
Avoid several logs together&lt;br /&gt;
&lt;br /&gt;
  WRONG:&lt;br /&gt;
  self.looger.debug(&amp;quot;Entering in method A&amp;quot;)&lt;br /&gt;
  self.logger.debug(&amp;quot;Contacting server&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  RIGHT:&lt;br /&gt;
  self.logger.debug(&amp;quot;method A, contacting server %s&amp;quot;, url)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the traceback is needed(call stack that generate the exception) , use the &amp;quot;exc_info=True&amp;quot; parameter&lt;br /&gt;
  self.logger.error(&amp;quot;Exception %s when ...&amp;quot;, exception, exc_info=True)&lt;br /&gt;
&lt;br /&gt;
===Exceptions===&lt;br /&gt;
Code must be wrote in a way that functions and methods raise an exception when something goes wrong, instead of returning a negative or false value.&lt;br /&gt;
&lt;br /&gt;
Example&lt;br /&gt;
  WRONG&lt;br /&gt;
    def get_ip_address():&lt;br /&gt;
        ...&lt;br /&gt;
        if fail:&lt;br /&gt;
            return False, &amp;quot;Fail because xxx&amp;quot;&lt;br /&gt;
        return True, ip&lt;br /&gt;
    &lt;br /&gt;
    ...&lt;br /&gt;
    result, ip = get_ip_address()&lt;br /&gt;
    if not result:&lt;br /&gt;
        return False, &amp;quot;Cannot get ip address...&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  RIGHT&lt;br /&gt;
    def get_ip_address():&lt;br /&gt;
        ...&lt;br /&gt;
        if fail:&lt;br /&gt;
            raise customException(&amp;quot;Fail because ...&amp;quot;)&lt;br /&gt;
        return ip&lt;br /&gt;
    &lt;br /&gt;
    ...&lt;br /&gt;
    try:&lt;br /&gt;
        ip = get_ip_address()&lt;br /&gt;
        ...&lt;br /&gt;
    except customException as e:&lt;br /&gt;
        raise customException2(str(e))&lt;br /&gt;
&lt;br /&gt;
==Directory Organization==&lt;br /&gt;
The code organized into the following high level directories: &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/&#039;&#039;&#039; contains the entry server file &#039;&#039;openmanod&#039;&#039; and client &#039;&#039;openmano&#039;&#039; code &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/osm_ro&#039;&#039;&#039; contains the RO server code files &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/test&#039;&#039;&#039; contains scripts and code for testing &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/database_utils&#039;&#039;&#039; contains scripts for database creation, dumping and migration &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/scripts&#039;&#039;&#039; general scripts, as installation, execution, reporting &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/scenarios&#039;&#039;&#039; examples and templates of network scnario descriptors &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/vnfs&#039;&#039;&#039; examples and templates of VNF descriptors &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==RO Architecture==&lt;br /&gt;
[[File:OpenmanoArchitecture.png|400px]]&lt;br /&gt;
&lt;br /&gt;
===RO Server modules===&lt;br /&gt;
The RO module contains the following modules&lt;br /&gt;
* &#039;&#039;&#039;openmanod&#039;&#039;&#039; is the main program. It reads the configuration file (openmanod.cfg) and execute the httpserver and wait for the end&lt;br /&gt;
* &#039;&#039;&#039;httpserver.py&#039;&#039;&#039; is a thread that implements the northbound API interface, uses python bottle module. Calls main engine methods to perform the tasks&lt;br /&gt;
* &#039;&#039;&#039;nfvo.py&#039;&#039;&#039; is the main engine, implementing all the methods for the creation, deletion and management of vnfs, scenarios and instances. Operations against a VIM are asynchornous. ACTIONs to be done are stored at database before returning ok to the client&lt;br /&gt;
* &#039;&#039;&#039;nfvo_db.py&#039;&#039;&#039; is the module in charge of database operations. Uses base &#039;&#039;&#039;db_base.py&#039;&#039;&#039;. Database is managed with MySQLdb python library&lt;br /&gt;
* &#039;&#039;&#039;openmano_schemas.py&#039;&#039;&#039; is a dictionary schemas used to validate API request and response content using jsonschema library&lt;br /&gt;
* &#039;&#039;&#039;vim_thread.py&#039;&#039;&#039; There is a thread per VIM and credentials. It performs basic tasks of creating/deleting VM, networks, flavors, etc. In addition it refreshes the VM and network status. It calls vimconn.py methods &lt;br /&gt;
* &#039;&#039;&#039;vimconn.py&#039;&#039;&#039; is the base class for the VIM plugin. It contains the definition of the methods to be implemented. The inherited &#039;&#039;&#039;vimconn_openstack.py&#039;&#039;&#039;, &#039;&#039;&#039;vimconn_openvim.py&#039;&#039;&#039;, &#039;&#039;&#039;vimconn_vmware&#039;&#039;&#039; and &#039;&#039;&#039;vimconn_aws&#039;&#039;&#039; implements the operations against the concrete VIM type. Openstack plugin uses the client-python libraris, meanwhile Openvim plugin uses direct http requests.&lt;br /&gt;
* &#039;&#039;&#039;console_proxy_thread.py&#039;&#039;&#039; is a thread that implements a TCP/IP proxy for the console access to a VIM&lt;br /&gt;
&lt;br /&gt;
===RO Client modules===&lt;br /&gt;
Other modules not part of the server are:&lt;br /&gt;
* &#039;&#039;&#039;openmnao&#039;&#039;&#039; is a CLI client&lt;br /&gt;
* &#039;&#039;&#039;openmanoclient.py&#039;&#039;&#039; is a client python library for managing openmano server&lt;br /&gt;
&lt;br /&gt;
===ACTIONS and TASKS===&lt;br /&gt;
ACTIONS are a a group of tasks performed against a a concrete instance-scenarios (NS record). The creation and deletion of the instance-scenario itself is an action. As it is asynchonous, NBI returns an &amp;quot;Action_id&amp;quot; that can be used to check the status. For each action, nfvo.py generates individual tasks for the related VIMs. Tasks are both stored at database and sent to the related vim_thread.py. A task has a concrete relation with a VIM, e.g. create/delete a VM, a network, ... look for a flavor, network, ...&lt;br /&gt;
&lt;br /&gt;
===Database content===&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
==Database changes==&lt;br /&gt;
Database schema can be changed if needed. It is recomended to use a graphical tool (e.g. Heidy) to change database and change it back and copy the SQL commands. Make this steps:&lt;br /&gt;
&lt;br /&gt;
1. openmanod: increment __version__, version_date and database_version&lt;br /&gt;
2. database_utils/migrate_mano_db.sh. See the three &amp;quot;TODO&amp;quot;&lt;br /&gt;
2a. Increment LAST_DB_VERSION&lt;br /&gt;
2b. Annotate a comment to have a track of versions: [ $OPENMANO_VER_NUM -ge 50XX ] &amp;amp;&amp;amp; DB_VERSION=XX  #0.5.XX =&amp;gt;  XX&lt;br /&gt;
3c. Generate new methods function upgrade_to_XX() and function downgrade_from_XX. Insert here the sql commands. Last sql command over schema_version is quite important to detect the database version.&lt;br /&gt;
&lt;br /&gt;
Test several upgrades/downgrades to version 20 with &amp;quot;migrate_mano_db.sh&amp;quot; and &amp;quot;migrate_mano_db.sh 20&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Package dependency osm-im==&lt;br /&gt;
It is under IM repository. It contains the OSM models. Used models at RO are under &amp;lt;IM&amp;gt;/models/yang/vnfd.yang and &amp;lt;IM&amp;gt;/models/yang/nsd.yang. More modules will be incorporated in the future.&lt;br /&gt;
&lt;br /&gt;
When IM is maked, pyangbind generates python source files imported at RO. They are used to validate and load a yaml/json VNFD and NSD catalog descriptor.&lt;br /&gt;
&lt;br /&gt;
Method pybindJSONDecoder.load_ietf_json from pyangbind is used to parse and load the descriptor. A structure of nested YANG classes are generated and used at &amp;lt;RO&amp;gt;/osm_ro/nfvo.py methods new_vnfd_v3 and new_nsd_v3. RO supports backward compatibility with old format descriptors. NBI (osm_ro/httpserver.py) uses .../v3/... at URL to diferenciate between old and new descriptors. CLI (openmano) detects automatically if the descriptor is in old format or in OSM format to send the request to the server using the old URL or the new &amp;quot;v3&amp;quot; URL&lt;br /&gt;
&lt;br /&gt;
===Installation===&lt;br /&gt;
The OSM binary installation install this package. In case of needed you can install/update it manually by:&lt;br /&gt;
&lt;br /&gt;
  apt-get update&lt;br /&gt;
  apt-get install make git python python-pip tox debhelper python-bitarray python-pyangbind&lt;br /&gt;
  pip install --upgrade pip&lt;br /&gt;
  # If not inside a container. Use &amp;quot;sudo -HE&amp;quot; to get root privileges for pip installation&lt;br /&gt;
  pip install pyangbind stdeb&lt;br /&gt;
  git clone https://osm.etsi.org/gerrit/osm/IM&lt;br /&gt;
  make -C IM clean all&lt;br /&gt;
  dpkg -i IM/deb_dist/python-osm-im*.deb&lt;br /&gt;
  # Use this line to check if it is installed and where  &lt;br /&gt;
  python -c &#039;import osm_im; print osm_im.__path__[0]&#039;&lt;br /&gt;
&lt;br /&gt;
==Package dependency lib-osm-openvim==&lt;br /&gt;
&lt;br /&gt;
It is under openvim repository. RO uses a library for the SDN assist that is in charge of performing the underlay dataplane connectivity using an openflow controller. osm-openvim and lib-osm-openvim are diffent, though they share same pieces of code. lib-osm-openvim uses a different database name (mano_vim_db) so that openvim can be installed in the same virtual machine or container (openvim uses vim_db database name) &lt;br /&gt;
&lt;br /&gt;
TODO complete where RO uses it&lt;br /&gt;
&lt;br /&gt;
===Installation===&lt;br /&gt;
The OSM binary installation install this package. In case of needed you can install/update it manually by:&lt;br /&gt;
&lt;br /&gt;
  apt-get update&lt;br /&gt;
  apt-get install make git python tox libmysqlclient-dev&lt;br /&gt;
  git clone https://osm.etsi.org/gerrit/osm/openvim&lt;br /&gt;
  git -C openvim checkout 005a9dc  # this is temporal, because last version contains error at Makefile&lt;br /&gt;
  make -C openvim lite&lt;br /&gt;
  # Use this line to check if it is installed and where  &lt;br /&gt;
  python -c &#039;import lib_osm_openvim; print lib_osm_openvim.__path__[0]&#039;&lt;br /&gt;
  # Install database of ovim library&lt;br /&gt;
  OSMLIBOVIM_PATH=`python -c &#039;import lib_osm_openvim; print lib_osm_openvim.__path__[0]&#039;`&lt;br /&gt;
  # -U and -P are the admin database user/password. Normally &amp;quot;-U root&amp;quot; without password &amp;quot;executed as root&amp;quot;&lt;br /&gt;
  ${OSMLIBOVIM_PATH}/database_utils/install-db-server.sh -U root [-P passwd] -u mano -p manopw -d mano_vim_db --updatedb&lt;br /&gt;
&lt;br /&gt;
==CLI client==&lt;br /&gt;
&lt;br /&gt;
The RO code contains a python CLI (openmano) that allows friently command execution. This CLI client can run on a separate machine where openmano server is running. &amp;quot;openmano config&amp;quot; indicates where the server is (by default localhost)&lt;br /&gt;
&lt;br /&gt;
==Northbound Interface==&lt;br /&gt;
&lt;br /&gt;
The RO uses a REST API with YAML/JSON content. The primitives are explained [[RO Northbound Interface|here]]&lt;br /&gt;
&lt;br /&gt;
==Running Unit Tests==&lt;br /&gt;
&lt;br /&gt;
===Launching RO===&lt;br /&gt;
Openmano can run as systemd service. (Can be installed with &#039;&#039;&#039;./scripts/install-openmano-service.sh -f RO&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
Or can be run inside a screen (the prefered method for developpers). The script to easily launch/remove is &#039;&#039;&#039;./scripts/service-openmano.sh&#039;&#039;&#039;. Execute with -h to see options&lt;br /&gt;
&lt;br /&gt;
Note that the general OSM install script, installs openmano inside a container and code run at folder /opt/openmano (instead of $HOME/openmano)&lt;br /&gt;
&lt;br /&gt;
===Tests===&lt;br /&gt;
Many of openmano operations rely on an external VIM. Without external infraestructure it is recomended to use openvim in &amp;quot;test&amp;quot; (fake) mode. Install it in the same machine where openmano is located with [[OpenVIM_installation_(Release_One)#Installation]]&lt;br /&gt;
&lt;br /&gt;
Run &#039;&#039;./test/basictest&#039;&#039; for a initial test. Type -h to see options. For testing using openvim just run &amp;lt;pre&amp;gt; . ./test/basictest.sh --force --screen --init-openvim &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating a new VIM plugin==&lt;br /&gt;
&lt;br /&gt;
Choose a name, eg. XXX&lt;br /&gt;
&lt;br /&gt;
Create a new python module vimconn_XXX.py derived from vimconn.py class. Implement the relevant functions. You have several connectors already created to be used as example as openstack and openvim. Openstack connector uses the python openstack client libraries, meanwhile openvim connector uses direct http requests.&lt;br /&gt;
&lt;br /&gt;
DO NOT change the method names, parameters or parameter content. Openmano use the same methods for all the VIMs and they cannot be changed to accomodate VIM specifics. VIM specifics must be solved inside the connector.&lt;br /&gt;
&lt;br /&gt;
The new module can need specific configuration for the VIM that it is passed as a dictionary in the &#039;&#039;config&#039;&#039; variable at constructor. For example, in the case of openstack, &#039;&#039;config&#039;&#039; variable is used for: enabling/disabling port_security_enable, specifying the name of the physical network used for dataplane, regions, etc. The &#039;&#039;config&#039;&#039; variable is the right place to specify those needed parameters not provided by openmano at the methods that form part of the VIM configuration. See [[Openstack configuration (Release TWO)#Add openstack toOSM]] and [[Configuring AWS for OSM Release TWO#Add AWS to OSM]] for examples &lt;br /&gt;
&lt;br /&gt;
Integration with the main project is automatic, just create a new datacenter of type XXX and this module will be automatically loaded. No other module of the main program need to be updated.&lt;br /&gt;
&lt;br /&gt;
    openmano tenant-create osm  # if not already done&lt;br /&gt;
    export OPENMANO_TENANT=osm&lt;br /&gt;
    openmano datacenter-create &amp;lt;vim-name&amp;gt; &amp;lt;access-URL&amp;gt;  --type=XXX --config &amp;lt;specific config&amp;gt;&lt;br /&gt;
    # if fails the cause can be a librery you need not installed or an error upon importing. Try tho import it in a python client&lt;br /&gt;
    # example of &amp;lt;specific config&amp;gt; text: &amp;quot;{dataplane_physical_net: physnet_sriov, port_security_enabled: False}&amp;quot;&lt;br /&gt;
    openmano datacenter-attach &amp;lt;vim-name&amp;gt; --vim-tenant-name=&amp;lt;tenant-to-use-by-openmano&amp;gt; --user=&amp;lt;tenant-user&amp;gt; --password=&amp;lt;tenant-password&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can test it using the &#039;&#039;&#039;test/test_RO.py&#039;&#039;&#039; file:&lt;br /&gt;
    # Create manually an image &amp;lt;image&amp;gt; and a management network &amp;lt;net-mgmt&amp;gt; at your VIM&lt;br /&gt;
    ./test/test_RO.py deploy --help&lt;br /&gt;
    # e.g. ./test/test_RO.py deploy -n &amp;lt;net-mgmt&amp;gt; -t osm -i &amp;lt;image&amp;gt; -d &amp;lt;vim-name&amp;gt; --timeout=30 --test simple_linux,simple_multi_vnfc,simple_2_vnf&lt;br /&gt;
    ./test/test_RO.py vimconn --help&lt;/div&gt;</summary>
		<author><name>Cardosoi</name></author>
	</entry>
	<entry>
		<id>https://osm.etsi.org/wikipub/index.php?title=Developer_HowTo_for_RO_Module&amp;diff=1833</id>
		<title>Developer HowTo for RO Module</title>
		<link rel="alternate" type="text/html" href="https://osm.etsi.org/wikipub/index.php?title=Developer_HowTo_for_RO_Module&amp;diff=1833"/>
		<updated>2017-10-23T09:41:55Z</updated>

		<summary type="html">&lt;p&gt;Cardosoi: /* Getting Started */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Getting Started==&lt;br /&gt;
The RO Module is implemented by openmano. The recommended Linux distribution for development is Ubuntu 16.04 LTS Server. PyCharm is a nice and easy to use tool for development and debugging.&lt;br /&gt;
&lt;br /&gt;
The step [[Release_1_Installation]] installs all OSM modules in containers. However, for development, a virtual machine may be more suitable. To install the openmano module you can run a script that installs the required packages, clone the project from &#039;&#039;git clones https://osm.etsi.org/gerrit/osm/RO&#039;&#039; and configures openmano client and other utility scripts at path&lt;br /&gt;
 wget -O install-openmano.sh &amp;quot;https://osm.etsi.org/gitweb/?p=osm/RO.git;a=blob_plain;f=scripts/install-openmano.sh&amp;quot;&lt;br /&gt;
 chmod +x install-openmano.sh&lt;br /&gt;
 sudo ./install-openmano.sh -q --develop   #-h for help&lt;br /&gt;
&lt;br /&gt;
See also and follow [[Workflow_with_OSM_tools#Clone_your_project]]&lt;br /&gt;
&lt;br /&gt;
New code features must be incorporated to master:&lt;br /&gt;
 git checkout master&lt;br /&gt;
Generate a &amp;quot;.gitignore&amp;quot;, you can use the &#039;&#039;.gitignore-common&#039;&#039; example that skips PyCharm and Eclipse files&lt;br /&gt;
 cp RO/.gitignore-common RO/.gitignore&lt;br /&gt;
 #edit to include your local files to ignore&lt;br /&gt;
Prepare your git environment to push with a proper user/email, push to gerrit. See and configure:&lt;br /&gt;
&amp;lt;p&amp;gt;[[Workflow_with_OSM_tools#Configure_your_Git_environment]]&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;[[Workflow_with_OSM_tools#Commit_changes_to_your_local_project]]&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;[[ Workflow_with_OSM_tools#Push_your_contribution_to_Gerrit]]&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Programming Language==&lt;br /&gt;
The RO module uses Python2. However Python3 conventions for a possible future migration should be used as far as possible. For example:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! BAD Python2&lt;br /&gt;
! OK  Python2 compatible with python3&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;format test string %s number %d&amp;quot; % (st, num)&lt;br /&gt;
| &amp;quot;format test string {} number {}&amp;quot;.format(st, num)&lt;br /&gt;
|-&lt;br /&gt;
| print a, b, c&lt;br /&gt;
| print(a,b,c)&lt;br /&gt;
|-&lt;br /&gt;
| except Exception, e&lt;br /&gt;
| except Exception as e&lt;br /&gt;
|-&lt;br /&gt;
| if type(x) == X:&lt;br /&gt;
| if isinstance(x,X):&lt;br /&gt;
|}&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Descriptors can be YAML (prefered because more readable and allow comments) or JSON&lt;br /&gt;
&lt;br /&gt;
==Code Style==&lt;br /&gt;
Please follow PEP8 style guide for all the Python code.&lt;br /&gt;
&lt;br /&gt;
===Logging===&lt;br /&gt;
Use the appropriate logging levels when logging the messages. An example is shown below:&lt;br /&gt;
    self.logger.debug(&amp;quot;Changing state to %s&amp;quot;, next_state)&lt;br /&gt;
&lt;br /&gt;
Logging levels (general and per module) are specified at &#039;&#039;&#039;openmanod.cfg&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Try to use few useful logs, not verbose, that brings useful information. For example, in case of fail getting a server, the complete URL should be provided.&lt;br /&gt;
&lt;br /&gt;
Avoid several logs together&lt;br /&gt;
&lt;br /&gt;
  WRONG:&lt;br /&gt;
  self.looger.debug(&amp;quot;Entering in method A&amp;quot;)&lt;br /&gt;
  self.logger.debug(&amp;quot;Contacting server&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  RIGHT:&lt;br /&gt;
  self.logger.debug(&amp;quot;method A, contacting server %s&amp;quot;, url)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the traceback is needed(call stack that generate the exception) , use the &amp;quot;exc_info=True&amp;quot; parameter&lt;br /&gt;
  self.logger.error(&amp;quot;Exception %s when ...&amp;quot;, exception, exc_info=True)&lt;br /&gt;
&lt;br /&gt;
===Exceptions===&lt;br /&gt;
Code must be wrote in a way that functions and methods raise an exception when something goes wrong, instead of returning a negative or false value.&lt;br /&gt;
&lt;br /&gt;
Example&lt;br /&gt;
  WRONG&lt;br /&gt;
    def get_ip_address():&lt;br /&gt;
        ...&lt;br /&gt;
        if fail:&lt;br /&gt;
            return False, &amp;quot;Fail because xxx&amp;quot;&lt;br /&gt;
        return True, ip&lt;br /&gt;
    &lt;br /&gt;
    ...&lt;br /&gt;
    result, ip = get_ip_address()&lt;br /&gt;
    if not result:&lt;br /&gt;
        return False, &amp;quot;Cannot get ip address...&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  RIGHT&lt;br /&gt;
    def get_ip_address():&lt;br /&gt;
        ...&lt;br /&gt;
        if fail:&lt;br /&gt;
            raise customException(&amp;quot;Fail because ...&amp;quot;)&lt;br /&gt;
        return ip&lt;br /&gt;
    &lt;br /&gt;
    ...&lt;br /&gt;
    try:&lt;br /&gt;
        ip = get_ip_address()&lt;br /&gt;
        ...&lt;br /&gt;
    except customException as e:&lt;br /&gt;
        raise customException2(str(e))&lt;br /&gt;
&lt;br /&gt;
==Directory Organization==&lt;br /&gt;
The code organized into the following high level directories: &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/&#039;&#039;&#039; contains the entry server file &#039;&#039;openmanod&#039;&#039; and client &#039;&#039;openmano&#039;&#039; code &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/osm_ro&#039;&#039;&#039; contains the RO server code files &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/test&#039;&#039;&#039; contains scripts and code for testing &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/database_utils&#039;&#039;&#039; contains scripts for database creation, dumping and migration &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/scripts&#039;&#039;&#039; general scripts, as installation, execution, reporting &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/scenarios&#039;&#039;&#039; examples and templates of network scnario descriptors &amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;/vnfs&#039;&#039;&#039; examples and templates of VNF descriptors &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==RO Architecture==&lt;br /&gt;
[[File:OpenmanoArchitecture.png|400px]]&lt;br /&gt;
&lt;br /&gt;
===RO Server modules===&lt;br /&gt;
The RO module contains the following modules&lt;br /&gt;
* &#039;&#039;&#039;openmanod&#039;&#039;&#039; is the main program. It reads the configuration file (openmanod.cfg) and execute the httpserver and wait for the end&lt;br /&gt;
* &#039;&#039;&#039;httpserver.py&#039;&#039;&#039; is a thread that implements the northbound API interface, uses python bottle module. Calls main engine methods to perform the tasks&lt;br /&gt;
* &#039;&#039;&#039;nfvo.py&#039;&#039;&#039; is the main engine, implementing all the methods for the creation, deletion and management of vnfs, scenarios and instances. Operations against a VIM are asynchornous. ACTIONs to be done are stored at database before returning ok to the client&lt;br /&gt;
* &#039;&#039;&#039;nfvo_db.py&#039;&#039;&#039; is the module in charge of database operations. Uses base &#039;&#039;&#039;db_base.py&#039;&#039;&#039;. Database is managed with MySQLdb python library&lt;br /&gt;
* &#039;&#039;&#039;openmano_schemas.py&#039;&#039;&#039; is a dictionary schemas used to validate API request and response content using jsonschema library&lt;br /&gt;
* &#039;&#039;&#039;vim_thread.py&#039;&#039;&#039; There is a thread per VIM and credentials. It performs basic tasks of creating/deleting VM, networks, flavors, etc. In addition it refreshes the VM and network status. It calls vimconn.py methods &lt;br /&gt;
* &#039;&#039;&#039;vimconn.py&#039;&#039;&#039; is the base class for the VIM plugin. It contains the definition of the methods to be implemented. The inherited &#039;&#039;&#039;vimconn_openstack.py&#039;&#039;&#039;, &#039;&#039;&#039;vimconn_openvim.py&#039;&#039;&#039;, &#039;&#039;&#039;vimconn_vmware&#039;&#039;&#039; and &#039;&#039;&#039;vimconn_aws&#039;&#039;&#039; implements the operations against the concrete VIM type. Openstack plugin uses the client-python libraris, meanwhile Openvim plugin uses direct http requests.&lt;br /&gt;
* &#039;&#039;&#039;console_proxy_thread.py&#039;&#039;&#039; is a thread that implements a TCP/IP proxy for the console access to a VIM&lt;br /&gt;
&lt;br /&gt;
===RO Client modules===&lt;br /&gt;
Other modules not part of the server are:&lt;br /&gt;
* &#039;&#039;&#039;openmnao&#039;&#039;&#039; is a CLI client&lt;br /&gt;
* &#039;&#039;&#039;openmanoclient.py&#039;&#039;&#039; is a client python library for managing openmano server&lt;br /&gt;
&lt;br /&gt;
===ACTIONS and TASKS===&lt;br /&gt;
ACTIONS are a a group of tasks performed against a a concrete instance-scenarios (NS record). The creation and deletion of the instance-scenario itself is an action. As it is asynchonous, NBI returns an &amp;quot;Action_id&amp;quot; that can be used to check the status. For each action, nfvo.py generates individual tasks for the related VIMs. Tasks are both stored at database and sent to the related vim_thread.py. A task has a concrete relation with a VIM, e.g. create/delete a VM, a network, ... look for a flavor, network, ...&lt;br /&gt;
&lt;br /&gt;
===Database content===&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
==Database changes==&lt;br /&gt;
Database schema can be changed if needed. It is recomended to use a graphical tool (e.g. Heidy) to change database and change it back and copy the SQL commands. Make this steps:&lt;br /&gt;
&lt;br /&gt;
1. openmanod: increment __version__, version_date and database_version&lt;br /&gt;
2. database_utils/migrate_mano_db.sh. See the three &amp;quot;TODO&amp;quot;&lt;br /&gt;
2a. Increment LAST_DB_VERSION&lt;br /&gt;
2b. Annotate a comment to have a track of versions: [ $OPENMANO_VER_NUM -ge 50XX ] &amp;amp;&amp;amp; DB_VERSION=XX  #0.5.XX =&amp;gt;  XX&lt;br /&gt;
3c. Generate new methods function upgrade_to_XX() and function downgrade_from_XX. Insert here the sql commands. Last sql command over schema_version is quite important to detect the database version.&lt;br /&gt;
&lt;br /&gt;
Test several upgrades/downgrades to version 20 with &amp;quot;migrate_mano_db.sh&amp;quot; and &amp;quot;migrate_mano_db.sh 20&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Package dependency osm-im==&lt;br /&gt;
It is under IM repository. It contains the OSM models. Used models at RO are under &amp;lt;IM&amp;gt;/models/yang/vnfd.yang and &amp;lt;IM&amp;gt;/models/yang/nsd.yang. More modules will be incorporated in the future.&lt;br /&gt;
&lt;br /&gt;
When IM is maked, pyangbind generates python source files imported at RO. They are used to validate and load a yaml/json VNFD and NSD catalog descriptor.&lt;br /&gt;
&lt;br /&gt;
Method pybindJSONDecoder.load_ietf_json from pyangbind is used to parse and load the descriptor. A structure of nested YANG classes are generated and used at &amp;lt;RO&amp;gt;/osm_ro/nfvo.py methods new_vnfd_v3 and new_nsd_v3. RO supports backward compatibility with old format descriptors. NBI (osm_ro/httpserver.py) uses .../v3/... at URL to diferenciate between old and new descriptors. CLI (openmano) detects automatically if the descriptor is in old format or in OSM format to send the request to the server using the old URL or the new &amp;quot;v3&amp;quot; URL&lt;br /&gt;
&lt;br /&gt;
===Installation===&lt;br /&gt;
The OSM binary installation install this package. In case of needed you can install/update it manually by:&lt;br /&gt;
&lt;br /&gt;
  apt-get update&lt;br /&gt;
  apt-get install make git python python-pip tox debhelper python-bitarray python-pyangbind&lt;br /&gt;
  pip install --upgrade pip&lt;br /&gt;
  # If not inside a container. Use &amp;quot;sudo -H&amp;quot; to get root privileges for pip installation&lt;br /&gt;
  pip install pyangbind stdeb&lt;br /&gt;
  git clone https://osm.etsi.org/gerrit/osm/IM&lt;br /&gt;
  make -C IM clean all&lt;br /&gt;
  dpkg -i IM/deb_dist/python-osm-im*.deb&lt;br /&gt;
  # Use this line to check if it is installed and where  &lt;br /&gt;
  python -c &#039;import osm_im; print osm_im.__path__[0]&#039;&lt;br /&gt;
&lt;br /&gt;
==Package dependency lib-osm-openvim==&lt;br /&gt;
&lt;br /&gt;
It is under openvim repository. RO uses a library for the SDN assist that is in charge of performing the underlay dataplane connectivity using an openflow controller. osm-openvim and lib-osm-openvim are diffent, though they share same pieces of code. lib-osm-openvim uses a different database name (mano_vim_db) so that openvim can be installed in the same virtual machine or container (openvim uses vim_db database name) &lt;br /&gt;
&lt;br /&gt;
TODO complete where RO uses it&lt;br /&gt;
&lt;br /&gt;
===Installation===&lt;br /&gt;
The OSM binary installation install this package. In case of needed you can install/update it manually by:&lt;br /&gt;
&lt;br /&gt;
  apt-get update&lt;br /&gt;
  apt-get install make git python tox libmysqlclient-dev&lt;br /&gt;
  git clone https://osm.etsi.org/gerrit/osm/openvim&lt;br /&gt;
  git -C openvim checkout 005a9dc  # this is temporal, because last version contains error at Makefile&lt;br /&gt;
  make -C openvim lite&lt;br /&gt;
  # Use this line to check if it is installed and where  &lt;br /&gt;
  python -c &#039;import lib_osm_openvim; print lib_osm_openvim.__path__[0]&#039;&lt;br /&gt;
  # Install database of ovim library&lt;br /&gt;
  OSMLIBOVIM_PATH=`python -c &#039;import lib_osm_openvim; print lib_osm_openvim.__path__[0]&#039;`&lt;br /&gt;
  # -U and -P are the admin database user/password. Normally &amp;quot;-U root&amp;quot; without password &amp;quot;executed as root&amp;quot;&lt;br /&gt;
  ${OSMLIBOVIM_PATH}/database_utils/install-db-server.sh -U root [-P passwd] -u mano -p manopw -d mano_vim_db --updatedb&lt;br /&gt;
&lt;br /&gt;
==CLI client==&lt;br /&gt;
&lt;br /&gt;
The RO code contains a python CLI (openmano) that allows friently command execution. This CLI client can run on a separate machine where openmano server is running. &amp;quot;openmano config&amp;quot; indicates where the server is (by default localhost)&lt;br /&gt;
&lt;br /&gt;
==Northbound Interface==&lt;br /&gt;
&lt;br /&gt;
The RO uses a REST API with YAML/JSON content. The primitives are explained [[RO Northbound Interface|here]]&lt;br /&gt;
&lt;br /&gt;
==Running Unit Tests==&lt;br /&gt;
&lt;br /&gt;
===Launching RO===&lt;br /&gt;
Openmano can run as systemd service. (Can be installed with &#039;&#039;&#039;./scripts/install-openmano-service.sh -f RO&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
Or can be run inside a screen (the prefered method for developpers). The script to easily launch/remove is &#039;&#039;&#039;./scripts/service-openmano.sh&#039;&#039;&#039;. Execute with -h to see options&lt;br /&gt;
&lt;br /&gt;
Note that the general OSM install script, installs openmano inside a container and code run at folder /opt/openmano (instead of $HOME/openmano)&lt;br /&gt;
&lt;br /&gt;
===Tests===&lt;br /&gt;
Many of openmano operations rely on an external VIM. Without external infraestructure it is recomended to use openvim in &amp;quot;test&amp;quot; (fake) mode. Install it in the same machine where openmano is located with [[OpenVIM_installation_(Release_One)#Installation]]&lt;br /&gt;
&lt;br /&gt;
Run &#039;&#039;./test/basictest&#039;&#039; for a initial test. Type -h to see options. For testing using openvim just run &amp;lt;pre&amp;gt; . ./test/basictest.sh --force --screen --init-openvim &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating a new VIM plugin==&lt;br /&gt;
&lt;br /&gt;
Choose a name, eg. XXX&lt;br /&gt;
&lt;br /&gt;
Create a new python module vimconn_XXX.py derived from vimconn.py class. Implement the relevant functions. You have several connectors already created to be used as example as openstack and openvim. Openstack connector uses the python openstack client libraries, meanwhile openvim connector uses direct http requests.&lt;br /&gt;
&lt;br /&gt;
DO NOT change the method names, parameters or parameter content. Openmano use the same methods for all the VIMs and they cannot be changed to accomodate VIM specifics. VIM specifics must be solved inside the connector.&lt;br /&gt;
&lt;br /&gt;
The new module can need specific configuration for the VIM that it is passed as a dictionary in the &#039;&#039;config&#039;&#039; variable at constructor. For example, in the case of openstack, &#039;&#039;config&#039;&#039; variable is used for: enabling/disabling port_security_enable, specifying the name of the physical network used for dataplane, regions, etc. The &#039;&#039;config&#039;&#039; variable is the right place to specify those needed parameters not provided by openmano at the methods that form part of the VIM configuration. See [[Openstack configuration (Release TWO)#Add openstack toOSM]] and [[Configuring AWS for OSM Release TWO#Add AWS to OSM]] for examples &lt;br /&gt;
&lt;br /&gt;
Integration with the main project is automatic, just create a new datacenter of type XXX and this module will be automatically loaded. No other module of the main program need to be updated.&lt;br /&gt;
&lt;br /&gt;
    openmano tenant-create osm  # if not already done&lt;br /&gt;
    export OPENMANO_TENANT=osm&lt;br /&gt;
    openmano datacenter-create &amp;lt;vim-name&amp;gt; &amp;lt;access-URL&amp;gt;  --type=XXX --config &amp;lt;specific config&amp;gt;&lt;br /&gt;
    # if fails the cause can be a librery you need not installed or an error upon importing. Try tho import it in a python client&lt;br /&gt;
    # example of &amp;lt;specific config&amp;gt; text: &amp;quot;{dataplane_physical_net: physnet_sriov, port_security_enabled: False}&amp;quot;&lt;br /&gt;
    openmano datacenter-attach &amp;lt;vim-name&amp;gt; --vim-tenant-name=&amp;lt;tenant-to-use-by-openmano&amp;gt; --user=&amp;lt;tenant-user&amp;gt; --password=&amp;lt;tenant-password&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can test it using the &#039;&#039;&#039;test/test_RO.py&#039;&#039;&#039; file:&lt;br /&gt;
    # Create manually an image &amp;lt;image&amp;gt; and a management network &amp;lt;net-mgmt&amp;gt; at your VIM&lt;br /&gt;
    ./test/test_RO.py deploy --help&lt;br /&gt;
    # e.g. ./test/test_RO.py deploy -n &amp;lt;net-mgmt&amp;gt; -t osm -i &amp;lt;image&amp;gt; -d &amp;lt;vim-name&amp;gt; --timeout=30 --test simple_linux,simple_multi_vnfc,simple_2_vnf&lt;br /&gt;
    ./test/test_RO.py vimconn --help&lt;/div&gt;</summary>
		<author><name>Cardosoi</name></author>
	</entry>
</feed>