Target Outcome
By the end of Phase 8 you should have:
1. Horizon dashboard reachable
2. Admin OpenStack CLI working
3. Core services registered
4. Glance image uploaded
5. Public/provider network created
6. Private tenant network created
7. Router connecting private network to provider network
8. Flavor created
9. SSH keypair added
10. Security group opened for ICMP and SSH
11. Test instance booted
12. Floating IP attached
13. SSH into the test VM working
8.1 Load the OpenStack Admin Environment
Run on ctrl:
source /opt/kolla-ansible/kolla-env.sh
export KOLLA_INVENTORY=/opt/kolla-ansible/inventory/multinode-homelab
Run post-deploy if you have not already:
kolla-ansible post-deploy -i "$KOLLA_INVENTORY"
This should create:
/etc/kolla/admin-openrc.sh
Load it:
source /etc/kolla/admin-openrc.sh
Confirm authentication works:
openstack token issue
Expected: a token table is returned.
8.2 Check Core OpenStack Services
Run:
openstack service list
You should see services like:
keystone
glance
placement
nova
neutron
Check endpoints:
openstack endpoint list
Check Nova services:
openstack compute service list
Expected services:
nova-api
nova-scheduler
nova-conductor
nova-compute on cmp
nova-compute on gpu
Check hypervisors:
openstack hypervisor list
Expected:
cmp
gpu
Check Neutron agents:
openstack network agent list
Expected agents:
Open vSwitch agent on ctrl
Open vSwitch agent on cmp
Open vSwitch agent on gpu
DHCP agent on ctrl
L3 agent on ctrl
Metadata agent on ctrl
8.3 Check Horizon UI
From your browser:
http://192.168.1.50/
or:
http://192.168.1.50/dashboard
Get the admin password:
sudo grep keystone_admin_password /etc/kolla/passwords.yml
Login:
Domain: Default
User: admin
Password: <keystone_admin_password>
8.4 Upload a Test Cloud Image
Use CirrOS first. It is tiny and ideal for proving Nova/Neutron works.
On ctrl:
mkdir -p ~/openstack-images
cd ~/openstack-images
wget https://download.cirros-cloud.net/0.6.2/cirros-0.6.2-x86_64-disk.img
Upload to Glance:
openstack image create "cirros-0.6.2" \
--file cirros-0.6.2-x86_64-disk.img \
--disk-format qcow2 \
--container-format bare \
--public
Verify:
openstack image list
Expected:
cirros-0.6.2
8.5 Create Basic Flavors
Create a tiny CirrOS flavor:
openstack flavor create m1.tiny \
--id 1 \
--ram 512 \
--disk 1 \
--vcpus 1
Create a small Ubuntu-ready flavor for later:
openstack flavor create m1.small \
--id 2 \
--ram 2048 \
--disk 20 \
--vcpus 1
Verify:
openstack flavor list
8.6 Understand Your Network Model
Your Kolla config uses:
network_interface: "eth0"
api_interface: "eth0"
tunnel_interface: "eth0"
neutron_external_interface: "enp6s19"
neutron_plugin_agent: "openvswitch"
neutron_tenant_network_types: "vxlan"
Meaning:
eth0 = management/API/tunnel network
enp6s19 = external/provider network, no IP on host
VXLAN = tenant/private networks
OVS = bridge/agent implementation
Your OpenStack external/provider network should map to enp6s19.
8.7 Create the External Provider Network
You need to decide which IP range to expose as OpenStack floating IPs.
Assuming your LAN is:
192.168.1.0/24
Gateway: 192.168.1.1
DNS: 192.168.1.1 or 8.8.8.8
OpenStack VIP: 192.168.1.50
ctrl: 192.168.1.51
cmp: 192.168.1.52
gpu: 192.168.1.53
Choose a free floating IP range that does not overlap with DHCP or existing hosts.
Example:
Floating IP range: 192.168.1.200 - 192.168.1.220
Gateway: 192.168.1.1
Subnet: 192.168.1.0/24
Create the external network:
openstack network create public1 \
--external \
--provider-network-type flat \
--provider-physical-network physnet1
Create the external subnet:
openstack subnet create public1-subnet \
--network public1 \
--subnet-range 192.168.1.0/24 \
--allocation-pool start=192.168.1.200,end=192.168.1.220 \
--gateway 192.168.1.1 \
--dns-nameserver 192.168.1.1 \
--no-dhcp
Verify:
openstack network list
openstack subnet list
Important: this assumes Kolla maps your external bridge to physnet1. If this fails, we will inspect /etc/kolla/neutron-openvswitch-agent/openvswitch_agent.ini on ctrl.
8.8 Create a Private Tenant Network
Create a private VXLAN tenant network:
openstack network create private1
Create a private subnet:
openstack subnet create private1-subnet \
--network private1 \
--subnet-range 10.10.10.0/24 \
--gateway 10.10.10.1 \
--dns-nameserver 192.168.1.1
Verify:
openstack network list
openstack subnet list
8.9 Create a Router
Create the router:
openstack router create router1
Attach it to the external provider network:
openstack router set router1 --external-gateway public1
Attach the private subnet:
openstack router add subnet router1 private1-subnet
Verify:
openstack router list
openstack router show router1
openstack port list --router router1
8.10 Create an SSH Keypair
Use your existing SSH public key if available:
ls -l ~/.ssh/*.pub
Create an OpenStack keypair:
openstack keypair create \
--public-key ~/.ssh/id_ed25519.pub \
homelab-key
If you do not have a key yet:
ssh-keygen -t ed25519 -f ~/.ssh/openstack_homelab -C "openstack-homelab"
openstack keypair create \
--public-key ~/.ssh/openstack_homelab.pub \
homelab-key
Verify:
openstack keypair list
8.11 Open Security Group Rules
Allow ping:
openstack security group rule create default \
--protocol icmp \
--ingress
Allow SSH:
openstack security group rule create default \
--protocol tcp \
--dst-port 22 \
--ingress
Verify:
openstack security group rule list default
8.12 Boot the First Test Instance
Create the CirrOS instance:
openstack server create test-cirros-01 \
--image cirros-0.6.2 \
--flavor m1.tiny \
--network private1 \
--key-name homelab-key
Watch it build:
watch -n 2 openstack server list
Expected:
test-cirros-01 ACTIVE
Check details:
openstack server show test-cirros-01
8.13 Attach a Floating IP
Create a floating IP:
openstack floating ip create public1
List it:
openstack floating ip list
Assign it to the test VM:
FLOATING_IP=$(openstack floating ip list -f value -c "Floating IP Address" | head -1)
openstack server add floating ip test-cirros-01 "$FLOATING_IP"
echo "$FLOATING_IP"
Verify:
openstack server list
openstack floating ip list
8.14 Test Network Access
Ping the floating IP from ctrl:
ping -c 4 "$FLOATING_IP"
Try SSH.
For CirrOS:
ssh cirros@"$FLOATING_IP"
Default CirrOS login is commonly:
username: cirros
password: gocubsgo
If using your SSH key:
ssh -i ~/.ssh/id_ed25519 cirros@"$FLOATING_IP"
or, if you created a dedicated key:
ssh -i ~/.ssh/openstack_homelab cirros@"$FLOATING_IP"
8.15 Check Placement and Hypervisor Resources
Run:
openstack hypervisor list
openstack hypervisor stats show
Show details:
openstack hypervisor show cmp
openstack hypervisor show gpu
Check compute services:
openstack compute service list
Check resource providers:
openstack resource provider list
8.16 Check Neutron Agent Health
Run:
openstack network agent list
You want all relevant agents alive:
neutron-openvswitch-agent ctrl Alive :-)
neutron-openvswitch-agent cmp Alive :-)
neutron-openvswitch-agent gpu Alive :-)
neutron-dhcp-agent ctrl Alive :-)
neutron-l3-agent ctrl Alive :-)
neutron-metadata-agent ctrl Alive :-)
If DHCP or metadata fails, check:
docker logs --tail 100 neutron_dhcp_agent
docker logs --tail 100 neutron_metadata_agent
docker logs --tail 100 neutron_l3_agent
8.17 Verify From Horizon
In Horizon:
Project → Compute → Instances
Project → Network → Networks
Project → Network → Routers
Project → Network → Floating IPs
Admin → Compute → Hypervisors
Admin → System → System Information
You should see:
test-cirros-01
private1
public1
router1
floating IP allocation
cmp and gpu hypervisors
8.18 Useful Troubleshooting Commands
Check all containers
Avoid Docker Go-template quoting inside Ansible. Use:
ansible -i "$KOLLA_INVENTORY" control,compute \
-m shell \
-a "hostname; docker ps | sort" \
-b
Check unhealthy containers
ansible -i "$KOLLA_INVENTORY" control,compute \
-m shell \
-a "hostname; docker ps --filter health=unhealthy || true" \
-b
Check exited containers
ansible -i "$KOLLA_INVENTORY" control,compute \
-m shell \
-a "hostname; docker ps -a --filter status=exited || true" \
-b
Check OpenStack service catalog
openstack catalog list
Check Nova logs on controller
docker logs --tail 100 nova_api
docker logs --tail 100 nova_scheduler
docker logs --tail 100 nova_conductor
Check Nova logs on compute nodes
ansible -i "$KOLLA_INVENTORY" compute \
-m shell \
-a "hostname; docker logs --tail 100 nova_compute" \
-b
Check Neutron logs
On ctrl:
docker logs --tail 100 neutron_server
docker logs --tail 100 neutron_l3_agent
docker logs --tail 100 neutron_dhcp_agent
docker logs --tail 100 neutron_metadata_agent
docker logs --tail 100 neutron_openvswitch_agent
On compute nodes:
ansible -i "$KOLLA_INVENTORY" compute \
-m shell \
-a "hostname; docker logs --tail 100 neutron_openvswitch_agent" \
-b
8.19 Save a Phase 8 Environment Helper
Create a helper file:
cat > ~/phase8-openstack-env.sh <<'EOF'
#!/usr/bin/env bash
source /opt/kolla-ansible/kolla-env.sh
export KOLLA_INVENTORY=/opt/kolla-ansible/inventory/multinode-homelab
source /etc/kolla/admin-openrc.sh
echo "Kolla inventory: $KOLLA_INVENTORY"
echo "OpenStack cloud: $OS_AUTH_URL"
openstack token issue >/dev/null && echo "OpenStack auth: OK"
EOF
chmod +x ~/phase8-openstack-env.sh
Use it:
source ~/phase8-openstack-env.sh
8.20 Full Phase 8 Runbook
You can run this after confirming your floating IP range is safe:
source /opt/kolla-ansible/kolla-env.sh
export KOLLA_INVENTORY=/opt/kolla-ansible/inventory/multinode-homelab
kolla-ansible post-deploy -i "$KOLLA_INVENTORY"
source /etc/kolla/admin-openrc.sh
openstack token issue
openstack service list
openstack endpoint list
openstack compute service list
openstack hypervisor list
openstack network agent list
mkdir -p ~/openstack-images
cd ~/openstack-images
wget -nc https://download.cirros-cloud.net/0.6.2/cirros-0.6.2-x86_64-disk.img
openstack image create "cirros-0.6.2" \
--file cirros-0.6.2-x86_64-disk.img \
--disk-format qcow2 \
--container-format bare \
--public
openstack flavor create m1.tiny \
--id 1 \
--ram 512 \
--disk 1 \
--vcpus 1
openstack flavor create m1.small \
--id 2 \
--ram 2048 \
--disk 20 \
--vcpus 1
openstack network create public1 \
--external \
--provider-network-type flat \
--provider-physical-network physnet1
openstack subnet create public1-subnet \
--network public1 \
--subnet-range 192.168.1.0/24 \
--allocation-pool start=192.168.1.200,end=192.168.1.220 \
--gateway 192.168.1.1 \
--dns-nameserver 192.168.1.1 \
--no-dhcp
openstack network create private1
openstack subnet create private1-subnet \
--network private1 \
--subnet-range 10.10.10.0/24 \
--gateway 10.10.10.1 \
--dns-nameserver 192.168.1.1
openstack router create router1
openstack router set router1 --external-gateway public1
openstack router add subnet router1 private1-subnet
openstack keypair create \
--public-key ~/.ssh/id_ed25519.pub \
homelab-key
openstack security group rule create default \
--protocol icmp \
--ingress
openstack security group rule create default \
--protocol tcp \
--dst-port 22 \
--ingress
openstack server create test-cirros-01 \
--image cirros-0.6.2 \
--flavor m1.tiny \
--network private1 \
--key-name homelab-key
watch -n 2 openstack server list
Then in another shell:
source /etc/kolla/admin-openrc.sh
openstack floating ip create public1
FLOATING_IP=$(openstack floating ip list -f value -c "Floating IP Address" | head -1)
openstack server add floating ip test-cirros-01 "$FLOATING_IP"
ping -c 4 "$FLOATING_IP"
ssh cirros@"$FLOATING_IP"
Phase 8 Success Criteria
Phase 8 is complete when these all pass:
openstack token issue
openstack service list
openstack compute service list
openstack hypervisor list
openstack network agent list
openstack image list
openstack flavor list
openstack network list
openstack router list
openstack server list
openstack floating ip list
And your test VM reaches:
ACTIVE
with working:
ping floating-ip
ssh floating-ip
Then your homelab OpenStack is not just deployed; it is operational.
