OpenStack: Neutron (network)

CLI
https://developer.openstack.org/firstapp-libcloud/networking.html

# search server by port ID
openstack port show -c device_id -f value ${PORT_ID}
openstack show show ${PORT_ID}
openstack router show ${PORT_ID}

Port
https://docs.openstack.org/python-openstackclient/latest/cli/command-objects/port.html

# get port ID for OVS interface
openstack port list -c id -f value | grep $(awk '{print substr($OVS_INTERFACE,4,8)}')
 
# list all port by subnet
openstack port list --fixed-ip subnet=mgmt-dev-net --sort-column Name
 
# list all devices by network
openstack port list --network mgmt-dev -c device_id -f value
 
# allow incomming (ingress) SSH for specific IP / subnet
openstack security group rule create default \
    --protocol tcp \
    --dst-port 22 \
    --remote-ip 10.20.30.40/32
 
# create port without security
openstack port create openstack-net-port1 --network openstack-net --no-security-group --disable-port-security --no-fixed-ip
openstack port set --disable-port-security openstack-net-port1
 
# get all port by subnet
openstack port list -c ID -f value --fixed-ip subnet=dev-net1
 
# search ports (filter with json)
openstack port list -c ID -c "Fixed IP Addresses" -f json | jq -r '.[] | select(."Fixed IP Addresses"[].ip_address | startswith("10.11")).ID'

Creat and assign port

openstack port create foo-db3-dev-mgmt-net \
    --network mgmt-net1-dev \
    --mac-address 00:16:3e:9b:b7:10 \
    --fixed-ip ip-address=10.0.0.14 \
    --security-group 5b825582-17c5-475b-9253-ec373ba96eb7 \
    --project 6df9bd4956404f06bf169a382fe4035a
 
openstack server add port foo-db3-dev-vm foo-db3-dev-mgmt-net

Security group
https://docs.openstack.org/ocata/user-guide/cli-nova-configure-access-security-for-instances.html

openstack security group list
 
# allow SSH ingress
openstack security group rule create \
  --protocol tcp \
  --dst-port 22:22 \
  --remote-ip 0.0.0.0/0 \
  --description "SSH ingress" \
  ${SECURITY_GROUP_ID}
 
# show
openstack security group show ${SECURITY_GROUP_ID}
 
# add
openstack port set --security-group ${SECURITY_GROUP} ${PORT_ID}
 
# remove
openstack port unset --security-group ${SECURITY_GROUP} ${PORT_ID}
 
# alllow ICMP traffic (ping)
openstack security group create foo-sec
openstack port show ${PORT_ID} -c security_group_ids -f json | jq -r .security_group_ids[]
openstack security group show ${SECURITY_GROUP_ID}
openstack security group rule create --protocol icmp ${SECURITY_GROUP_ID}
openstack security group rule delete ${SECURITY_GROUP_RULE_ID}

Cleanup OpenvSwitch "No such device" devices

# Evacuate all VMs
# Cleanup "No such device" Open vSwitch devices
 
openstack compute service list --host compute1.example.com
openstack server list --all --host compute1.example.com
 
ssh compute1.example.com
docker exec -it openvswitch_vswitchd ovs-vsctl show | grep "No such device"
docker exec -it openvswitch_vswitchd ovs-vsctl show | tee ovs-vsctl_show.1.out
docker exec -it neutron_openvswitch_agent neutron-ovs-cleanup
docker exec -it openvswitch_vswitchd ovs-vsctl show | tee ovs-vsctl_show.2.out
 
# diff ovs-vsctl_show.1.out ovs-vsctl_show.2.out
# reboot node

Debug DHCP errors

# dnsmasq (DHCP) configuration
ssh -t control1 docker exec -i neutron_dhcp_agent ls -l /var/lib/neutron/dhcp/${NETWORK_ID}
 
# get dnsmasq prozess
docker exec -i neutron_dhcp_agent pgrep -af ${NETWORK_ID}
 
# test DHCP server
sudo dhcping -v -h 00:11:22:33:44:55 -s 10.0.0.2 #-c 10.0.0.99
 
# get dhclient logs (in VM)
sudo journalctl --since "7 days ago" -u dnsmasq-dhcp
sudo journalctl --since "7 days ago" | grep -i dhcp
 
 
for NODE in ctl{1..6}-dev; do
    echo ${NODE}
    ssh ${NODE} cat /var/lib/docker/volumes/kolla_logs/_data/neutron/dnsmasq.log | grep "lease not found" | awk '{print $1, $2}' | uniq -c | awk '$1 > 100 {print}'
    echo
done

API

curl -s -H "X-Auth-Token: $(openstack token issue -c id -f value)" -X GET http://neutron.service.i.example.com:9696/v2.0/routers | jq

RBAC
https://docs.openstack.org/mitaka/networking-guide/config-rbac.html
https://docs.openstack.org/python-openstackclient/pike/cli/command-objects/quota.html
https://docs.openstack.org/ocata/admin-guide/cli-networking-advanced-quotas.html

# create 
openstack network rbac create --target-project foo-project1 --action access_as_shared --type network foo-net-01
 
# show rbac quota
neutron quota-show --tenant_id <PROJECT_ID> | grep rbac_policy
 
# set rbac quota to unlimited
openstack quota set --rbac-policies -1 <PROJECT_ID>

Check ARP count for subnet

# get total port count
ssh admin-dev "source /etc/kolla/admin-openrc.sh; openstack port list -c ID -f value --fixed-ip subnet=dev-rbac-net1 | wc -l"
 
# get ARP entry by compute node
for COMPUTE_NODE in com{{1..16},{101..102}}-dev; do
    echo -n "${COMPUTE_NODE}: "
    for OVS in br-tun br-int; do
        ssh ${COMPUTE_NODE} docker exec -t openvswitch_vswitchd ovs-ofctl dump-flows ${OVS} | grep arp | grep -c 10.11.0
    done | paste -s -d+ | bc
done
 
# check specific ARP entry
ssh ${COMPUTE_NODE}
TARGET_IP=10.0.11.1
docker exec -t openvswitch_vswitchd ovs-ofctl dump-flows br-tun | grep "arp_tpa=${TARGET_IP} "
 
# delete ARP entry
docker exec -t openvswitch_vswitchd ovs-ofctl --strict del-flows br-tun "priority=1,arp,dl_vlan=21,arp_tpa=10.11.12.13"

Public IP

# show public network
openstack subnet list --network public

Find IP in namespace

IP=172.16.0
for NS in $(ip netns | cut -d" " -f1); do
    ip netns exec ${NS} ip a | grep ${IP} && echo ${NS}
done

Add / Delete port

# show ports
nova interface-list ${SERVER_ID}
 
# add port
openstack server add port ${SERVER_ID} ${PORT_ID}
 
# add remove port
openstack server remove port ${SERVER_ID} ${PORT_ID}

Debug

# search for INACTIVE ports in neutron DB
DB_PASS=$(grep neutron_database_password /etc/kolla/passwords.yml | cut -d " " -f2)
mysql --host=${DB_HOST} --password=${DB_PASS} --port=3306 --user=neutron --database=neutron \
  -se "select port_id from ml2_port_bindings where status = 'INACTIVE'"
 
# check total port count for a network
for COMPUTE_NODE in com{{1..10},{150..155}}-stage; do
    BR_INT=$(ssh ${COMPUTE_NODE} docker exec -t openvswitch_vswitchd ovs-ofctl dump-flows br-int | grep arp | cut -d"," -f9 | cut -d"=" -f2 | cut -d" " -f1)
    BR_TUN=$(ssh ${COMPUTE_NODE} docker exec -t openvswitch_vswitchd ovs-ofctl dump-flows br-tun | grep arp | cut -d"," -f9 | cut -d"=" -f2 | cut -d" " -f1)
    comm -12  <(echo "$BR_INT" | sort) <(echo "$BR_TUN" | sort) | grep 10.123.0
done

Search disabled router and DHCP server ports in IP namespaces

# search for disabled router ports
for JSON in $(openstack port list --device-owner network:router_ha_interface -c id -c binding_host_id -c device_id -f json | jq -rc .[]); do
    DEVICE_ID=$(echo ${JSON} | jq -r .device_id)
    BINDING_HOST_ID=$(echo ${JSON} | jq -r .binding_host_id)
    ID=$(echo ${JSON} | jq -r .ID)
    ID_TOKEN=$(echo ${ID}| awk -F'-' '{print $1}')
 
    OUTPUT=$(ssh ${BINDING_HOST_ID} ip netns exec qrouter-${DEVICE_ID} ip link | egrep "ha-.*DOWN")
    if [ -n "${OUTPUT}" ]; then
        echo ${OUTPUT}
 
        openstack port show ${ID}
        openstack router show ${DEVICE_ID}
 
        PROJECT_ID=$(openstack router show ${DEVICE_ID} -c project_id -f value)
        openstack project show 6b15a34076074342b79632bd37e5bd15
 
        DOMAIN_ID=$(openstack project show ${PROJECT_ID} -c domain_id -f value)
        openstack domain show ${DOMAIN_ID}
 
        DEVICE=$(echo ${OUTPUT} | cut -d":" -f2)
        echo "ssh ${BINDING_HOST_ID} ip netns exec qrouter-${DEVICE_ID} ip link set dev ${DEVICE} up"
 
        EXIT_CODE=1
    fi
done
 
# search for disabled dhcp ports
for JSON in $(openstack port list --device-owner network:dhcp -c binding_host_id -c network_id -f json | jq -rc .[]); do
    NETWORK_ID=$(echo ${JSON} | jq -r .network_id)
    BINDING_HOST_ID=$(echo ${JSON} | jq -r .binding_host_id)
 
    OUTPUT=$(ssh ${BINDING_HOST_ID} ip netns exec qdhcp-${NETWORK_ID} ip link | egrep "tap.*DOWN")
    if [ -n "${OUTPUT}" ]; then
        echo ${OUTPUT}
        echo "ssh ${BINDING_HOST_ID} ip netns exec qdhcp-${NETWORK_ID} ip link set dev tapXXXXXXXX-XX up"
        openstack port show ${ID}
 
        EXIT_CODE=1
    fi
done
 
# search for all disabled port in all IP namespaces
for NODE in $(openstack network agent list --agent-type dhcp -c Host -f value); do
    for NETNS in $(ssh ${NODE} ip netns | cut -d" " -f1); do
        ssh ${NODE} ip netns exec ${NETNS} ip -br l | grep DOWN
    done
done

Recreate router network namespace

openstack router set --disable ${ROUTER_ID}
openstack router set --enable ${ROUTER_ID}

Manual failover router

# connect to IP namespace on control node
ip netns exec 79d8a480-bbcb-4850-9941-2f5627e69fb4 bash
 
# get HA interface name
ip a | grep "ha-"
 
# shut down HA interface
ip link set dev ha-xxxxxxxx-xx down
 
# reenable HA interface
ip link set dev ha-xxxxxxxx-xx up

Debug router NS

SERVER_ID=e1440c6d-44c2-4a9f-bc30-fe2166e6f439
 
# get port(s) ID
PORT_ID=$(openstack port list --server ${SERVER_ID} -c id -f value)
 
# get network ID
NETWORK_ID=$(openstack port show ${PORT_ID} -c network_id -f value)
openstack port list --network ${NETWORK_ID} -c device_id -c  device_owner -c id -c mac_address -c fixed_ips
 
# get router device ID
DEVICE_ID=$(openstack port list --network ${NETWORK_ID} --device-owner network:ha_router_replicated_interface -c device_id -f value)
# openstack router show ${DEVICE_ID}
 
# show router / gw namespaces
openstack port list --device-id ${DEVICE_ID} -c id -c device_id -c binding_host_id -c fixed_ips -c device_owner --sort-column device_owner
 
# Debug: connect to router namespaces
ssh -t <binding_host_id> ip netns exec qrouter-<device_id> bash

Metadata service
metadata API: 169.254.169.254
http://kimizhang.com/metadata-service-in-dhcp-namespace/

Video
https://www.youtube.com/embed/B17qcaSglHA - Neutron Network Know-How: A Hands-On Workshop for Solving Neutron Nightmares