Creating your own VNF charm (Release FIVE)

From OSM Public Wiki
Revision as of 20:08, 5 December 2018 by Israelad (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

DISCLAIMER: This page is being updated to reflect changes required for Release FIVE.

What is a VNF charm

A charm is a collection of scripts and metadata that encapsulate the distilled DevOps knowledge of experts in a particular product. These charms make it easy to reliably and repeatedly deploy applications, then scale them as required with minimal effort.

Driven by Juju, these charms manage the complete lifecycle of the application, including installation, configuration, clustering, and scaling.

Types of charm

There are two types of charms supported in Release 5: proxy and machine. Proxy charms are appropriate when working with physical devices, such as a switch, or virtualized appliances, running in a VM. Machine charms work best with software that can be installed and run on top of a traditional operating system, such as Ubuntu Linux.

The primary difference between them is that a proxy charm operates remotely against a VNF, typically using SSH, while a machine charm runs on the same machine as the VNF and interacts with it directly.

Proxy Charm

The diagram below illustrates the OSM proxy charm workflow:

 +---------------------+    +---------------------+
 |                     <----+                     |
 |  Resource           |    | Lightweight         |
 |  Orchestrator (RO)  +----> Management (LCM)    |
 |                     |    |                     |
 +------------------+--+    +-------+----^--------+
                    |               |    |
                    |               |    |
                    |               |    |
              +-----v-----+       +-v----+--+
              |           <-------+         |
              |  Virtual  |       |  Proxy  |
              |  Machine  |       |  Charm  |
              |           +------->         |
              +-----------+       +---------+

The SO directs the RO to create a virtual machine using the selected VNF image. When that has successfully completed, the SO will instantiate a LXD container, managed by Juju, with the proxy charm. The proxy charm will then communicate with the VNF virtual machine to do Day 1 configuration.

Machine Charm

Machine (or Native) charms are written to run on the same machine as the application. They handle the complete lifecycle of an application, from installation to removal.

Here is the OSM machine charm workflow:

+---------------------+    +---------------------+
|                     <----+                     |
|  Resource           |    | Lightweight         |
|  Orchestrator (RO)  +----> Management (LCM)    |
|                     |    |                     |
+------------------+--+    +-------+----^--------+
                   |               |    |
                   |               |    |
                   |               |    |
             +-----v-----+         |    |
             |           |         |    |
             |  Virtual  |         |    |
             |  Machine  |         |    |
             |           |         |    |
             |           |         |    |
             | +-------+ <---------+    |
             | | Charm | |              |
             | +-------+ +--------------+
             +-----------+


Layers

Layers are pieces of code that encapsulate operational logic. Each layer provides specific functionality that can be utilized by other layers.

The diagram below illustrates the layers used by our simple charm, followed by a walkthrough of how it is built. The layer is available in the devops charms repository.

 +------------------+
 |                  |
 |      Layers      |
 |                  |
 |  +------------+  |
 |  |            |  |
 |  |   simple   |  |
 |  |            |  |
 |  +------+-----+  |
 |         |        |
 |  +------v-----+  |
 |  |            |  |
 |  |  sshproxy  |  |            +-----------------+
 |  |            |  |            |                 |
 |  +------+-----+  |            |     simple      |
 |         |        +------------>                 |
 |  +------v-----+  |            |      charm      |
 |  |            |  |            |                 |
 |  |  vnfproxy  |  |            +-----------------+
 |  |            |  |
 |  +------+-----+  |
 |         |        |
 |  +------v-----+  |
 |  |            |  |
 |  |    Base    |  |
 |  |            |  |
 |  +------------+  |
 |                  |
 +------------------+

When we are ready, we will use the charm build command to flatten these layers into a charm, which can then be onboarded into OSM.

Interfaces

Interfaces are layers that facilitate communication between two applications. Examples of using interfaces are forthcoming.

Actions

Actions, also referred to as Service Primitives, enable the operator to execute Day 1 and Day 2 configuration.

Getting Started

We recommend that you are running Ubuntu 16.04 or newer, using the Juju and LXD packages installed via Snap, and the latest release of OSM.

By default, the OSM installer will install and configure LXD and Juju for you,

Charm Tools

Install the charm snap, which provides the charm command and libraries necessary to compile your charm:

snap install charm --classic

Setup your workspace for writing layers and building charms:

mkdir -p ~/charms/layers
export JUJU_REPOSITORY=~/charms
export LAYER_PATH=$JUJU_REPOSITORY/layers
cd $LAYER_PATH


Creating a charm

Create your charm layer

Create the layer for your proxy charm:

cd ~/charms/layers
charm create simple
cd simple

This will create a charm layer ready for customization:

.
├── config.yaml
├── icon.svg
├── layer.yaml
├── metadata.yaml
├── reactive
│   └── simple.py
├── README.ex
└── tests
    ├── 00-setup
    └── 10-deploy

config.yaml

Application-level configuration can be defined in config.yaml. For our simple charm, extra configuration is required so you may ignore or delete this file.

layers.yaml

We define the layers required for our charm in layers.yaml. Modify the file as shown below. This will include the vnfproxy layer, which adds standard primitives that OSM can execute. We'll also set the use_venv option of layer:basic.

Note: We don't need to explicitly include the sshproxy layer, because it is included by the vnfproxy layer.

includes:
    - layer:basic
    - layer:vnfproxy
options:
    basic:
        use_venv: false


You can find more layers in the Charm Layers Index.

metadata.yaml

The metadata.yaml file describes what your charm is and sets certain properties used by Juju.

name: simple
summary: A simple charm example.
maintainer: Adam Israel <adam.israel@canonical.com>
description: |
  A simple charm to use with Open Source Mano.
subordinate: false
series:
    - trusty
    - xenial
    - bionic

The metadata provides OSM and Juju with basic details about your charm. The series key informs Juju of what series of Ubuntu the charm can be deployed to.

actions.yaml

There are three pieces that make up an action: actions.yaml, which define an action, the actions/ directory where we'll place a small script that invokes the reactive framework, and the python code in reactive/simple.py that executes the action.

In actions.yaml, we define the actions we wish to support:

touch:
    description: "Touch a file."
    params:
        filename:
            description: "The filename to touch."
            type: string
            default: ""
    required:
        - filename

mkdir actions/

For each action, we need to create a script to invoke the reactive framework. This is a boilerplate script that will be used for every action. The first step is to create the first action script.


cat <<'EOF' >> actions/touch
#!/usr/bin/env python3
import sys
sys.path.append('lib')

from charms.reactive import main
from charms.reactive import set_state
from charmhelpers.core.hookenv import action_fail, action_name

"""
`set_state` only works here because it's flushed to disk inside the `main()`
loop. remove_state will need to be called inside the action method.
"""
set_state('actions.{}'.format(action_name()))

try:
    main()
except Exception as e:
    action_fail(repr(e))
EOF

After this, make the file executable.

chmod +x actions/touch

The last step is to map the action to the command(s) to be run. To do this, open up reactive/simple.py and add this code.

@when('actions.touch')
def touch():
    err = ''
    try:
        filename = action_get('filename')
        cmd = ['touch {}'.format(filename)]
        result, err = charms.sshproxy._run(cmd)
    except:
        action_fail('command failed:' + err)
    else:
        action_set({'outout': result})
    finally:
        remove_flag('actions.touch')

When the touch primitive is invoked, it will execute the actions/touch script, which will run the code in reactive/simple.py that uses the matching @when decorator.

Building

When you're ready, you can create your charm via the charm build command:

$ charm build
build: Composing into /home/stone/charms
build: Destination charm directory: /home/stone/charms/builds/simple
build: Please add a `repo` key to your layer.yaml, with a url from which your layer can be cloned.
build: Processing layer: layer:basic
build: Processing layer: layer:sshproxy
build: Processing layer: layer:vnfproxy
build: Processing layer: simple

This combines all layers that you included, and those that they include, into a charm called simple, located in the ~/charms/builds directory.

Now, you can copy the simple charm from your builds directory into the charms folder inside your VNF package:

hackfest_simplecharm_vnf
├── charms/
│   └── simple/
├── checksums.txt
├── icons/
├── images/
├── scripts/
├── hackfest_simplecharm_vnfd.yaml
└── README

Debugging

When developing a charm, there are several useful tools available to use to aid in debugging.

juju debug-log

The juju debug-log command allows you to view the Juju log stream in real time. This will show you the inner workings of Juju and any logs sent from the charm, including unhandled errors.

juju debug-hooks

The juju debug-hooks command allows you to intercept lifecycle events and actions before or during their execution by opening a tmux session in the container running the charm.

The initial tmux window does nothing but keep the session alive. When an event is queued, Juju will open a new window in the tmux session in a hook context.

From here, you can manually execute the hook or action.

You can also make to make changes to the deployed charm, such as adding import pdb; pdb.set_trace() to set a break point where you would like to use the Python debugger to examine the code at runtime.

Note: Changes made to a charm during a debug-hooks session are ephemeral, so be sure to replicate any fixes to your charm layer, rebuild the charm, and update the VNF package.

Source

Simple charm

The source code for the simple charm layer can be found in the devops git repository, under charms/layers, along with other example charms.

VNF Descriptor

Also in the devops repo, you will find many examples of descriptors, including the simplecharm ns and simplecharm_vnf.