BMaaS Part 3: Multi-tenancy

So far we have learned how to configure and provision baremetal nodes with OpenStack Ironic in Part 1 of the blog. We also configured our deployment to allow zero-touch discovery in Part 2. The next “LEGO” building block is to allow our tenants/project to isolate their baremetal resources. This unique OpenStack feature can take advantage of neutron to reach out to top of rack switches (TORs) via ml2 driver and dynamically assign a VLAN id to switch ports for corresponding nodes. 

With this functionality, your tenants can take ownership of the pool of baremetal nodes for the time of the project and not worry about other users of the cloud. When they are done, they simply delete instances and the baremetal resource return to the pool of nodes that can be consumed by other projects (and the networking is being set back to default).

Let’s look at the short 7 minutes video:

There are currently 3 alternatives for configuring Multi-tenancy for baremetal in Ironic (ml2 drivers):

In this blog we are going to focus mostly on the one up top (generic-switch), since it’s the one officially working with Queen release of OpenStack (OSP13). However you will also receive a sneak peak into ansible-networking driver that is going to be a driver of choice starting with OSP14 (Rocky) and beyond. I would probably recommend to avoid the third option. Even though you might be able to make it work, the drivers I have used are typically far behind current release cycles and are more buggy then the other 2 options.

I. Building new docker container for networking-generic-switch

The process for integrating networking-generic-switch and ansible-networking is very similar. Unfortunately OSP13 doesn’t ship with driver being available inside neutron container, so we need to start with rebuilding our neutron container.

1. Create working director and download networking-generic-switch rpms. I have used RDO repository for Queens

(chrisj) [stack@undercloud ~]$ mkdir rebuild-image/

(chrisj) [stack@undercloud ~]$ cd rebuild-image/

2. Open RDO repo – http://mirror.centos.org/centos/7/cloud/x86_64/openstack-queens/ – you will need to download follow RPMs into working directory:

  • python2-networking-generic-switch-1.0.0-1.el7.noarch.rpm
  • python2-scp-0.10.2-6.el7.noarch.rpm
  • python2-netmiko-1.4.1-1.el7.noarch.rpm

3. Find out the name and version of openstack-neutron-server docker container

(chrisj) [stack@undercloud rebuild-image]$ grep openstack-neutron-server ~/templates/overcloud_images.yaml 
  DockerNeutronApiImage: 172.31.0.10:8787/rhosp13/openstack-neutron-server:13.0-58

4. Create Dockerfile with following content:

(chrisj) [stack@undercloud rebuild-image]$ cat Dockerfile 
FROM 172.31.0.10:8787/rhosp13/openstack-neutron-server:13.0-58
USER root
# add packages for generic driver
ADD /python2-networking-generic-switch-1.0.0-1.el7.noarch.rpm /python2-networking-generic-switch-1.1.0-1.el7.noarch.rpm
ADD /python2-scp-0.10.2-6.el7.noarch.rpm /python2-scp-0.10.2-6.el7.noarch.rpm
ADD /python2-netmiko-1.4.1-1.el7.noarch.rpm /python2-netmiko-1.4.1-1.el7.noarch.rpm

#install generic driver
RUN yum -y install python2-networking-generic-switch-1.1.0-1.el7.noarch.rpm python2-netmiko-1.4.1-1.el7.noarch.rpm python2-scp-0.10.2-6.el7.noarch.rpm

5. Build and push docker container for neutron

(chrisj) [stack@undercloud rebuild_image]$ docker build -t 172.31.0.10:8787/rhosp13/openstack-neutron-server:13.0-58-custom .

(chrisj) [stack@undercloud rebuild_image]$ sudo docker push 172.31.0.10:8787/rhosp13/openstack-neutron-server:13.0-58-custom

6. Adjust overcloud_images.yaml to include a new neutron container name:

(chrisj) [stack@undercloud rebuild_image]$ sed -i ‘s/openstack-neutron-server:13.0-58/openstack-neutron-server:13.0-58-custom/g’ ~/templates/overcloud_images.yaml

II. Integrating networking-generic-switch configuration into Director/TripleO

This should be an easy part. There are only few parameters that have to be included during the deployment. If you’ve followed my previous post, I am putting all the custom parameters into ‘catch all’ yaml file called Extra Config.yaml.

1. Configure multitenancy parameters in parameter_defaults:

(chrisj) [stack@undercloud ~]$ cat templates/ExtraConfig.yaml 
parameter_defaults:

  # Ironic Multi-tenancy
  IronicProvisioningNetwork: baremetal
  NeutronMechanismDrivers: openvswitch,genericswitch
  IronicEnabledNetworkInterfaces: flat,noop,neutron
  IronicDefaultNetworkInterface: neutron
  ControllerExtraConfig:
     neutron::config::plugin_ml2_config:
               genericswitch:arista/device_type:
                      value: ‘netmiko_arista_eos’
               genericswitch:arista/ip:
                      value: ‘172.31.9.100’
               genericswitch:arista/username:
                      value: ‘admin’
               genericswitch:arista/password:
                      value: ‘secret’

               genericswitch:arista/ngs_mac_address:
                      value: ’00:1c:73:0b:a3:df’

Note: I feel parameters used in here are self-explanatory. At minimum you need IP, user and password (or key) for the switch. The ngs_mac_address you can plug in the physical mac of the switch itself – this will help streamline consumption of newly discovered node, since Inspector will map mac learn from LLDP with the mac specified in ngs_mac_address.

If you anticipate to use multiple switches, simply create multiple entries with different genericswitch:<switch-name>/<parameter>

Note: In my example I am using Arista switch, however there is plethora of other switches available and documented here -> https://github.com/openstack/networking-generic-switch/blob/master/doc/source/configuration.rst

2. You are now ready to re-deploy your openstack cloud and enjoy multi-tenancy function in overcloud

 time openstack overcloud deploy  –templates –stack chrisj \
  -r /home/stack/templates/roles_data.yaml \
  -n /home/stack/templates/network_data.yaml \


  -e /usr/share/openstack-tripleo-heat-templates/environments/services-docker/ironic.yaml \
  -e /usr/share/openstack-tripleo-heat-templates/environments/services-docker/ironic-inspector.yaml \
  -e /home/stack/templates/ExtraConfig.yaml \
  -e /home/stack/templates/overcloud_images.yaml 

3. (optional) If you don’t take advantage of auto discovery described in one of the earlier blogs, you would need to define individual ironic ports and map them to corresponding switch and port-id. Example

openstack baremetal port delete <UUID>

openstack baremetal port create 90:b1:1c:03:9e:fd –node 028e4607-64fc-49bf-94de-0e0b2f48fcb4 –local-link-connection switch_id=00:1c:73:0b:a3:df –local-link-connection switch_info=arista –local-link-connection port_id=Et11 –pxe-enabled true

APENDIX A

Here is a sneak peak into upcoming multi-tenancy driver that will be introduced together with RH OSP14 (Rocky) – networking-ansible. I happened to get my hands on re-based OSP13 (Queens) version and was able to validate it’s functionality against my juniper ex2200 switch (this is old and slow switch not recommended for production)

Big thank you to Dan Radez for building special version of the driver that could be used with Queen release of OpenStack (OSP13)

The steps used to configure networking-ansible with Ironic are very similar to generic-switch.

1. First configure you neutron container. Follow the steps from above, with following change to Dockerfile

(chrisj) [stack@undercloud rebuild-image]$ cat Dockerfile 
FROM 172.31.0.10:8787/rhosp13/openstack-neutron-server:13.0-58
USER root
# add packages for ansible network driver
ADD /python2-networking-ansible-2.0.0-1.el7_radez.noarch.rpm /python2-networking-ansible-2.0.0-1.el7_radez.noarch.rpm
ADD /python2-ansible-runner-1.0.5-1.el7.noarch.rpm /python2-ansible-runner-1.0.5-1.el7.noarch.rpm
ADD /python2-pexpect-4.6-1.el7.noarch.rpm /python2-pexpect-4.6-1.el7.noarch.rpm
ADD /ansible-role-openstack-ml2-2.0.0-1.el7_radez.noarch.rpm /ansible-role-openstack-ml2-2.0.0-1.el7_radez.noarch.rpm
ADD /ansible-2.5.2-1.el7.ans.noarch.rpm /ansible-2.5.2-1.el7.ans.noarch.rpm
ADD /python2-ptyprocess-0.5.2-3.el7.noarch.rpm /python2-ptyprocess-0.5.2-3.el7.noarch.rpm
ADD /python-daemon-1.6-5.1.el7.noarch.rpm /python-daemon-1.6-5.1.el7.noarch.rpm
ADD /python-lockfile-0.9.1-5.1.el7.noarch.rpm /python-lockfile-0.9.1-5.1.el7.noarch.rpm
#ADD /python-neutron-13.0.0-1.el7.noarch.rpm /python-neutron-13.0.0-1.el7.noarch.rpm
#ADD /python2-ryu-4.26-1.el7.noarch.rpm /python2-ryu-4.26-1.el7.noarch.rpm
#ADD /python-ryu-common-4.26-1.el7.noarch.rpm /python-ryu-common-4.26-1.el7.noarch.rpm
#ADD /python2-openvswitch-2.9.0-3.el7.noarch.rpm /python2-openvswitch-2.9.0-3.el7.noarch.rpm

#install ansible ml2 driver
RUN yum -y install python2-networking-ansible-2.0.0-1.el7_radez.noarch.rpm python2-ansible-runner-1.0.5-1.el7.noarch.rpm python2-pexpect-4.6-1.el7.noarch.rpm ansible-role-openstack-ml2-2.0.0-1.el7_radez.noarch.rpm python2-ptyprocess-0.5.2-3.el7.noarch.rpm ansible-2.5.2-1.el7.ans.noarch.rpm python-daemon-1.6-5.1.el7.noarch.rpm python-lockfile-0.9.1-5.1.el7.noarch.rpm
 

2. Configure multi-tenancy parameters in parameter_defaults:

  # Ironic Multi-tenancy
  IronicProvisioningNetwork: baremetal
  NeutronMechanismDrivers: openvswitch,ansible
  IronicEnabledNetworkInterfaces: flat,noop,neutron
  IronicDefaultNetworkInterface: neutron
  ControllerExtraConfig:
     neutron::config::plugin_ml2_config:
               ansible:ex2200/ansible_network_os:
                      value: ‘junos’
               ansible:ex2200/ansible_host:
                      value: ‘172.31.8.254’
               ansible:ex2200/ansible_user:
                      value: ‘ansible’
               ansible:ex2200/ansible_password:
                      value: ‘secret’

               ansible:ex2200/manage_vlans:
                      value: ‘False’

3. Re-deploy and enjoy multitenancy with Baremetal nodes

Leave a Reply

Your email address will not be published. Required fields are marked *