Deploy a complete NFV stack — OSM as the NFV orchestrator and OpenStack (Devstack) as the VIM — on two COSMOS compute nodes, onboard a VNF package, and launch a virtual network service.
This tutorial walks through a full Network Functions Virtualisation (NFV) deployment using ETSI Open Source MANO (OSM) and OpenStack. OSM acts as the NFV Orchestrator (NFVO); a single-node Devstack installation provides the Virtual Infrastructure Manager (VIM) and compute plane.
Two large-footprint compute nodes are required: one for OSM and one for the Devstack VIM. Because the OSM and VIM installations are independent, their setup steps can be run in parallel from separate terminal windows to save time.
After the infrastructure is running, the tutorial demonstrates onboarding a CirrOS-based VNF package and NS package through the OSM web UI, instantiating the network service on OpenStack, and verifying connectivity between the two virtual instances.
This tutorial implements the OSM quickstart from the ETSI user guide with adaptations for COSMOS hardware and the Ubuntu 18.04-based testbed images.
After completing this tutorial you will be able to:
| Difficulty | Intermediate |
| Estimated time | 90–120 min (dominated by install times) |
| Domain / sandbox | sb1.cosmos-lab.org (any domain with ≥ 2 large compute nodes) |
| Topic group | Cloud & Edge |
| Last verified | Not re-tested (migrated 2026-06-20) |
Background knowledge
Account & access
Devices / nodes
| Resource | Role | Qty | Notes |
|---|---|---|---|
| srv1-lg1.sb1.cosmos-lab.org | OSM node | 1 | Large compute; ≥ 40 GB disk, ≥ 8 GB RAM |
| srv2-lg1.sb1.cosmos-lab.org | VIM node (Devstack/OpenStack) | 1 | Large compute; same requirements |
Disk images
| Image | Load onto | Provides |
|---|---|---|
| tutorial-osm.ndz | OSM node (srv1-lg1) | Ubuntu 18.04 with OSM pre-installed; user native (password native) in sudo/docker/lxd groups |
| tutorial-devstack.ndz | VIM node (srv2-lg1) | Ubuntu 18.04 with Devstack pre-configured; user native (password native) |
Software components
| Component | Version | Source |
|---|---|---|
| OSM (Open Source MANO) | Release 8 | Preinstalled in tutorial-osm.ndz; install script: install_osm.sh from ETSI |
| OpenStack | Train | Preinstalled via Devstack in tutorial-devstack.ndz |
| Devstack | Latest (Train era) | ~/devstack/stack.sh on VIM node |
| Docker | TODO: verify | Required by OSM; preinstalled in image |
| LXD | TODO: verify | Required by OSM; preinstalled in image |
Spectrum / RF / special
Not applicable.
Two large compute nodes on the same COSMOS sandbox. The console provides control-plane access to both. OSM (node 1) communicates with the OpenStack Keystone identity service on the VIM node (node 2) to discover the rest of the cloud configuration. Both web interfaces are accessed from the experimenter's laptop via SSH port-forwarding through the console.
Experimenter laptop
|
| SSH (port-forwards 9980→srv1-lg1:80, 9981→srv2-lg1:80)
|
console.sb1.cosmos-lab.org
|---> srv1-lg1 (OSM + Docker containers)
|---> srv2-lg1 (Devstack OpenStack VIM)
The OSM and VIM imaging steps can be done in parallel.
Reserve the resources and open three terminal windows. Log into the console in the first terminal:
ssh <username>@console.sb1.cosmos-lab.org
In the first terminal, load the OSM image (resize to ≥ 60 GB to accommodate Docker layers):
omf load -t srv1-lg1.sb1.cosmos-lab.org -i tutorial-osm.ndz -r 60
Wait for:
INFO exp: 1 node successfully imaged ...
In the same terminal, turn the OSM node on and wait for it to boot (up to ~3 minutes):
omf tell -a on -t srv1-lg1.sb1.cosmos-lab.org
Confirm reachability: ping srv1-lg1.sb1.cosmos-lab.org
In the second terminal (also logged into the console), load the Devstack image in parallel with step 2:
omf load -t srv2-lg1.sb1.cosmos-lab.org -i tutorial-devstack.ndz -r 60
Wait for:
INFO exp: 1 node successfully imaged ...
Turn the VIM node on:
omf tell -a on -t srv2-lg1.sb1.cosmos-lab.org
Confirm reachability: ping srv2-lg1.sb1.cosmos-lab.org
SSH to the OSM node as the native user:
ssh native@srv1-lg1.sb1.cosmos-lab.org
If you are using the tutorial-osm.ndz image, OSM is already installed. Skip to verifying the Docker stack below.
If you need to install OSM from a bare Ubuntu 18.04 image, follow these sub-steps first:
Load a baseline image and resize to ≥ 60 GB:
omf load -t srv1-lg1.sb1.cosmos-lab.org -i baseline_1804.ndz -r 60
Turn the node on:
omf tell -a on -t srv1-lg1.sb1.cosmos-lab.org
Log in as root:
ssh root@srv1-lg1.sb1.cosmos-lab.org
Set a password for the native user:
echo native:native | chpasswd
Add native to the required groups:
sudo groupadd lxd && sudo groupadd docker && sudo usermod -a -G lxd,docker native
Log out and back in as native:
exit
ssh native@srv1-lg1.sb1.cosmos-lab.org
Install net-tools:
sudo apt install net-tools
Download and run the OSM install script:
wget https://osm-download.etsi.org/ftp/osm-6.0-six/install_osm.sh
chmod +x install_osm.sh
./install_osm.sh 2>&1 | tee osm_install_log.txt
Enter y when prompted.
If the script fails with an LXD error, run:
lxd init
Accept all defaults except choose none for IPv6. Then re-run ./install_osm.sh.
Once OSM is installed (from image or from scratch):
docker stack ps osm
All services should show Running. If any are not:
docker stack rm osm && sleep 60
docker stack deploy -c /etc/osm/docker/docker-compose.yaml osm
In your second terminal, SSH to the VIM node:
ssh native@srv2-lg1.sb1.cosmos-lab.org
Change to the Devstack directory and run the installation script:
cd ~/devstack
./stack.sh
This will run for approximately 10 minutes. On success, the output will end with something like:
=========================
DevStack Component Timing
(times are in seconds)
=========================
run_process 16
test_with_retry 2
apt-get-update 5
osc 115
wait_for_service 10
git_timed 107
dbsync 65
pip_install 201
apt-get 166
-------------------------
Unaccounted time 345
=========================
Total runtime 1032
This is your host IP address: 10.19.1.2
This is your host IPv6 address: ::1
Horizon is now available at http://10.19.1.2/dashboard
Keystone is serving at http://10.19.1.2/identity/
The default users are: admin and demo
The password: native
Note the Host IP address, Horizon URL, Keystone URL, and password — you will need them below.
If you need to customise the Devstack networking (for example, to make OpenStack VMs directly reachable from the console), edit ~/devstack/local.conf before running stack.sh:
[[local|localrc]]
ADMIN_PASSWORD=native
DATABASE_PASSWORD=$ADMIN_PASSWORD
RABBIT_PASSWORD=$ADMIN_PASSWORD
SERVICE_PASSWORD=$ADMIN_PASSWORD
HOST_IP=10.19.1.2
SERVICE_HOST=$HOST_IP
MYSQL_HOST=$HOST_IP
RABBIT_HOST=$HOST_IP
#Check out latest commits
RECLONE=True
#upgrade python
PIP_UPGRADE=True
##Uncomment to Customize VNC
#NOVA_VNC_ENABLED=True
#VNCSERVER_LISTEN=0.0.0.0
#VNCSERVER_PROXYCLIENT_ADDRESS=$SERVICE_HOST
##use for ssh forwarding
#NOVNCRPROXY_BASE_URL=http://127.0.0.1:6080/vnc_auto.html
##Uncomment to enable Spice, comment VNC section
#NOVA_VNC_ENABLED=False
#NOVA_SPICE_ENABLED=True
#SPICEAGENT_ENABLED=True
#enable_service n-spice
#disable_service n-novnc
#html5proxy_base_url=http://127.0.0.1:6082/spice_auto.html
To make virtual machines directly accessible from the console, determine your control interface details first:
root@node1-2:~# ip r
default via 10.19.0.1 dev enp134s0 proto dhcp src 10.19.1.2 metric 100
10.19.0.0/16 dev enp134s0 proto kernel scope link src 10.19.1.2
10.19.0.1 dev enp134s0 proto dhcp scope link src 10.19.1.2 metric 100
172.24.4.0/24 dev br-ex proto kernel scope link src 172.24.4.1
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1 linkdown
root@node1-2:~# ip addr show enp134s0
2: enp134s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 68:05:ca:1e:e5:98 brd ff:ff:ff:ff:ff:ff
inet 10.19.1.2/16 brd 10.19.255.255 scope global dynamic enp134s0
valid_lft 2297sec preferred_lft 2297sec
inet6 fe80::6a05:caff:fe1e:e598/64 scope link
valid_lft forever preferred_lft forever
Then add to local.conf:
#set to control interface name
PUBLIC_INTERFACE=enp134s0
#set to control interface IP
HOST_IP=10.19.1.2
#Set to control interface subnet
FLOATING_RANGE=10.19.0.0/16
#set to control interface gateway
PUBLIC_NETWORK_GATEWAY=10.19.0.1
#choose range of IPs in control subnet to assign to VMs
Q_FLOATING_ALLOCATION_POOL=start=10.19.100.1,end=10.19.100.254
#set IP range for private networks not to conflict with testbed nets
IPV4_ADDRS_SAFE_TO_USE=172.16.100.0/24
Because this configuration causes OpenStack to override the DHCP configuration on the control interface, run the following before stack.sh:
sudo ip r add default via 10.19.0.1
echo "DNS=10.50.0.8 10.50.0.9" | sudo tee -a /etc/systemd/resolved.conf
echo "Domains=~." | sudo tee -a /etc/systemd/resolved.conf
After stack.sh completes, open the default security group for ICMP and SSH:
openstack security group rule create --proto icmp --dst-port 0 default
openstack security group rule create --proto tcp --dst-port 22 default
This material follows the Devstack single-machine guide and the networking guide.
If you don't specify any configuration you will get the following:
PUBLIC_INTERFACE=eth1 (this connects to the br-ex bridge)See also the Devstack neutron guide.
To change the IP address without re-running stack.sh:
unstack.sh:./unstack.sh
update endpoint set url = REPLACE(url, '[old IP address]', '[new IP address]');
/etc folder:grep -rl '[old IP address]' /etc | xargs sed -i 's/[old IP address]/[new IP address]/g'
/opt/stack folder:grep -rl '[old IP address]' /opt/stack | xargs sed -i 's/[old IP address]/[new IP address]/g'
sudo systemctl restart apache2
rejoin-stack.sh:./rejoin-stack.sh
keystone-all
In your third terminal (on your laptop), open SSH port-forwards to reach both web interfaces. The example below forwards local port 9980 to the OSM node's port 80, and local port 9981 to the Devstack node's port 80:
ssh testbeduser@sb1.cosmos-lab.org -N \
-L 9980:srv1-lg1:80 \
-L 9981:srv2-lg1:80
For more information, see the SSH tunnelling guide.
OSM Web UI
http://localhost:9980admin / adminIf the OSM web UI does not come up:
ssh native@srv1-lg1.sb1.cosmos-lab.org (password: native)docker stack ps osm./install_osm.shOpenStack (Horizon) Web UI
http://localhost:9981admin / native (unless the stack.sh output showed a different password)stack.sh completes successfully.http://localhost:9980) with admin / admin.http://<DEVSTACK_IP>/identity/v3/ (replace <DEVSTACK_IP> with the IP shown by stack.sh)adminnativeadminopenstack-siteopenstackSSH to the OSM node and run:
native@node1-1:~$ export LC_ALL=C.UTF-8
native@node1-1:~$ export LANG=C.UTF-8
native@node1-1:~$ osm vim-create --name openstack-standalone --user admin --password native \
--auth_url http://10.19.1.2:5000/v2.0 --tenant admin --account_type openstack
http://localhost:9981).cirros034.img fileqcow2cirros_2vnf_nsopenstack-sitehttp://localhost:9981):
omf tell -a offh -t srv1-lg1.sb1.cosmos-lab.org
omf tell -a offh -t srv2-lg1.sb1.cosmos-lab.org
The tutorial images (tutorial-osm.ndz, tutorial-devstack.ndz) are pre-built; run omf save only if you made changes you want to preserve:
omf save -n srv1-lg1.sb1.cosmos-lab.org # OSM node, only if modified
omf save -n srv2-lg1.sb1.cosmos-lab.org # VIM node, only if modified
| Symptom | Likely cause | Fix |
|---|---|---|
OSM web UI not reachable at localhost:9980 |
Docker stack not fully started, or SSH tunnel not active | Check docker stack ps osm; restart with docker stack rm osm && sleep 60 && docker stack deploy -c /etc/osm/docker/docker-compose.yaml osm; verify SSH tunnel in third terminal |
./install_osm.sh fails with LXD error |
LXD not initialised | Run lxd init, choose all defaults except none for IPv6, then re-run the script |
stack.sh fails midway |
Dependency or network issue | Review the Devstack log; often re-running stack.sh after fixing the reported error is sufficient |
| OpenStack Horizon not reachable | stack.sh still running or failed |
Wait for stack.sh to finish; check for errors at the end of its output |
| OSM cannot connect to VIM (VIM account shows ERROR) | Wrong Keystone URL or credentials | Verify <DEVSTACK_IP> matches the IP shown by stack.sh; re-create the VIM account |
| CirrOS instances not reachable / no ping | Default security group blocks ICMP | Run openstack security group rule create --proto icmp --dst-port 0 default on the Devstack node |
Author(s): COSMOS team · Last verified: Not re-tested (migrated 2026-06-20) · Tested image/release: tutorial-osm.ndz / tutorial-devstack.ndz · Tags: cloud, nfv, osm, openstack, devstack, vim, vnf