diff --git a/03-developer-how-to-for-modules.md b/03-developer-how-to-for-modules.md index 58b7d1142c11afc5b9ab1ce0905f890193c73c06..674ec7834083fb5b3a57d914f3f35569b5006f2c 100644 --- a/03-developer-how-to-for-modules.md +++ b/03-developer-how-to-for-modules.md @@ -114,200 +114,173 @@ RIGHT: The code organized into the following high level directories: -- **RO/** main RO server engine - - **`RO/osm_ro/`** contains the RO server code files - - **`RO/test/`** contains scripts and code for testing - - **`RO/database_utils/`** contains scripts for database creation, dumping and migration - - **`RO/scripts/`** general scripts, as installation, execution, reporting - - **`RO/scenarios/`** examples and templates of network scenario descriptors - - **`RO/vnfs/`** examples and templates of VNF descriptors -- **RO-client/** contains the own RO client CLI +- **RO-plugin/** contains base classes for VIM and SDN plugins and dummy plugins +- **NG-RO/** the new generation RO is the main server engine - **RO-SDN-*/** contains the SDN plugins - **RO-VIM-*/** contains the VIM plugins +- **RO/** (Deprecated) old RO server engine. +- **RO-client/** (Deprecated) contains the own RO client CLI ### RO Architecture -![OpenmanoArchitecture.png](assets/400px-OpenmanoArchitecture.png) +![NG-RO-Architecture.png](assets/400px-NGROArchitecture.png) + +#### NG-RO Server modules + +The NG-RO module contains the following modules + +**ro_main.py** Starting point. Load configuration from ro.cfg file and overrides with ENV with the format "OSMRO_XXX_YYY". Receives http requests and calls ns.py methods. The accepted URLs are: + +- /ro/version + - GET: To get the version +- /ro/ns/v1/deploy + - GET: just to get list of Network Services (debugging) +- /ro/ns/v1/deploy/(nsrs_id) + - POST: To create a NS action, that is an modification of the current deployment + - GET: Return the list of actions registered over this NS + - DELETE: Removes all the database entries for this NS +- /ro/ns/v1/deploy/(nsrs_id)/(action_id) + - GET: Obtain status over an action or incremental deployment + +An example of the content for creating a NS action is the following: + +```yaml +action_id: proposed id for the action. Normally equals to nscmop_id. RO will append a suffix if already present, to have it unique. +cloud_init_content: {'(vnfr_id):file:cloud-init.cfg': cloud_init_text} +flavor: + - id: '0' # unique in this list + guest-epa: {'cpu-pinning-policy': 'DEDICATED', 'cpu-thread-pinning-policy': 'PREFER', 'mempage-size': 'LARGE', 'numa-node-policy': {'mem-policy': 'STRICT', 'node-cnt': 1}} + name: 'ubuntu_cloudinit-vnf-VM-flv' + storage-gb: 10 + vim_info: {'vim:a9adcb0b-ae70-4e09-9b40-e78b94655829': {}} +image: + - id: '0' # unique in this list + image: ubuntu16.04 + vim_info': {'vim:a9adcb0b-ae70-4e09-9b40-e78b94655829': {}} +name: 'NS_NAME' +ns: + vld: + - id: 'mgmtnet' + mgmt-network: True + name: mgmtnet + vim_info: # vims/sdnc where this vld must be deployed, and parameters for creation + vim:a9adcb0b-ae70-4e09-9b40-e78b94655829: + vim_network_name: 'internal' # look for a network with this name + vnf: # vnfs to deploy + - id: 2434c189-7569-4cad-8bf4-67b2e6bbe4b7 # vnf record id + additionalParamsForVnf: {} # parameters used for jinja2 cloud init + member-vnf-index-ref: '1' + vld: + - id: internal vld_id + vim_info: {vim:a9adcb0b-ae70-4e09-9b40-e78b94655829: {}} + vdur: + - id: ebac7ccb-82f0-49e1-b81a-c03760b6cc58 + additionalParams: # parameters used for jinja2 cloud init + cloud-init': e015e1ef-86ad-4daf-8b42-603c97e6127b:file:cloud-init.cfg # must be at cloud_init_content + count-index: 0 # every instance will have a separate vdur entry + ns-flavor-id: '0' # must exist at flavor.id + ns-image-id: '0' # must exist at image.id + ssh-keys: list of ssh-keys to inject with cloud-init + vim_info: {'vim:a9adcb0b-ae70-4e09-9b40-e78b94655829': {}} + interfaces: + - mgmt-interface: True + mgmt-vnf: True + name: eth0 + ns-vld-id: mgmtnet # connect to ns vld. This id must exist at ns.vld.id or... + vnf-vld-id: mgmtnet # connect to vnf vld. This id must exist at ns.vnf.vld.id -#### RO Server modules - -The RO module contains the following modules - -- **`openmanod.py`** is the main program. It reads the configuration file (`openmanod.cfg`) and execute `httpserver` and wait for the end -- **`httpserver.py`** is a thread that implements the northbound API interface, uses python bottle module. Calls main engine methods to perform the tasks -- **`nfvo.py`** 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 -- **`nfvo_db.py`** is the module in charge of database operations. Uses base **`db_base.py`**. Database is managed with MySQLdb python library -- **`openmano_schemas.py`** is a dictionary schemas used to validate API request and response content using jsonschema library -- **`vim_thread.py`** 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 -- **`vimconn.py`** is the base class for the VIM plugin. It contains the definition of the methods to be implemented. The inherited - **`console_proxy_thread.py`** is a thread that implements a TCP/IP proxy for the console access to ## a VIM. - -#### RO Client modules - -Other modules not part of the server are: - -- **`roclient.py`** is a CLI client - -#### ACTIONS and TASKS - -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 "Action_id" 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, ... - -#### Database content - -TODO: add details on DB content - -### Database changes +``` -Database schema can be changed if needed. It is recommended to use a graphical tool (e.g. Heidy) to change database and change it back and copy the SQL commands. Make these steps: +**ns.py** Main engine. Compute the requests. Main methods are: -1. `RO/osm_ro/openmanod.py`: increment `__version__`, `version_date` and `database_version` -2. `RO/osm_ro/database_utils/migrate_mano_db.sh`. See the three "TODO" - - 2a. Increment `LAST_DB_VERSION` - - 2b. Annotate a comment to have a track of versions: `[ $OPENMANO_VER_NUM -ge 50XX ] && DB_VERSION=XX #0.5.XX => XX` - - 2c. 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. +- method deploy: Used for create/delete/modify a NS. It computes differences between current deployment (read from database nsrs and vnfrs) and target deployment in the body of the http requests. It create tasks (database ro_tasks) to accomplish target. Same method is used for a new instantiation, scale or termination (empty target). An action id can be provided (normally equal to the nslcmop_id). Otherwise a new id is created an returned for later polling. +- method status: get status of a previously created action. The action_id must be supplied +- method delete: remove database entries for a NS when no longer is needed. Used when NS is deleted +This module also manages the creation of ns_threads and track the VIMs/SDNCs/WIMs that they are processing -Test several upgrades/downgrades to version 20 with `migrate_mano_db.sh` and `migrate_mano_db.sh 20` +**ns_thread.py** Manage and perform all the ro_tasks of one, or several VIM/SDNC/WIM +Each one has a queue to receive orders: -### Package dependency osm-im +- `load_vim`/`reload_vim`: to load or reload a VIM/SDNC/WIM and start processing ro_tasks of this element +- `check_vim`: Load if needed a VIM/SDNC/WIM, check connectivity and credentials and update its status on database +- `unload_vim`. Stop processing ro_tasks of this VIM/SDNC/WIM +- `terminate`: finish thread -It is under IM repository. It contains the OSM models. Used models at RO are under `/models/yang/vnfd.yang` and `/models/yang/nsd.yang`. More modules will be incorporated in the future. +Apart from reading this queue, its main work is reading and processing pending ro_tasks. It performs a lock/unlock writing in a key `locked_at` for HA exclusiveness processing: -When IM is built, `pyangbind` generates python source files imported at RO. They are used to validate and load a yaml/json VNFD and NSD catalog descriptor. +- Looks for ro_tasks where `to_check_at` less than current time, `target_id` one of its vim list, `locked_at` less than current time minus LOCKED_TIME +- Locks it by writing at `locked_at` current time. If fails abandon this ro_task +- Processes all the tasks. Classes `VimInteraction` are used for that. Then updates database (`target_record`) with the result +- Updates and unlock ro_task (by setting `locked_at` with current time minus LOCKED_TIME) -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 `/osm_ro/nfvo.py` methods `new_vnfd_v3` and `new_nsd_v3`. RO supports backwards compatibility with old format descriptors. NBI (`osm_ro/httpserver.py`) uses `.../v3/...` at URL to differentiate 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 "v3" URL +**vim_admin.py** +Read kafka topics for VIM/SDNCs/WIM (broadcast mode over all RO workers) and order to load/check/unload. +Detect unattended ro_tasks (among others because a crass of a previos RO worker) and order to load this VIM/SDNC/WIM to start processing these ro_tasks (done by `vim_watcher` method) -#### Installation +**html_out.py** Just to serve a developer simple UI +**validation.py** Contain jsonschema to validate input content of http -The OSM binary installation install this package. In case of needed you can install/update it manually by: +#### Database content -```bash -apt-get update -apt-get install make git python python-pip tox debhelper python-bitarray python-lxml -python3 -m pip install --upgrade pip -# If not inside a container. Use "sudo -HE" to get root privileges for pip installation -git clone https://osm.etsi.org/gerrit/osm/IM -python3 -m install -e IM -# Use this line to check if it is installed and where -python3 -c 'import osm_im; print osm_im.__path__[0]' +NG-RO manages two collection over a non relational database +**ro_tasks** +There is a ro_task entry per element in a VIM/SDNC/WIM (a network, flavor, image, VM). It contains a list of tasks. A task is an action as CREATE (find with filter or create with params), EXEC (e.g. inject a key) or DELETE. Each task contains the target (NS,VNFRS) with path where the status must be updated upon completion. Stored internal plugin information used by itself for later deletion + + +```yaml + _id: unique id + locked_by: just for debugging + locked_at: Time (with up to 6 decimals) when this is locked. After some time it is considered unlocked automatically. In case locked crashes + target_id: has the format "vim:vim_id", "sdn:sdnc_id" or "wim:wim_id" + vim_info: # object with vim_information needed to maintain and delete: + created: False, If the item has been created by OSM and then need to be deleted + created_items: extra information returned by plugins and used by them to delete + vim_id: internal VIM id + vim_name: internal VIM name + vim_status: internal VIM status + vim_details: text with error message + refresh_at: when this information needs to be refreshed + modified_at: when it has been modified + created_at: when it has been created + to_check_at: when it needs to be processed/refreshed + tasks: # list with + - action_id: all tasks has one action id, normally the nslcmop_id; instantiate, scale, terminate + nsr_id: NS id where this task belong. + task_id: action_id:task_index + status: SCHEDULED, DONE, ERROR + action: CREATE, EXEC, DELETE + item: vdu, net, flavor, image, sdn-net + target_record: nsrs::path.to.entry.to.update or vnfrs::path.to,update + target_record_id: The identity of the element with the format nsrs::path.id + common_id: used to indentify the same element for different NS. Used for common netslice VLDs for different NSs ``` -### CLI client - -The RO code contains a python CLI (openmano) that allows friendly command execution. This CLI client can run on a separate machine where openmano server is running. `openmano config` indicates where the ## server is (by default `localhost`). - -### Northbound Interface - -The RO uses a REST API with YAML/JSON content. The primitives are explained [here]## (16-ro-northbound-rest-api.md) - -### Running Unit Tests +Note that same ro_task can contain tasks for several NS. It can contains also several "CREATE" tasks, each one with different target_record (place where to update the result) -#### Launching RO +**ro_nsrs** +This is used to store important internal information over a NS. In current version it stores the private an public ssh-key (one different per NS) used to inject keys to the VM. Public key is injected using cloud-init. Other keys are injected using the private key. -RO can run as `systemd` service. (Can be installed with `./scripts/install-openmano-service.sh -f RO`). - -Or can be run inside a screen (the preferred method for developers). The script to easily launch/remove is `./scripts/service-openmano.sh`. Execute with `-h` to see options. - -Note that the general OSM install script, installs openmano inside a container and code run at folder `/opt/openmano` (instead of `$HOME/openmano`). +```yaml +public_key: public_ssh_key +private_key: private_ssh_key_encrypted +actions: [] # list of ids for every action. Used to avoid duplications +``` #### Tests -Many of RO operations rely on an external VIM. Without external infrastructure it is recommended to use openvim in "test" (fake) mode. Install it in the same machine where openmano is located with [OpenVIM_installation_(Release_One)#Installation](10-00-openvim-install.md#installation) - -Run; - -```bash -. ./test/basictest.sh --force --screen --init-openvim -``` +There are dummy VIMs and dummy SDN that can be used for system tests without needed facilities ### Creating a new VIM plugin Choose a name, eg. XXX -Create a new plugin folder RO-VIM-XXX. Copy one of the existing, there are 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. Create a class derived from vimconn.py. Implement the relevant functions. +Create a new plugin folder RO-VIM-XXX. Copy one of the existing, there are several connectors already created to be used as example as openstack. Create a class derived from vimconn.py. Implement the relevant functions. DO NOT change the method names, parameters or parameter content. RO uses the same methods for all the VIMs and they cannot be changed to accommodate VIM specifics. VIM specifics must be solved inside the connector. The new module can need specific configuration for the VIM that it is passed as a dictionary in the *config* variable at constructor. For example, in the case of openstack, `config` variable is used for: enabling/disabling port_security_enable, specifying the name of the physical network used for dataplane, regions, etc. The `config` variable is the right place to specify those needed parameters not provided by RO at the methods that form part of the VIM configuration. See [Openstack configuration#Add openstack to OSM](05-02-openstack-configuration.md#add-openstack-to-osm) and [Configuring AWS for OSM Release TWO#Add AWS to OSM](12-aws-configuration.md#add-aws-to-osm) for examples. -```bash -openmano tenant-create osm # if not already done -export OPENMANO_TENANT=osm -openmano datacenter-create --type=XXX --config -# if fails the cause can be a library you need not installed or an error upon importing. Try tho import it in a python client -# example of text: "{dataplane_physical_net: physnet_sriov, port_security_enabled: False}" -openmano datacenter-attach --vim-tenant-name= --user= --password= -``` - -You can test it using the `test/test_RO.py` file: - -```bash -# Create manually an image and a management network at your VIM -./test/test_RO.py deploy --help -# e.g. ./test/test_RO.py deploy -n -t osm -i -d --timeout=30 --test simple_linux,simple_multi_vnfc,simple_2_vnf -./test/test_RO.py vimconn --help -``` - -To be able to run the `test/test_RO.py` script, you need to do some changes. First in the class `vim_connector` you need to import the plugin of the new vim: - -```python -def test_vimconnector(args): - global test_config - sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + "/osm_ro") - test_config['vimtype'] = args.vimtype - if args.vimtype == "aws": - import vimconn_aws as vim -``` - -And also,some tests are depending on the vim, you you would need to look for the following chain: `'test_config['vimtype'] =='` and place the code for the call to your vim there. For instance: - -```python - def test_000_connect(self): - self.__class__.test_text = "{}.{}. TEST {}".format(test_config["test_number"], - self.__class__.test_index, - inspect.currentframe().f_code.co_name) - - self.__class__.test_index += 1 - if test_config['vimtype'] == 'vmware': - vca_object = test_config["vim_conn"].connect() - logger.debug("{}".format(vca_object)) - self.assertIsNotNone(vca_object) - elif test_config['vimtype'] == 'openstack': - test_config["vim_conn"]._reload_connection() - network_list = test_config["vim_conn"].get_network_list() - logger.debug("{}".format(network_list)) - self.assertIsNotNone(network_list) -``` - -The script could be used to launch tests against the vim connector directly with the following syntax: - -```bash -python ./test/test_RO.py vimconn --vimtype XXX -t -u -c '{user: , passwd: }' --test -``` - -Next you can find the tests that could be executed: - -```bash -test_vimconn_connect -test_vimconn_delete_network -test_vimconn_get_image_list -test_vimconn_get_network -test_vimconn_new_flavor -test_vimconn_new_network -test_vimconn_new_vminstance -``` - -Also, the script could be used to launch tests against the RO with the following syntax: - -```bash -python ./test/test_RO.py deploy -d -n -i --tests -``` - -Next you can find the tests that could be executed: - -```bash -v3_2vdu_set_ip_mac -simple_multi_vnfc -simple_linux -``` +Create methods must return a unique ´id´ and it can return an object with extra information that will be available at deleteion method. The content is VIM dependent, It admit nested dictionaries, but never use a forbidden mongo character (start with '$' or contains '.' in any key) ### Creating a new SDN/WIM plugin diff --git a/assets/400px-NGROArchitecture.png b/assets/400px-NGROArchitecture.png new file mode 100644 index 0000000000000000000000000000000000000000..0ef4bf5b4512369291820a10c37c3eb4885c198e Binary files /dev/null and b/assets/400px-NGROArchitecture.png differ diff --git a/assets/400px-OpenmanoArchitecture.png b/assets/400px-OpenmanoArchitecture.png deleted file mode 100644 index f18ed93c44e88515bd28e67bbe1a746da200358b..0000000000000000000000000000000000000000 Binary files a/assets/400px-OpenmanoArchitecture.png and /dev/null differ