Creating your own VNF charm (Release FIVE): Difference between revisions

From OSM Public Wiki
Jump to: navigation, search
No edit summary
No edit summary
 
Line 10: Line 10:
===Types of charm===
===Types of charm===


There are three types of charms: proxy, machine, and Kubernetes.
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====
====Proxy Charm====


OSM supports a limited version of charms that we call "proxy charms". These charms is responsible for doing Day 1 configuration. Configurations are mapped to [https://jujucharms.com/docs/stable/actions Juju Actions] which manage configuration within the VNFD qcow2 image (over SSH, via RESTful API, etc).
The diagram below illustrates the OSM proxy charm workflow:
 
<nowiki>
+---------------------+    +---------------------+
|                    <----+                    |
|  Resource          |    | Lightweight        |
|  Orchestrator (RO)  +----> Management (LCM)    |
|                    |    |                    |
+------------------+--+    +-------+----^--------+
                    |              |    |
                    |              |    |
                    |              |    |
              +-----v-----+      +-v----+--+
              |          <-------+        |
              |  Virtual  |      |  Proxy  |
              |  Machine  |      |  Charm  |
              |          +------->        |
              +-----------+      +---------+
</nowiki>
 
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====


The diagram below illustrates the OSM workflow:
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:


  <nowiki>
  <nowiki>
+---------------------+    +---------------------+
+---------------------+    +---------------------+
|                    <----+                    |
|                    <----+                    |
|  Resource          |    | Service            |
|  Resource          |    | Lightweight        |
|  Orchestrator (RO)  +----> Orchestrator (SO) |
|  Orchestrator (RO)  +----> Management (LCM)   |
|                    |    |                    |
|                    |    |                    |
+------------------+--+    +-------+----^--------+
+------------------+--+    +-------+----^--------+
Line 28: Line 54:
                   |              |    |
                   |              |    |
                   |              |    |
                   |              |    |
             +-----v-----+       +-v----+--+
             +-----v-----+         |    |
             |          <-------+         |
             |          |         |    |
             |  Virtual  |       | Proxy  |
             |  Virtual  |         |   |
             |  Machine  |       | Charm  |
             |  Machine  |         |   |
             |          +------->        |
            |          |        |    |
             +-----------+       +---------+
             |          |        |    |
            | +-------+ <---------+    |
            | | Charm | |              |
             | +-------+ +--------------+
            +-----------+
</nowiki>
</nowiki>


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====
===Layers===


These are the default type of charm. These charms are written to run on the same instance as the application. They handle the complete lifecycle of an application, from installation to removal.
Layers are pieces of code that encapsulate operational logic. Each layer provides specific functionality that can be utilized by other layers.


====Kubernetes Charm====
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 [https://osm.etsi.org/gitweb/?p=osm/devops.git;a=tree;f=charms;h=40e509e61920da3bb6f42b2ea403c923fc5fdbdf;hb=HEAD charms] repository.
 
Kubernetes charms are a new type of charm, beginning with Juju 2.5.
 
Support for these types of charm will be introduced with OSM Release Six. Examples of a Kubernetes charm can be found in devops/TBD, and the experimental OSM on Kubernetes installer.
 
===Layers===
 
Layers are individual components that, when combined, result in a finished product. The diagram below describes what our example ''pingpong'' charm looks like, followed by a walkthrough of how it is built. The completed charm is available in the [https://osm.etsi.org/gitweb/?p=osm/juju-charms.git;a=summary juju-charms] repository.


  <nowiki>
  <nowiki>
+------------------+
+------------------+
|                  |
|                  |
|      Layers      |
|      Layers      |
|                  |
|                  |
|  +------------+  |
|  +------------+  |
|  |            |  |
|  |            |  |
|  |   Base    |  |
|  |   simple  |  |
|  |            |  |
|  |            |  |
|  +------+-----+  |
|  +------+-----+  |
|        |        |
|        |        |
|  +------v-----+  |
|  +------v-----+  |
|  |            |  |
|  |            |  |
|  |  sshproxy  |  |            +-----------------+
|  |  sshproxy  |  |            +-----------------+
|  |            |  |            |                |
|  |            |  |            |                |
|  +------+-----+  |            |    pingpong    |
|  +------+-----+  |            |    simple      |
|        |        +------------>                |
|        |        +------------>                |
|  +------v-----+  |            |      charm      |
|  +------v-----+  |            |      charm      |
|  |            |  |            |                |
|  |            |  |            |                |
|  |  vnfproxy  |  |            +-----------------+
|  |  vnfproxy  |  |            +-----------------+
|  |            |  |
|  |            |  |
|  +------+-----+  |
|  +------+-----+  |
|        |        |
|        |        |
|  +------v-----+  |
|  +------v-----+  |
|  |            |  |
|  |            |  |
|  | pingpong  |  |
|  |   Base    |  |
|  |            |  |
|  |            |  |
|  +------------+  |
|  +------------+  |
|                  |
|                  |
+------------------+
+------------------+
</nowiki>
</nowiki>
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===
Interfaces are layers that facilitate communication between two applications. Examples of using interfaces are forthcoming.


===Actions===
===Actions===
[https://jujucharms.com/docs/stable/actions Actions], also referred to as Service Primitives, enable the operator to execute Day 1 and Day 2 configuration.


==Getting Started==
==Getting Started==


We recommend that you are running Ubuntu 16.04 or newer, using the Juju and LXD packages installed via Snap. It's also possible to  [https://docs.snapcraft.io/core/install install snapd] on other Linux distributions.
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.
 
===LXD===
 
<nowiki>
snap install lxd
# TODO: Add configuration details
</nowiki>
 
===Juju===


For charm development, it's recommended that you test your charm through Juju before attempting to onboard it as part of a VNF package. This will help you get familiar with the Juju toolset and iterate on your charm faster.
By default, the OSM installer will install and configure [[LXD_configuration_for_OSM_Release_FIVE|LXD]] and Juju for you,
 
<nowiki>
snap install juju
juju bootstrap localhost osmdev
</nowiki>


===Charm Tools===
===Charm Tools===
Line 113: Line 126:


  <nowiki>
  <nowiki>
snap install charm
snap install charm --classic
</nowiki>
</nowiki>


Line 124: Line 137:
cd $LAYER_PATH
cd $LAYER_PATH
</nowiki>
</nowiki>


==Creating a charm==
==Creating a charm==
Line 132: Line 146:


  <nowiki>
  <nowiki>
charm create pingpong
cd ~/charms/layers
cd pingpong
charm create simple
cd simple
</nowiki>
</nowiki>


Line 144: Line 159:
├── metadata.yaml
├── metadata.yaml
├── reactive
├── reactive
│   └── pingpong.py
│   └── simple.py
├── README.ex
├── README.ex
└── tests
└── tests
Line 152: Line 167:


===config.yaml===
===config.yaml===
Application-level configuration can be defined in [https://docs.jujucharms.com/2.4/en/charms-config config.yaml]. For our simple charm, extra configuration is required so you may ignore or delete this file.


===layers.yaml===
===layers.yaml===


TODO: How to find and add layers
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.


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


  <nowiki>
  <nowiki>
Line 163: Line 180:
     - layer:basic
     - layer:basic
     - layer:vnfproxy
     - layer:vnfproxy
options:
    basic:
        use_venv: false
</nowiki>
</nowiki>
You can find more layers in the [https://github.com/juju/layer-index Charm Layers Index].


===metadata.yaml===
===metadata.yaml===
Line 170: Line 193:


  <nowiki>
  <nowiki>
name: pingpong
name: simple
summary: A service to test latency between machines.
summary: A simple charm example.
maintainer: Adam Israel <adam.israel@canonical.com>
maintainer: Adam Israel <adam.israel@canonical.com>
description: |
description: |
   The pingpong charm manages the pingpong vnfd deployed by Open Source Mano.
   A simple charm to use with Open Source Mano.
tags:
  - nfv
subordinate: false
subordinate: false
series:
series:
     - trusty
     - trusty
     - xenial
     - xenial
    - bionic
</nowiki>
</nowiki>


 
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.
This means that your charm will include the basic layer, required for all charms, and the vnfproxy layer, which has been designed to aid in the development in proxy charms by implementing common functionality.


===actions.yaml===
===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/pingpong.py'' that performs said action.
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:
In ''actions.yaml'', we define the actions we wish to support:


  <nowiki>
  <nowiki>
set-server:
touch:
     description: "Set the target IP address and port"
     description: "Touch a file."
     params:
     params:
         server-ip:
         filename:
             description: "IP on which the target service is listening."
             description: "The filename to touch."
             type: string
             type: string
             default: ""
             default: ""
        server-port:
            description: "Port on which the target service is listening."
            type: integer
            default: 5555
     required:
     required:
         - server-ip
         - filename
set-rate:
    description: "Set the rate of packet generation."
    params:
        rate:
            description: "Packet rate."
            type: integer
            default: 5
get-stats:
    description: "Get the stats."
get-state:
    description: "Get the admin state of the target service."
get-rate:
    description: "Get the rate set on the target service."
get-server:
    description: "Get the target server and IP set"
</nowiki>
</nowiki>


  <nowiki>
  <nowiki>
Line 232: Line 233:
  <nowiki>
  <nowiki>


cat <<'EOF' >> actions/set-server
cat <<'EOF' >> actions/touch
#!/usr/bin/env python3
#!/usr/bin/env python3
import sys
import sys
Line 257: Line 258:


  <nowiki>
  <nowiki>
chmod +x actions/set-server
chmod +x actions/touch
</nowiki>
 
Next, copy this script for the remaining actions:
<nowiki>
cp actions/set-server actions/set-rate
cp actions/set-server actions/get-stats
cp actions/set-server actions/set-state
cp actions/set-server actions/get-rate
cp actions/set-server actions/get-server
</nowiki>
</nowiki>


The last step is to map the action to the command(s) to be run. To do this, open up reactive/pingpong.py and add this code.
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.
  <nowiki>
  <nowiki>
@when('actions.set-server')
@when('actions.touch')
def set_server():
def touch():
     err = ''
     err = ''
     try:
     try:
         cmd = ""
        filename = action_get('filename')
         cmd = ['touch {}'.format(filename)]
         result, err = charms.sshproxy._run(cmd)
         result, err = charms.sshproxy._run(cmd)
     except:
     except:
Line 282: Line 275:
         action_set({'outout': result})
         action_set({'outout': result})
     finally:
     finally:
         remove_flag('actions.set-server')
         remove_flag('actions.touch')
</nowiki>
</nowiki>


The reactive framework, coupled with the script in the ''actions/'' directory, maps the SO's invocation of the action to the block of code with the matching ''@when'' decorator. As demonstrated in the above code, it will execute a command via the ssh (configured automatically by the SO). You could replace with with calls to a REST API or any other RPC method. You can also run code against the LXD container running the charm.
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===
===Building===


Line 294: Line 287:
$ charm build
$ charm build
build: Composing into /home/stone/charms
build: Composing into /home/stone/charms
build: Destination charm directory: /home/stone/charms/builds/pingpong
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: 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:basic
build: Processing layer: layer:sshproxy
build: Processing layer: layer:sshproxy
build: Processing layer: layer:vnfproxy
build: Processing layer: layer:vnfproxy
build: Processing layer: pingpong
build: Processing layer: simple
</nowiki>
</nowiki>


This combines all layers that you included, and those that they include, into a charm called ''pingpong'', located in the ''~/charms/builds'' directory.
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:
 
<nowiki>
hackfest_simplecharm_vnf
├── charms/
│  └── simple/
├── checksums.txt
├── icons/
├── images/
├── scripts/
├── hackfest_simplecharm_vnfd.yaml
└── README
</nowiki>


===Debugging===
===Debugging===


==VNF Descriptor==
When developing a charm, there are several useful tools available to use to aid in debugging.
 
====juju debug-log====
 
The [https://docs.jujucharms.com/2.4/en/developer-debugging#the-'debug-log'-command 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 [https://docs.jujucharms.com/2.4/en/developer-debugging#the-'debug-hooks'-command 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====


In your Virtual Network Function Descriptor (VNFD), you specify the name of the charm as demonstrated below:
The source code for the simple charm layer can be found in the [https://osm.etsi.org/gitweb/?p=osm/devops.git;a=tree devops] git repository, under [https://osm.etsi.org/gitweb/?p=osm/devops.git;a=tree;f=charms/layers;h=d87b76d8b7169776ed59d6bc094b9a6eca5f2279;hb=HEAD charms/layers], along with other example charms.
<nowiki>
vnfd:vnfd-catalog:
    vnfd:vnfd:
    -  vnfd:id: rift_pong_vnf
        vnfd:name: pong_vnf
        vnfd:vnf-configuration:
            vnfd:juju:
                vnfd:charm: pingpong
</nowiki>


Then the compiled charm (from the builds directory) has to be packaged with the descriptor package under the charm directory. So the ping VNF with the charm would be:
===VNF Descriptor===


<nowiki>
Also in the devops repo, you will find many [https://osm.etsi.org/gitweb/?p=osm/devops.git;a=tree;f=descriptor-packages;h=17294792b83cdfc3d00caea2989125bedd05edbe;hb=HEAD examples of descriptors], including the [https://osm.etsi.org/gitweb/?p=osm/devops.git;a=tree;f=descriptor-packages/nsd/hackfest_simplecharm_ns;h=3ce3d0c1c427440c8980456614c0f540d2014c6f;hb=HEAD simplecharm ns] and [https://osm.etsi.org/gitweb/?p=osm/devops.git;a=tree;f=descriptor-packages/vnfd/hackfest_simplecharm_vnf;h=680b919586f9f94d89502932939280c7d02e1b26;hb=HEAD simplecharm_vnf].
ping_vnf
├── charms
│  └── pingpong
├── checksums.txt
├── icons
├── images
├── ping_vnfd.yaml
├── README
└── scripts
</nowiki>

Latest revision as of 20:08, 5 December 2018

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.