# VNF Onboarding Walkthrough

**NOTE: this section uses pre-SOL006 descriptors which need to be converted before trying in Release 9+**

## Introduction

This section uses NextEPC (an open-source implementation of a 4G/5G packet core) to go through most of the steps described in the onboarding guidelines, in order to provide a concrete example on how to build a complete VNF Package from scratch.

The example is meant to be used for educational purposes and not for a real-life implementation of an EPC. It may change over time to cover more use cases. A Linux machine is required to follow the complete procedure.
In addition to the procedure, here you can find some resources related to it:

- [Resulting packages](https://osm-download.etsi.org/ftp/Packages/vnf-onboarding-tf/)
- [Images](https://osm-download.etsi.org/ftp/images/vnf-onboarding-tf/)
- [Video presentation](https://youtu.be/hZzwwy9wNRE)

## VNF Requirements

### Day-0 Requirements

The following table describes the components description and associated images.

|   VDU   | Description                            |                                                  Image name                                                   |
| :-----: | :------------------------------------- | :-----------------------------------------------------------------------------------------------------------: |
| spgwmme | Single VDU containing SGW, PGW and MME | [nextepc-spgwmme-base](https://osm-download.etsi.org/ftp/images/vnf-onboarding-tf/nextepc-spgwmme-base.qcow2) |
|   hss   | HSS VDU                                |     [nextepc-hss-base](https://osm-download.etsi.org/ftp/images/vnf-onboarding-tf/nextepc-hss-base.qcow2)     |

And here the NFVI requirements (for this example, as the VNF has no strict requirements)

|   VDU   | vCPU | RAM (GB) | Storage (GB) | EPA Features                              |
| :-----: | :--: | :------: | :----------: | :---------------------------------------- |
| spgwmme |  2   |    4     |      10      | CPU Pinning, Huge Pages & SRIOV in S1/SGI |
|   hss   |  1   |    2     |      10      | -                                         |

The topology of the VNF would be as follows:

![](assets/vnfonbtf_samplevnf_1.png)

Finally, we will use cloud-init files to set a hostname and password (just as example, since OSM VCA supports SSH key authentication).
The password will be kept as a variable, so it can be passed at instantiation time.

```
#cloud-config
hostname: nextepc-hss
password: {{ password }}
chpasswd: { expire: False }
ssh_pwauth: True
```

```
#cloud-config
hostname: nextepc-spgw
password: {{ password }}
chpasswd: { expire: False }
ssh_pwauth: True
```

### Day-1 Requirements

For this sample VNF, we will assume that establishing the session between the MME and HSS, and starting the main services, is enough to consider that the EPC is ready to start serving subscribers. This VNF does not expose an API, so we will configure it with Linux commands through SSH.

SPGW-MME Day-1 operations include:

- Enabling its 3 additional interfaces:

```
sudo ip link set ens4 up && sudo dhclient ens4
sudo ip link set ens5 up && sudo dhclient ens5
sudo ip link set ens6 up && sudo dhclient ens6
```

- Replacing the HSS and SPGW IP addresses in the configuration file of the MME component. We will need to pass both IP addresses as instantiation parameters (as of OSM Release 6.0.2, there is no automatic detection of non-management IP addressing)

```
sudo sed -i 's/$hss_ip/HSS_IP/g' /etc/nextepc/freeDiameter/mme.conf
sudo sed -i 's/$spgw_ip/SPGW_IP/g' /etc/nextepc/freeDiameter/mme.conf
```

- Restarting the MME daemon

```
sudo systemctl restart nextepc-mmed
```

HSS Day-1 operations include:

- Enabling its additional interface:

```
sudo ip link set ens4 up && sudo dhclient ens4
```

- Replacing the HSS and SPGW IP addresses in the configuration file of the HSS component. We will need to pass both IP addresses as instantiation parameters as well.

```
sudo sed -i 's/$hss_ip/HSS_IP/g' /etc/nextepc/freeDiameter/hss.conf
sudo sed -i 's/$spgw_ip/SPGW_IP/g' /etc/nextepc/freeDiameter/hss.conf
```

- Restarting the HSS daemon

```
sudo systemctl restart nextepc-hssd
```

### Day-2 Requirements

For day-2 operations, we will enable the possibility of reconfiguring and monitoring the SPGW.

- SPGW reconfiguration includes adding static routes. We will need to pass variables for prefix and next-hop.

```
sudo route add -net PREFIX gw NEXTHOP
```

- SPGW KPIs will include CPU and Memory metrics collection from the NFVI, through the VIM.

## Building the VNF Package for Day-0

- Generate base VNF and NS packages. Our VNF includes 2 VDUs, but we will specify just one and add the other one later.

```
osm package-create --base-directory ~/vEPC --image nextepc-spgwmme-base --vcpu 2 --memory 4096 --storage 10 --interfaces 3 --vendor OSM_VNFONB_TF vnf vEPC
```

- Modify the VNFD (at ~/vEPC/vEPC_vnf/vEPC_vnfd.yaml), to replace the names of our first VDU and its connection points.

```
...
        vdu:
        -   id: spgwmme
            name: spgwmme
            description: spgwmme
...
            interface:
            -   name: eth0
                type: EXTERNAL
                virtual-interface:
                    type: PARAVIRT
                external-connection-point-ref: spgwmme-mgmt
            -   name: eth1
                type: EXTERNAL
                virtual-interface:
                    type: PARAVIRT
                external-connection-point-ref: spgwmme-s1
            -   name: eth2
                type: EXTERNAL
                virtual-interface:
                    type: PARAVIRT
                external-connection-point-ref: spgwmme-sgi
            -   name: eth3
                type: EXTERNAL
                virtual-interface:
                    type: PARAVIRT
                external-connection-point-ref: spgwmme-s6a
...
```

- Add the second VDU, you can copy and paste the first one, adapting the number of interfaces and VM Flavor.

```
...
        vdu:
...
        -   id: hss
            name: hss
            description: hss
            count: 1
            vm-flavor:
                vcpu-count: 1
                memory-mb: 2048
                storage-gb: 10
            image: 'nextepc-hss-base'
            interface:
            -   name: eth0
                type: EXTERNAL
                virtual-interface:
                    type: PARAVIRT
                external-connection-point-ref: hss-mgmt
            -   name: eth1
                type: EXTERNAL
                virtual-interface:
                    type: PARAVIRT
                external-connection-point-ref: hss-s6a
...
```

- Modify the s6a connection point to be 'internal' one, mapped to internal CPs and VLD to interconnect both VDUs.

```
...
        vdu:
        -   id: spgwmme
...
            interface:
...
            -   name: eth3
                type: INTERNAL
                virtual-interface:
                    type: PARAVIRT
                internal-connection-point-ref: spgwmme-s6a
            internal-connection-point:
            - id: spgwmme-s6a
              name: spgwmme-s6a
              type: VPORT
...
        vdu:
        -   id: hss
...
            interface:
...
            -   name: eth1
                type: INTERNAL
                virtual-interface:
                    type: PARAVIRT
                internal-connection-point-ref: hss-s6a
            internal-connection-point:
            - id: hss-s6a
              name: hss-s6a
              type: VPORT
...
        internal-vld:
        - id: s6a
          internal-connection-point:
          - id-ref: spgwmme-s6a
          - id-ref: hss-s6a
          name: s6a
...
```

- Modify the external connection points that will be exposed to the Network Service level, and set the management one.

```
...
        connection-point:
        -   name: spgwmme-mgmt
        -   name: spgwmme-s1
        -   name: spgwmme-sgi
        -   name: hss-mgmt
        mgmt-interface:
            cp: spgwmme-mgmt
...
```

- We will set a particular subnet prefix for our internal VLD, to be able to set our own IP addresses at instantiation time.

```
...
        ip-profiles:
        -   name: s6a
            description: s6a network
            ip-profile-params:
                ip-version: ipv4
                subnet-address: 10.0.6.0/24
                dhcp-params:
                  enabled: true
...
        internal-vld:
        - id: s6a
          ip-profile-ref: s6a
...
```

- Now, let's add the EPA requirements to the SPGW VDU.

```
...
        vdu:
        -   id: spgwmme
            guest-epa:
                cpu-pinning-policy: DEDICATED
                mempage-size: LARGE
...
            interface:
...
            -   name: eth1
                type: EXTERNAL
                virtual-interface:
                    type: SRIOV
                external-connection-point-ref: spgwmme-s1
            -   name: eth2
                type: EXTERNAL
                virtual-interface:
                    type: SRIOV
                external-connection-point-ref: spgwmme-sgi
...
```

- Finally, let's specify the cloud-init file names in the descriptor, and copy them to the corresponding folder (~/vEPC/vEPC_vnf/cloud_init/)

```
...
        vdu:
        -   id: spgwmme
            cloud-init-file: spgwmme-init
...
        vdu:
        -   id: hss
            cloud-init-file: hss-init
...
```

- At this point, it is ideal to validate if your package has the correct format:

```
# Validating the VNFD
osm package-validate vEPC/vEPC_vnf/
```

## Building the VNF Package for Day-1

- Let's start with the SPGW day-1 operations by populating the descriptor with 'initial config primitives'. The management interface is already set at the "spgw_mgmt" CP, so OSM will connect to this machine when defining a configuration at the VNF level. A 'config' primitive is required to pass the parameters for SSH connection.
  The only parameter that is auto-populated is 'rw_mgmt_ip' (the management IP address), the other ones will need to be provided at instantiation time.
  Note that we are setting names for primitives (operations), order of execution, parameters, and the juju charm that will implement all of them.

```
...
        vnf-configuration:
            initial-config-primitive:
            -   seq: '1'
                name: config
                parameter:
                -   name: ssh-hostname
                    value: <rw_mgmt_ip>
                -   name: ssh-username
                    value: ubuntu
                -   name: ssh-password
                    value: <password>
            -   seq: '2'
                name: configure-spgw
                parameter:
                -   name: spgw-ip
                    data-type: STRING
                    value: <spgw_ip>
                -   name: hss-ip
                    data-type: STRING
                    value: <hss_ip>
            -   seq: '3'
                name: restart-spgw
            juju:
                charm: spgwcharm
...
```

- Now, let's modify the descriptor to include operations for the HSS VDU. For this, we will use a configuration block at the VDU level, and specify the management interface for this particular VDU.

```
...
        vdu:
...
        -   id: hss
...
            interface:
            -   name: eth0
                type: EXTERNAL
                mgmt-interface: true
...
            vdu-configuration:
                initial-config-primitive:
                -   seq: '1'
                    name: config
                    parameter:
                    -   name: ssh-hostname
                        value: <rw_mgmt_ip>
                    -   name: ssh-username
                        value: ubuntu
                    -   name: ssh-password
                        value: <password>
                -   seq: '2'
                    name: configure-hss
                    parameter:
                    -   name: spgw-ip
                        data-type: STRING
                        value: <spgw_ip>
                    -   name: hss-ip
                        data-type: STRING
                        value: <hss_ip>
                -   seq: '3'
                    name: restart-hss
                juju:
                    charm: hsscharm
...
```

- Validate your package again, just in case:

```
# Validating the VNFD
osm package-validate vEPC/vEPC_vnf/
```

- Finally, we need to build the 'spgwcharm' and 'hsscharm' that will implement these operations. Let's start with the SPGW.

```
# Prepare the environment
snap install charm --classic
mkdir -p ~/charms/layers
export JUJU_REPOSITORY=~/charms
export LAYER_PATH=$JUJU_REPOSITORY/layers
cd $LAYER_PATH
charm create spgwcharm
cd spgwcharm
```

```
# Modify the layer.yaml file
includes:
    - layer:basic
    - layer:vnfproxy
```

```
# Modify the metadata.yaml file
name: spgwcharm
summary: NextEPC SPGW Charm
maintainer: Your name <youremail@yourdomain.com>
description: |
  This is an example of a proxy charm deployed by Open Source Mano.
tags:
  - nfv
subordinate: false
series:
    - trusty
    - xenial
```

```
# Create and modify the actions.yaml file
configure-spgw:
    description: "Configures the SPGW"
    params:
        hss-ip:
            description: "HSS IP"
            type: string
            default: "0.0.0.0"
        spgw-ip:
            description: "SPGW IP"
            type: string
            default: "0.0.0.0"
restart-spgw:
    description: "Restarts the service of the VNF"
```

```
# Create the 'actions' folder and populate executable files for each action, with the same content:
mkdir actions
cat <<'EOF' >> actions/configure-spgw
#!/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
chmod +x actions/configure-spgw
```

```
# Same procedure for the 'restart-spgw' action
cat <<'EOF' >> actions/restart-spgw
#!/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
chmod +x actions/restart-spgw
```

```
# Fill in the contents of the 'reactive' file (reactive/spgwcharm.py)
from charms.reactive import when, when_not, set_flag

from charmhelpers.core.hookenv import (
    action_get,
    action_fail,
    action_set,
    config,
    status_set,
)

from charms.reactive import (
    remove_state as remove_flag,
    set_state as set_flag,
    when, when_not
)

import charms.sshproxy

@when('actions.configure-spgw')
def configure_spgw():
    hss_ip = action_get('hss-ip')
    spgw_ip = action_get('spgw-ip')
    cmd1 = "sudo ip link set ens4 up && sudo dhclient ens4"
    charms.sshproxy._run(cmd1)
    cmd2 = "sudo ip link set ens5 up && sudo dhclient ens5"
    charms.sshproxy._run(cmd2)
    cmd3 = "sudo ip link set ens6 up && sudo dhclient ens6"
    charms.sshproxy._run(cmd3)
    cmd3='sudo sed -i "\'s/$hss_ip/{}/g\'" /etc/nextepc/freeDiameter/mme.conf'.format(hss_ip)
    charms.sshproxy._run(cmd3)
    cmd4='sudo sed -i "\'s/$spgw_ip/{}/g\'" /etc/nextepc/freeDiameter/mme.conf'.format(spgw_ip)
    charms.sshproxy._run(cmd4)
    remove_flag('actions.configure-spgw')

@when('actions.restart-spgw')
def restart_spgw():
    cmd = "sudo systemctl restart nextepc-mmed"
    charms.sshproxy._run(cmd)
    remove_flag('actions.restart-spgw')
```

- Proceed in a similar way for the HSS, and provide the following contents to the reactive file:

```
cd $LAYER_PATH
charm create hsscharm
cd hsscharm
```

```
# Modify the layer.yaml file
includes:
    - layer:basic
    - layer:vnfproxy
```

```
# Modify the metadata.yaml file
name: hsscharm
summary: NextEPC HSS Charm
maintainer: Your name <youremail@yourdomain.com>
description: |
  This is an example of a proxy charm deployed by Open Source Mano.
tags:
  - nfv
subordinate: false
series:
    - trusty
    - xenial
```

```
# Create and modify the actions.yaml file
configure-hss:
    description: "Configures the HSS"
    params:
        hss-ip:
            description: "HSS IP"
            type: string
            default: "0.0.0.0"
        spgw-ip:
            description: "SPGW IP"
            type: string
            default: "0.0.0.0"
restart-hss:
    description: "Restarts the service of the VNF"
```

```
# Create the 'actions' folder and populate executable files for each action, with the same content:
mkdir actions
cat <<'EOF' >> actions/configure-hss
#!/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
chmod +x actions/configure-hss
```

```
# Same procedure for the 'restart-hss' action
cat <<'EOF' >> actions/restart-hss
#!/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
chmod +x actions/restart-hss
```

```
# Fill in the contents of the 'reactive' file (reactive/hsscharm.py)
from charms.reactive import when, when_not, set_flag

from charmhelpers.core.hookenv import (
    action_get,
    action_fail,
    action_set,
    config,
    status_set,
)

from charms.reactive import (
    remove_state as remove_flag,
    set_state as set_flag,
    when, when_not
)

import charms.sshproxy

@when('actions.configure-hss')
def configure_hss():
    spgw_ip = action_get('spgw-ip')
    hss_ip = action_get('hss-ip')
    cmd1 = "sudo ip link set ens4 up && sudo dhclient ens4"
    charms.sshproxy._run(cmd1)
    cmd2= 'sudo sed -i "\'s/$hss_ip/{}/g\'" /etc/nextepc/freeDiameter/hss.conf'.format(hss_ip)
    charms.sshproxy._run(cmd2)
    cmd3= 'sudo sed -i "\'s/$spgw_ip/{}/g\'" /etc/nextepc/freeDiameter/hss.conf'.format(spgw_ip)
    charms.sshproxy._run(cmd3)
    remove_flag('actions.configure-hss')

@when('actions.restart-hss')
def restart_hss():
    cmd = "sudo systemctl restart nextepc-hssd"
    charms.sshproxy._run(cmd)
    remove_flag('actions.restart-hss')
```

- Charms need to be built and copied into the package, but we can do this in a later stage after Day-2 operations have been defined.

## Building the VNF Package for Day-2

- As defined earlier, the only VDU containing reconfiguration primitives is the SPGW. Let's add it to the descriptor first. We can define default values in this kind of primitive.

```
...
        vnf-configuration:
...
            config-primitive:
            -   name: add-route
                parameter:
                -   name: external-prefix
                    data-type: STRING
                    default-value: '8.8.8.8/32'
                -   name: next-hop
                    data-type: STRING
                    default-value: '192.168.2.1'
```

- Back to the SPGW charm folder, modify the actions.yaml file to include this new primitive, ading the respective executable file at the 'actions' folder, and finally adding the primitive at the 'reactive' file.

```
# Modify the actions.yaml file
...
add-route:
    description: "Adds a route to the SPGW"
    params:
        external-prefix:
            description: "Destinaton prefix IP"
            type: string
            default: "8.8.8.8/32"
        next-hop:
            description: "SGI next hop"
            type: string
            default: "192.168.2.1"
```

```
# Populate the executable file for the new action, in the 'actions' folder:
cat <<'EOF' >> actions/add-route
#!/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
chmod +x actions/add-route
```

```
# Fill in the contents of the 'reactive' file (reactive/spgwcharm.py)
...
@when('actions.add-route')
def add_route():
    prefix = action_get('external-prefix')
    next_hop = action_get('next-hop')
    cmd = "sudo route add -net " + prefix + " gw " + next_hop
    charms.sshproxy._run(cmd)
    remove_flag('actions.add-route')
```

- Build both charms and copy them to the VNF folder

```
cd ~/charms/layers/spgwcharm
sudo -E charm build
cp -r ~/charms/builds/spgwcharm ~/vEPC/vEPC_vnf/charms/

cd ~/charms/layers/hsscharm
sudo -E charm build
cp -r ~/charms/builds/hsscharm ~/vEPC/vEPC_vnf/charms/
```

- We also defined monitoring as part of our day-2 operations. Modify the descriptor to monitor CPU and Memory metrics of the SPGW.

```
        vdu:
...
        -   id: spgwmme
...
            monitoring-param:
            - id: "spgw_cpu_util"
              nfvi-metric: "cpu_utilization"
            - id: "spgw_memory_util"
              nfvi-metric: "average_memory_utilization"
...
        monitoring-param:
        -   id: "spgw_cpu_util"
            name: "spgw_cpu_util"
            aggregation-type: AVERAGE
            vdu-monitoring-param:
              vdu-ref: "spgwmme"
              vdu-monitoring-param-ref: "spgw_cpu_util"
        -   id: "spgw_memory_util"
            name: "spgw_memory_util"
            aggregation-type: AVERAGE
            vdu-monitoring-param:
              vdu-ref: "spgwmme"
              vdu-monitoring-param-ref: "spgw_memory_util"

```

- Run a final validation of your package:

```
# Validating the VNFD
osm package-validate vEPC/vEPC_vnf/
```

## Testing the VNF Package

- To test the VNF package, you need to first include it into a NS Package, let's create one.

```
osm package-create --base-directory ~/vEPC --vendor OSM_VNFONB_TF ns vEPC
```

- Its content should be similar to the following one, where VLDs are mapped to the external connection points of the VNF. Management external network is expected to be already present at the VIM ('vim-network-name' attribute).
  Note that, for this example, we are setting some subnets and IP address values, to be requested to the VIM's IPAM to match some pre-existing configurations inside the VNF.

```
nsd:nsd-catalog:
    nsd:
    -   id: vEPC_nsd
        name: vEPC_nsd
        short-name: vEPC_nsd
        description: Generated by OSM package generator
        vendor: OSM_VNFONB_TF
        version: '1.0'
        constituent-vnfd:
        -   member-vnf-index: 1
            vnfd-id-ref: vEPC_vnfd
        ip-profiles:
        -   name: s1
            description: s1 network
            ip-profile-params:
                ip-version: ipv4
                subnet-address: 192.168.0.0/24
                dhcp-params:
                  enabled: true
        -   name: sgi
            description: s1 network
            ip-profile-params:
                ip-version: ipv4
                subnet-address: 192.168.2.0/24
                dhcp-params:
                  enabled: true
        vld:
        -   id: management
            name: management
            short-name: management
            type: ELAN
            mgmt-network: 'true'
            vim-network-name: osm-ext
            vnfd-connection-point-ref:
            -   member-vnf-index-ref: 1
                vnfd-id-ref: vEPC_vnfd
                vnfd-connection-point-ref: spgwmme-mgmt
            -   member-vnf-index-ref: 1
                vnfd-id-ref: vEPC_vnfd
                vnfd-connection-point-ref: hss-mgmt
        -   id: s1
            name: s1
            short-name: s1
            type: ELAN
            ip-profile-ref: s1
            vnfd-connection-point-ref:
            -   member-vnf-index-ref: 1
                vnfd-id-ref: vEPC_vnfd
                vnfd-connection-point-ref: spgwmme-s1
                ip-address: 192.168.0.11
        -   id: sgi
            name: sgi
            short-name: sgi
            type: ELAN
            ip-profile-ref: sgi
            vnfd-connection-point-ref:
            -   member-vnf-index-ref: 1
                vnfd-id-ref: vEPC_vnfd
                vnfd-connection-point-ref: spgwmme-sgi
                ip-address: 192.168.2.11
```

- Now, validate your descriptors against the OSM's Information Model, using the tool in the devops repository. For example:

```
# Validating the NSD
osm package-validate vEPC/vEPC_ns/
```

- Now that you now your descriptors are valid, compress both packages and upload them to OSM.

```
cd ~/vEPC
tar -cvzf vEPC_vnfd.tar.gz vEPC_vnf/
tar -cvzf vEPC_nsd.tar.gz vEPC_ns/
osm vnfd-create vEPC_vnfd.tar.gz
osm nsd-create vEPC_nsd.tar.gz
```

- Prepare a file, which you could call 'params.yaml', with the instantiaton parameters. Note that it also includes a 'vnf' block that modifies the internal VLD at instantiation time to set its IP addresses (at VIM IPAM level) so they match with the ones we are providing.

```
additionalParamsForVnf:
-  member-vnf-index: '1'
   additionalParams:
     spgw_ip: '10.0.6.15'
     hss_ip: '10.0.6.20'
     password: 'osm4u'

vnf:
- member-vnf-index: '1'
  internal-vld:
  - name: s6a
    internal-connection-point:
    - id-ref: spgwmme-s6a
      ip-address: 10.0.6.15
    - id-ref: hss-s6a
      ip-address: 10.0.6.20
```

- Instantiate the VNF! Make sure you have registered a VIM with the compute and EPA requirements you need for the VNF.

```
osm ns-create --ns_name EPC1 --nsd_name vEPC_nsd --ssh_keys ~/.ssh/id_rsa.pub --config_file params.yaml --vim_account [VIM_ACCOUNT]
```

- Monitor the primitives execution status and NS status with the following commands. Remember that the instantiation flow from Release 7 onwards is as follows: (1) Charm execution enviroment preparation and VM Instantiation (in parallel), (2) Primitives execution

```
osm ns-list
juju switch [NS_ID]
juju status
juju debug-log
```

- When the NS reaches the 'configured' state, ssh to the HSS or SPGW/MME, and check if the HSS - MME session is established. This means that Day-1 operations worked.

```
ubuntu@nextepc-spgw:~$ sudo netstat -anlp | grep 10.0.6
...
sctp       0      0 10.0.6.15:3868          10.0.6.20:55662         ESTABLISHED
```

- We can also test Day-2 reconfiguration operations by running the primitive that adds routes to the SPGW (no host routes allowed in this example). This can be done through the OSM UI or the CLI, for example:

```
osm ns-action --vnf_name 1 --action_name add-route --params '{external-prefix: "8.8.8.0/24", next-hop: "192.168.2.1"}' epc1
```

- Finally, visit the Prometheus GUI at OSM IP (port 9091), or Grafana Dashboard at port 3000 and look for the 'osm_cpu_utilization' and 'osm_average_memory_utilization' metrics.

  ![](assets/vnfonbtf_samplevnf_1_prometheus.png)
