FlexSwitch on Whitebox Hardware

This document explains the steps required to install the SnapRoute FlexSwitch Network OS on a white box switch running ONIE (Open Network Install Environment). Initial configuration is done using the device’s console port, with the management port used for the ONIE kick process.


Image Deployment

ONIE can be used to build out a provisioning environment to automatically deploy images via DHCP and HTTP. Alternatively, it can be used to manually deploy a single image on a single device with the ONIE console. Both methods are outlined below.

Example Environment

For the purposes of this document, a clean install of Ubuntu 14.04 Server is used as the host device.

Setting Up a Basic ONIE Kick Environment

Any host can take on the role of an ONIE image server, the only requirements are an HTTP server to host the images and DHCP to serve the URL. The following instructions explain the process of setting up a new server to fulfill the image hosting requirements. If a new server is not required, use these steps as a reference for configuration.

Setup the HTTP Server to Host Images

1) Update apt-get package lists.

server$ sudo apt-get update

2) Install the apache2 package to serve as http server.

server$ sudo apt-get install apache2

3) Create a directory on the in the root www directory for storing ONIE images.

server$ sudo mkdir -p /var/www/html/onie

4) Copy the ONIE image to /var/www/html/onie and validate.

server$ cp image_path /var/www/html/onie

server$ ls /var/www/html/onie/
ONL-FlexSwitch-2.0.0.26.0_AMD64_INSTALLER

5) Test image download from another host.

server$ wget http://10.1.10.200/onie/ONL-FlexSwitch-2.0.0.26.0_AMD64_INSTALLER

Setup the DHCP Server

1) Update the apt-get package lists.

server$ sudo apt-get update

2) Install apache2 package to serve as http server.

server$ sudo apt-get install isc-dhcp-server

3) Modify the DHCP configuration to serve an IP and an ONIE image URL to the target switch.

server$ sudo vi /etc/dhcp/dhcpd.conf

Sample Config:

option domain-name-servers 8.8.8.8, 8.8.4.4;
default-lease-time 86400;
max-lease-time 86400;
log-facility local7;

subnet 10.1.10.0 netmask 255.255.255.0 {
    option routers 10.1.10.1;
    range 10.1.10.2 10.1.10.100;
    option default-url = "http://10.1.10.200/onie/ONL-FlexSwitch-2.0.0.26.0_AMD64_INSTALLER";
}

As shown above, the default-url DHCP option is used to tell ONIE where to pull the image from.

4) For the configurations changes to /etc/dhcp/dhcpd.conf to take affect, the service must be restarted:

server$ sudo service isc-dhcp-server restart

Installing FlexSwith via ONIE with DHCP

After the DHCP and HTTP servers are installed and configured, the target switch should discover the ONIE image URL via DHCP and download it automatically.

The following is an output example from the console of an ONIE image installation via DHCP.

** Installer Mode Enabled **
ONIE:/ # 

Info: Sleeping for 20 seconds 
4..3..2..1..Info: eth0:  Checking link... up.
Info: Trying DHCPv4 on interface: eth0
ONIE: Using DHCPv4 addr: eth0: 10.1.10.2 / 255.255.255.0
ONIE: Starting ONIE Service Discovery
Info: Fetching http://10.1.10.200/onie/ONL-FlexSwitch-2.0.0.26.0_AMD64_INSTALLER ...
ONIE: Executing installer: http://10.1.10.200/onie/ONL-FlexSwitch-2.0.0.26.0_AMD64_INSTALLER
Verifying image checksum ... OK.
Preparing image archive ... OK.

The example above shows that the target device is receiving an IP address via DHCP of 10.1.10.2, being served the URL to download the ONIE image, then proceeding to download the image and verify the checksum.

Installing FlexSwitch Manually with an Image URL

ONIE offers a method of manually installing an image, other than of using a default-url served by DHCP. All that is required is a DHCP address served to the device and IP reachability to an HTTP server hosting the ONIE image.

1) Attach to the target device via the console port and access the ONIE shell. Until interrupted, ONIE loops in discovery mode, trying to download a bootable image for the device.

ONIE:/ # 
Info: Sleeping for 20 seconds 
4..3..2..1..Info: eth0:  Checking link... up.
Info: Trying DHCPv4 on interface: eth0
ONIE: Using DHCPv4 addr: eth0: 10.1.10.2 / 255.255.255.0
ONIE: Starting ONIE Service Discovery
Info: Fetching http://10.1.10.200/onie-installer-x86_64-accton_wedge100_32x-r0 ...
Info: Fetching http://10.1.10.200/onie-installer-x86_64-accton_wedge100_32x ...
Info: Fetching http://10.1.10.200/onie-installer-accton_wedge100_32x ...
Info: Fetching http://10.1.10.200/onie-installer-x86_64-bcm ...
Info: Fetching http://10.1.10.200/onie-installer-x86_64 ...
Info: Fetching http://10.1.10.200/onie-installer ...

2) Press the Enter key several times to interrupt the discovery process and gain access to the BusyBox ONIE console.

3) Use the ifconfig command to verify that the management interface is receiving an IP address via DHCP.

ONIE:/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 00:E0:EC:26:A7:5B
          inet addr:10.1.10.2  Bcast:10.1.10.255  Mask:255.255.255.0

If eth0 has a link, but is not receiving a DHCP address – ONIE defaults to using 192.168.3.10.

ONIE:/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 00:E0:EC:26:A7:5B  
          inet addr:192.168.3.10  Bcast:192.168.3.255  Mask:255.255.255.0

4) Use the install_url command to tell ONIE to manually install an image.

ONIE:/ # install_url http://10.1.10.2/onie/ONL-FlexSwitch-2.0.0.26.0_AMD64_INSTALLER
Stopping: discover... done.
Info: Fetching http://10.1.10.2/onie/ONL-FlexSwitch-2.0.0.26.0_AMD64_INSTALLER ...

5) After the image download is complete, ONIE verifies the checksum and proceeds with the installation.

Booting Into the ONIE Console

If remote access via SSH is not available or the OS is in a failed state an ONIE re-kick can be initiated via a console session:

1) Connect a console cable and configure the host device or terminal server with the console settings documented for the target device

2) If the device is accessible issue a “sudo reboot” from the console, otherwise physically power-cycle the switch\

Warning

On ARM-based platforms extra steps are required to allow u-boot to boot into ONIE. Scroll down to the section Booting Into the ONIE Console on ARM Platforms for more information

When presented with the GRUB menu, select “ONIE” and press :

                     GNU GRUB  version 2.02~beta2+e4a1fe391

 +----------------------------------------------------------------------------+
 | OpenNetworkLinux                                                           | 
 |*ONIE                                                                       |
 |                                                                            |
 |                                                                            |
 |                                                                            |
 |                                                                            |
 |                                                                            |
 |                                                                            |
 |                                                                            |
 |                                                                            |
 |                                                                            |
 |                                                                            | 
 +----------------------------------------------------------------------------+

      Use the ^ and v keys to select which entry is highlighted.          
      Press enter to boot the selected OS, `e' to edit the commands       
      before booting or `c' for a command-line.            

The asterisk indicates which option is selected. There is a several second timeout for the default option (in this example: OpenNetworkLinux), so it is important to quickly press an arrow key to change the GRUB menu option.

3) When the ONIE menu is displayed, select “ONIE: Install OS”:

                    GNU GRUB  version 2.02~beta2+e4a1fe391

 +----------------------------------------------------------------------------+
 |*ONIE: Install OS                                                           | 
 | ONIE: Rescue                                                               |
 | ONIE: Uninstall OS                                                         |
 | ONIE: Update ONIE                                                          |
 | ONIE: Embed ONIE                                                           |
 |                                                                            |
 |                                                                            |
 |                                                                            |
 |                                                                            |
 |                                                                            |
 |                                                                            |
 |                                                                            | 
 +----------------------------------------------------------------------------+

      Use the ^ and v keys to select which entry is highlighted.          
      Press enter to boot the selected OS, `e' to edit the commands       
      before booting or `c' for a command-line.

The "ONIE: Uninstall OS" option may be required if the ONIE installer fails to partition the flash. When using the uninstall mode, ONIE removes the NOS and clears the flash partitions. After the uninstall is complete, ONIE automatically restarts in the “ONIE: Install OS” mode.

When the ONIE:/ # prompt is available, the steps for loading an image via ONIE can be followed (either DHCP or Manual Install).

Booting Into the ONIE Console on ARM Platforms

For ARM-based platforms - such as the Edgecore AS4610 U-Boot commands are required to allow the device to boot into ONIE.

1) Connect a console cable and configure the host device or terminal server with the console settings documented for the target device.

2) Power-cycle the device and wait for the prompt to "stop autoboot"

USB0:  Bringing USB2 host out of reset...
Net:   eth-0
Hit any key to stop autoboot:  0 
accton_as4610-54-> 

3) Issue the "setenv onie_boot_reason install" command at the u-boot prompt

accton_as4610-54-> setenv onie_boot_reason install

4) Use "boot" to boot into the ONIE console

accton_as4610-54-> boot
Loading Open Network Install Environment ...
Platform: arm-accton_as4610_54-r0
Version : master-201705311146
## Booting kernel from FIT Image at 70000000 ...

Now the device should be at the ONIE prompt:

ONIE:/ # 

With the device at the ONIE prompt - the steps in the Manual Install Method section can be followed or allow the device to auto-install the NOS via ONIE.

Note

If the device has an older version of ONIE installed - it may be required to use the command "run onie_load" in place of "setenv onie_boot_reason install" during Step 3 and then "bootm" instead of "boot" during Step 4.

Appliance Mode

Starting with version 2.0.0.11.0, FlexSwitch is distributed with ONL and FlexSwitch bundled into a single installer and boots by default into the FlexSwitch CLI.

After installation, the user is prompted for login credentials:

Open Network Linux OS ONL-2.0.0, 2017-08-31.20:41-dafe190

localhost login: admin
Password: snaproute

After logging in as admin for the first time, the systems will prompt for the password to be changed from the default of snaproute:

You are required to change your password immediately (root enforced)
Changing password for admin.
(current) UNIX password: 
Enter new UNIX password: 
Retype new UNIX password: 

After the default password is updated, the CLI is automatically loaded:

Linux localhost 3.2.71-OpenNetworkLinux #1 SMP Thu Aug 31 20:59:34 UTC 2017 armv7l
FlexSwitch

loading schema...
loading model...
 _______  __       __________   ___      _______.____    __    ____  __  .___________.  ______  __    __
|   ____||  |     |   ____\  \ /  /     /       |\   \  /  \  /   / |  | |           | /      ||  |  |  |
|  |__   |  |     |  |__   \  V  /     |   (----` \   \/    \/   /  |  | `---|  |----`|  ,----'|  |__|  |
|   __|  |  |     |   __|   >   <       \   \      \            /   |  |     |  |     |  |     |   __   |
|  |     |  `----.|  |____ /  .  \  .----)   |      \    /\    /    |  |     |  |     |  `----.|  |  |  |
|__|     |_______||_______/__/ \__\ |_______/        \__/  \__/     |__|     |__|      \______||__|  |__|
                                _______  __       __ 
                               /       ||  |     |  |
                              |   ,----||  |     |  |
                              |   |     |  |     |  |
                              |   `----.|  `----.|  |
                               \_______||_______||__|

FlexSwitch Console Version 1.0.0.190, Connected to: switch Version 2.0.0.26.0
Using snap style cli

switch>

Accessing the Shell From Appliance Mode

The shell command can be issued from the Appliance Mode CLI to access the underlying Linux OS:

switch> enable
switch# shell
switch$ 

Entering into the Linux shell will change the prompt from switch# to switch$. Commands in this guide that require the Linux shell begin with the shell$ prompt.

More information about using the FlexSwitch CLI can be found at Accessing the Command Line Interface page.

Disaggregated Mode

Alternatively, FlexSwitch can be installed as a Debian package - independent from the installed ONL version. This was the default distribution method prior to version 2.0.0.11.0.

Base Linux NOS

After the ONL image installation, grub is modified to add an entry for the newly installed Network Operating System (NOS) and the device will reboot into the new OS.

The NOS is indexed as OpenNetworkLinux in grub and is based on Debian 8 Jessie.

Note

The initial login credentials are (ONL version ONL-2.0.0_ONL-OS_2017-05-24.X and later):
Username: admin
Password: snaproute

The password must be changed after the initial login.

Previous to ONL-2.0.0_ONL-OS_2017-05-24.X, the default username is root:
Username: root
Password: snaproute

The management interface is represented as ma1 and has a default configuration of DHCP in /etc/network/interfaces.

switch$ cat /etc/network/interfaces
iface ma1 inet dhcp
auto ma1

Reinstall NOS

During the course of deployment, it may become necessary to re-kick a device by forcing ONIE to run on the next reboot. This prevents the need to reboot with a console attached and manually changing the grub selection during boot.

Force grub to boot into the ONIE menu option during the next reboot.

switch$ sudo onl-onie-boot-mode install

If there is a need to clear the above action and revert grub to the default.

switch$ sudo onl-onie-boot-mode none

Warning

This command is not supported on ARM-based platforms currently (such as the AS4610) - see Booting Into the ONIE Console on ARM Platforms for more information.

Note

If remote access via SSH is not available or the OS is in a failed state an ONIE re-kick can be initiated via a console session: Booting Into the ONIE Console

FlexSwitch Package Installation

The SnapRoute FlexSwitch network protocol stack and accompanying toolchain is provided as an installable Debian dpkg package. The package and can be added to a local repository or installed manually, as shown below.

All required package dependencies are included in the ONL image provided by SnapRoute.

1) Copy the FlexSwitch package to the device.

switch$ wget http://10.1.10.2/debs/flexswitch_bcmsdk-release_1.0.0.190.16_amd64.deb

2) Install FlexSwitch using dpkg.

switch$ sudo dpkg -i flexswitch_bcmsdk-release_1.0.0.190.16_amd64.deb

3) After the package installs, use the ps command to verify that the FlexSwitch daemons are running.

switch$ ps -efa | grep flexswitch
root      3776     1  1 00:36 ?        00:01:07 /opt/flexswitch/bin/sysd -params=/opt/flexswitch/params
root      3783     1 17 00:36 ?        00:19:36 /opt/flexswitch/bin/asicd -params=/opt/flexswitch/params
root      3786     1  0 00:36 ?        00:00:13 /opt/flexswitch/bin/lacpd -params=/opt/flexswitch/params
root      3792     1  0 00:36 ?        00:00:13 /opt/flexswitch/bin/stpd -params=/opt/flexswitch/params
root      3803     1  0 00:36 ?        00:00:13 /opt/flexswitch/bin/lldpd -params=/opt/flexswitch/params
root      3811     1  0 00:36 ?        00:00:16 /opt/flexswitch/bin/arpd -params=/opt/flexswitch/params
root      3815     1  0 00:36 ?        00:00:20 /opt/flexswitch/bin/ribd -params=/opt/flexswitch/params
root      3828     1  0 00:36 ?        00:00:13 /opt/flexswitch/bin/bfdd -params=/opt/flexswitch/params
root      3834     1  0 00:36 ?        00:00:05 /opt/flexswitch/bin/bgpd -params=/opt/flexswitch/params
root      3845     1  0 00:36 ?        00:00:13 /opt/flexswitch/bin/ospfv2d -params=/opt/flexswitch/params
root      3853     1  0 00:36 ?        00:00:12 /opt/flexswitch/bin/dhcpd -params=/opt/flexswitch/params
root      3863     1  0 00:36 ?        00:00:13 /opt/flexswitch/bin/dhcprelayd -params=/opt/flexswitch/params
root      3870     1  0 00:36 ?        00:00:13 /opt/flexswitch/bin/vrrpd -params=/opt/flexswitch/params
root      3876     1  0 00:36 ?        00:00:15 /opt/flexswitch/bin/vxland -params=/opt/flexswitch/params
root      3890     1  0 00:36 ?        00:00:13 /opt/flexswitch/bin/ndpd -params=/opt/flexswitch/params
root      3899     1  0 00:36 ?        00:00:03 /opt/flexswitch/bin/platformd -params=/opt/flexswitch/params
root      3906     1  0 00:36 ?        00:00:06 /opt/flexswitch/bin/fMgrd -params=/opt/flexswitch/params
root      3907     1  0 00:36 ?        00:00:03 /opt/flexswitch/bin/notifierd -params=/opt/flexswitch/params
root      3930     1  0 00:36 ?        00:00:13 /opt/flexswitch/bin/statsd -params=/opt/flexswitch/params
root      3934     1  0 00:36 ?        00:00:04 /opt/flexswitch/bin/confd -params=/opt/flexswitch/params
root      4452  4444  0 02:25 pts/0    00:00:00 grep flexswitch

Configuring FlexSwitch

SnapRoute FlexSwitch utilizes REST APIs for configuration and management of the device. The configuration is stored in a Redis DB. For the purposes of this example, 10.1.10.2 is used in place of the IP for the device being configured.

Swagger UI

FlexSwitch uses a Swagger framework for documenting REST APIs. It documents the available APIs in the installed version of FlexSwitch, as well as the details for all of the associated parameters.

Swagger is accessible on the device directly via this URL:

https://192.168.100.119/api-docs/

Note

The "/" after /api-docs/ is required and Swagger will not load without the forward slash at the end of the URL.

Swagger is hosted on the device using an embedded nginx https server. This means that the self-signed certificate needs to be accepted by the user. The first time the URL is accessed by a web browser, a window similar to this will be seen:

Swagger SSL Screen 1

Follow the instructions specific to the web browser to allow for the an exception to the certificate policy. In the above example (Safari) - simply clicking Continue will allow the site to load.

After accepting the certificate, a login page will be presented:

Swagger SSL Screen 2

Once authenticated, the main Swagger page is available - with the full list of APIs supported by the current version:

Swagger SSL Screen 3

Browser Based JSON

APIs can be called in a web browser directly with the data presented in JSON. A JSON plugin, such as JSONView for Chrome can be used to format the JSON in a more readable format.

APIs are categorized as either state or config objects.

https://192.168.100.119/public/v1/state/{object}
https://192.168.100.119/public/v1/config/{object}

Config objects are the result of user configuration and represent the desired parameters for configured elements (i.e. what the user wants to the config to be). State objects are the current run-time status of each configured element (i.e. what the status actually is).

Config View

Using the “config” URL for a given object will yield the parameters that are configured for that object.   This URL can be used to view the configured parameters for all VLANs:

https://192.168.100.119/public/v1/config/Vlans

Vlan Config REST Result 1

The example above shows that vlan 100 is configured on the switch with fpPort1 set as access or untagged, non-trunked ports in that vlan (UntagIntfList). Also, the UUID for this vlan is returned, which can be used for referencing this vlan in a programmaticly. Trunk ports are defined using IntfList and cannot intersect ports listed under UntagIntfList, meaning that a port cannot be both a trunk and an access port at the same time.

State View

Using the state URL for a given object will yield the parameters that reflect the runtime status of these objects.

The following URL can be used to view the state parameters for all VLANs:

https://192.168.100.119/public/v1/state/Vlans Vlan Config REST Result 2

The example above shows the state information for the configured vlan 100, as well as two internal vlans; 3050 and 3051. These internal vlans are used to represent a layer-3 physical interface (an interface that does not belong to a configured vlan and has an IP assigned directly to it). The OperState shows that vlan 100 is in the “UP” state, while the 2 internal vlans are “DOWN”. Also outlined are the “IfIndex” values for each vlan – which can be used for reference or configuration.

REST API Examples

VLANs

In this example, three new VLANs are created and front-panel ports are assigned to them.

Using the Swagger UI, information about the Vlan API can be displayed:

Vlan Config Swagger 1

Clicking POST shows that the valid parameters for the Vlan API are VlanId, IntfList, and UntagIntfList.

This Swagger UI interface can be used to build the curl command to perform the REST call.

Vlan Config Swagger 2

In the example above; vlan 100 is defined, with ports fpPorts1-10 assigned as untagged (or access ports) and fpPort11 set as a trunk port (because vlans are tagged).

Swagger generates the curl and executes it.

Vlan Config Swagger 3

The following example is a curl command generated by Swagger.

curl -k -X POST --header 'Content-Type: application/x-www-form-urlencoded' --header 'Accept: application/json' -d '{"VlanId":100,"AdminState":"UP","Description":"none","AutoState":"UP","IntfList":["fpPort11"],"UntagIntfList":["fpPort1,fpPort2,fpPort3,fpPort4,fpPort5,fpPort6,fpPort7,fpPort8,fpPort9,fpPort10"]}' 'https://192.168.100.119/public/v1/config/Vlan'

Since the curl command was executed directly from the Swagger interface - no authentication was required - as the commands are run local to the device itself - and credentials were used to access the Swagger UI page.

Therefore, to execute the above curl command to configure Vlan 100 as described, the command will need to be altered to be used either local to the device or remotely via IP.

Using the API locally:

When logged into the device via SSH or console, it is possible to run curl commands directly on the device - if the configured user has sufficient access:

switch$ curl -k -X POST --header 'Content-Type: application/x-www-form-urlencoded' --header 'Accept: application/json' -d '{"VlanId":100,"AdminState":"UP","Description":"none","AutoState":"UP","IntfList":["fpPort11"],"UntagIntfList":["fpPort1,fpPort2,fpPort3,fpPort4,fpPort5,fpPort6,fpPort7,fpPort8,fpPort9,fpPort10"]}' 'http://localhost:8080/public/v1/config/Vlan'

Note

Notice in the above example that the https is changed to http and localhost is used as the IP with a port of 8080. Otherwise, the command is unchanged.

Using the API remotely:

server$ curl -k -u admin -X POST --header 'Content-Type: application/x-www-form-urlencoded' --header 'Accept: application/json' -d '{"VlanId":100,"AdminState":"UP","Description":"none","AutoState":"UP","IntfList":["fpPort11"],"UntagIntfList":["fpPort1,fpPort2,fpPort3,fpPort4,fpPort5,fpPort6,fpPort7,fpPort8,fpPort9,fpPort10"]}' 'https://192.168.100.119/public/v1/config/Vlan'

Enter host password for user 'admin':

Note

The command generated by Swagger has the necessary https and IP address - all that is required is the addition of the username at the beginning of the curl, using the -u option as shown above.

The Swagger UI is also displaying the Request URL for this API: https://192.168.100.119/public/v1/config/Vlan

This URL can be used in a browser with a JSON viewer to query the API. Note that the URL needs to be updated to the IP of the target device. Also, if a bulk get is desired an s can be appended to the API name to return all of the configured vlans.

https://192.168.100.119/public/v1/config/Vlans

Vlan Config Swagger 4

These curl commands create vlans 100, 200, and 300 and assign fpPorts 1-10 to vlan 100, fpPort 12 to vlan 200, and fPport 13 to vlan 300. fpPort 11 is a trunk carrying all 3 vlans.

In these examples the APIs are being run remotely with the admin user.

Create Vlan 100:

server$ curl -k -u admin -X POST --header 'Accept: application/json' -d '{"VlanId":100,"AdminState":"UP","Description":"none","AutoState":"UP","IntfList":["fpPort11"],"UntagIntfList":["fpPort1,fpPort2,fpPort3,fpPort4,fpPort5,fpPort6,fpPort7,fpPort8,fpPort9,fpPort10"]}' 'https://192.168.100.119/public/v1/config/Vlan'

Response:

{"Access-Control-Allow-Origin":"*","Access-Control-Allow-Headers":"Origin, X-Requested-With, Content-Type, Accept","Access-Control-Allow-Methods":"POST, GET, OPTIONS, PATCH, DELETE","Access-Control-Max_age":"86400","ObjectId":"c9708cb7-3b79-4a9e-4493-81aeb244df8c","Result":"Success"}

Create Vlan 200:

server$ curl -k -u admin -X POST --header 'Accept: application/json' -d '{"VlanId":200,"AdminState":"UP","Description":"none","AutoState":"UP","IntfList":["fpPort11"],"UntagIntfList":["fpPort12"]}' 'https://192.168.100.119/public/v1/config/Vlan'

Response:

{"Access-Control-Allow-Origin":"*","Access-Control-Allow-Headers":"Origin, X-Requested-With, Content-Type, Accept","Access-Control-Allow-Methods":"POST, GET, OPTIONS, PATCH, DELETE","Access-Control-Max_age":"86400","ObjectId":"87d2fd13-f3b7-4f37-61ff-af77f177cf14","Result":"Success"}

Create Vlan 300:

server$ curl -k -u admin -X POST --header 'Accept: application/json' -d '{"VlanId":300,"AdminState":"UP","Description":"none","AutoState":"UP","IntfList":["fpPort11"],"UntagIntfList":["fpPort13"]}' 'https://192.168.100.119/public/v1/config/Vlan'

Response:

{"Access-Control-Allow-Origin":"*","Access-Control-Allow-Headers":"Origin, X-Requested-With, Content-Type, Accept","Access-Control-Allow-Methods":"POST, GET, OPTIONS, PATCH, DELETE","Access-Control-Max_age":"86400","ObjectId":"eb2ef324-5598-4fd6-51e9-9d37c5b3ba24","Result":"Success"}

The example above shows that the port-list is supplied as a comma-separated list of interfaces. Also, notice that a unique ObjectId or UUID is returned after each vlan creation and can be used to reference that vlan in future API calls. Finally, all configuration calls will return a Result string - in this case it returns Success.

Assigning IP Addresses

Now that there are 3 vlans on the device, IP addresses can be assigned, creating SVIs for each vlan.

Referencing the Swagger UI, notice there is a IPv4Intf API:

IPv4Intf Config Swagger 1

This shows the parameters for IPv4Intf are IntRef, IpAddr, and AdminState. IntRef can be either the IfIndex or the name of the interface.

In this example, the name of the interface is used to assign an IP address to each of the three vlans.

server$ curl -k -u admin -X POST --header 'Accept: application/json' -d '{"IntfRef":"vlan100","IpAddr":"10.10.100.1/24","AdminState":"UP"}' 'https://192.168.100.119/public/v1/config/IPv4Intf'

server$ curl -k -u admin -X POST --header 'Accept: application/json' -d '{"IntfRef":"vlan200","IpAddr":"10.10.101.1/24","AdminState":"UP"}' 'https://192.168.100.119/public/v1/config/IPv4Intf'

server$ curl -k -u admin -X POST --header 'Accept: application/json' -d '{"IntfRef":"vlan300","IpAddr":"10.10.102.1/24","AdminState":"UP"}' 'https://192.168.100.119/public/v1/config/IPv4Intf'

Querying for state shows these IP addresses are configured, but the vlan interfaces are in a “DOWN” state.

https://192.168.100.119/public/v1/state/IPv4Intfs

Ipv4Intfs State REST Result 1

A GET query can also be used to display this same information.

server$ curl -k -u admin -X GET --header 'Accept: application/json' -d '{}' 'https://192.168.100.119/public/v1/state/IPv4Intfs' | python -m json.tool

Piping the output to the python JSON tool allows for a pretty print of the output.

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   859  100   857  100     2  42339     98 --:--:-- --:--:-- --:--:-- 47611
{
    "CurrentMarker": 0,
    "MoreExist": false,
    "NextMarker": 3,
    "ObjCount": 3,
    "Objects": [
        {
            "Object": {
                "IfIndex": 33554532,
                "IntfRef": "vlan100",
                "IpAddr": "10.10.100.1/24",
                "L2IntfId": 100,
                "L2IntfType": "vlan",
                "LastDownEventTime": "",
                "LastUpEventTime": "",
                "NumDownEvents": 0,
                "NumUpEvents": 0,
                "OperState": "DOWN"
            },
            "ObjectId": "73fa7167-e696-4952-42cf-65c30ca63b3d"
        },
        {
            "Object": {
                "IfIndex": 33554632,
                "IntfRef": "vlan200",
                "IpAddr": "10.10.101.1/24",
                "L2IntfId": 200,
                "L2IntfType": "vlan",
                "LastDownEventTime": "",
                "LastUpEventTime": "",
                "NumDownEvents": 0,
                "NumUpEvents": 0,
                "OperState": "DOWN"
            },
            "ObjectId": "89475f2d-ecf2-40ef-545c-da986cb842e5"
        },
        {
            "Object": {
                "IfIndex": 33554732,
                "IntfRef": "vlan300",
                "IpAddr": "10.10.102.1/24",
                "L2IntfId": 300,
                "L2IntfType": "vlan",
                "LastDownEventTime": "",
                "LastUpEventTime": "",
                "NumDownEvents": 0,
                "NumUpEvents": 0,
                "OperState": "DOWN"
            },
            "ObjectId": "6c594973-1d52-4a31-7aa9-491a8b7e9067"
        }
    ]
}

As shown above, vlan100 is in the DOWN state even though there is a host connected to port 1 on the switch.

Setting Port Parameters

Using the IntRef parameter for the Port state API, the current operational state of fpPort 1 can be retrieved.

server$ curl -k -u admin -X GET --header 'Accept: application/json' -d '{"IntfRef":"fpPort1"}' 'https://192.168.100.119/public/v1/state/Port' | python -m json.tool
Enter host password for user 'admin':
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   920  100   899  100    21   154k   3692 --:--:-- --:--:-- --:--:--  175k
{
    "Object": {
        "ConfigMode": "L2",
        "DscpToCosProfileRef": "default",
        "ErrDisableReason": "",
        "IfEtherBcastPkts": 0,
        "IfEtherCRCAlignError": 0,
        "IfEtherFragments": 0,
        "IfEtherJabber": 0,
        "IfEtherMCPkts": 0,
        "IfEtherOverSizePktCnt": 0,
        "IfEtherPkts": 0,
        "IfEtherPkts1024To1518Octets": 0,
        "IfEtherPkts128To255Octets": 0,
        "IfEtherPkts256To511Octets": 0,
        "IfEtherPkts512To1023Octets": 0,
        "IfEtherPkts64OrLessOctets": 0,
        "IfEtherPkts65To127Octets": 0,
        "IfEtherUnderSizePktCnt": 0,
        "IfInDiscards": 0,
        "IfInErrors": 0,
        "IfInOctets": 0,
        "IfInUcastPkts": 0,
        "IfInUnknownProtos": 0,
        "IfIndex": 145,
        "IfOutDiscards": 0,
        "IfOutErrors": 0,
        "IfOutOctets": 0,
        "IfOutUcastPkts": 0,
        "IntfRef": "fpPort1",
        "LastDownEventTime": "",
        "LastUpEventTime": "",
        "Name": "fpPort1",
        "NumDownEvents": 0,
        "NumUpEvents": 0,
        "OperState": "DOWN",
        "PRBSRxErrCnt": 0,
        "PcpToCosProfileRef": "default",
        "PresentInHW": "YES",
        "Pvid": 100,
        "SchedProfileRef": "default"
    },
    "ObjectId": "b359db2f-33b6-4f23-70fd-647f5484aee7"
}

The example above shows the state of the interface which is DOWN, as indicated in the following example.

"OperState": "DOWN",

Further information about this interface can be obtained via the Port config API.

server$ curl -k -u admin -X GET --header 'Accept: application/json' -d '{"IntfRef":"fpPort1"}' 'https://192.168.100.119/public/v1/config/Port' | python -m json.tool
Enter host password for user 'admin':
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   542  100   521  100    21  29713   1197 --:--:-- --:--:-- --:--:-- 43416
{
    "Object": {
        "AdminState": "DOWN",
        "Autoneg": "OFF",
        "BreakOutMode": "1x100",
        "Description": "",
        "DscpToCosProfileRef": "default",
        "Duplex": "Full_Duplex",
        "EnableFEC": false,
        "IfIndex": 145,
        "IntfRef": "fpPort1",
        "LoopbackMode": "NONE",
        "MacAddr": "1a:67:8d:11:d9:ef",
        "MediaType": "Media Type",
        "Mtu": 9412,
        "PRBSPolynomial": "2^7",
        "PRBSRxEnable": false,
        "PRBSTxEnable": false,
        "PcpToCosProfileRef": "default",
        "PhyIntfType": "KR4",
        "SchedProfileRef": "default",
        "Speed": 100000,
        "StormControlProfile": "NONE"
    },
    "ObjectId": "b359db2f-33b6-4f23-70fd-647f5484aee7"
}

The example above shows some important information about this interface.

"AdminState": "DOWN",
"Speed": 100000,

By default all of the interfaces are set to an Admin State of DOWN and a default of the maximum speed of the interface - in this case 100G.

Since a 40G DAC is being used in this example, the speed needs to be set to 40000 and the Admin State to UP:

server$ curl -k -u admin -X PATCH --header 'Accept: application/json' -d '{"IntfRef":"fpPort1","AdminState":"UP","Speed":40000}' 'https://192.168.100.119/public/v1/config/Port'

This example uses a PATCH for the Port config API - as the interface already exists and only the speed and admin state need to be updated.

This response shows that the config was successful:

{"Access-Control-Allow-Origin":"*","Access-Control-Allow-Headers":"Origin, X-Requested-With, Content-Type, Accept","Access-Control-Allow-Methods":"POST, GET, OPTIONS, PATCH, DELETE","Access-Control-Max_age":"86400","ObjectId":"b359db2f-33b6-4f23-70fd-647f5484aee7","Result":"Success"}

Warning

Subsequently, if there is an attempt to configure an unsupported speed (in this case 100M) - an error is returned:

server$ curl -k -u admin -X PATCH --header 'Accept: application/json' -d '{"IntfRef":"fpPort1","AdminState":"UP","Speed":100}' 'https://192.168.100.119/public/v1/config/Port'

{"Access-Control-Allow-Origin":"*","Access-Control-Allow-Headers":"Origin, X-Requested-With, Content-Type, Accept","Access-Control-Allow-Methods":"POST, GET, OPTIONS, PATCH, DELETE","Access-Control-Max_age":"86400","ObjectId":"b359db2f-33b6-4f23-70fd-647f5484aee7","Result":"Internal error processing UpdatePort: Failed to update port configuration"}

After issuing the PATCH for Admin State and Speed, the port has an OperState of UP:

server$ curl -k -u admin -X GET --header 'Accept: application/json' -d '{"IntfRef":"fpPort1"}' 'https://192.168.100.119/public/v1/state/Port' | python -m json.tool
Enter host password for user 'admin':
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1049  100  1028  100    21  74476   1521 --:--:-- --:--:-- --:--:-- 79076
{
    "Object": {
        "ConfigMode": "L2",
        "DscpToCosProfileRef": "default",
        "ErrDisableReason": "",
        "IfEtherBcastPkts": 13285888,
        "IfEtherCRCAlignError": 0,
        "IfEtherFragments": 0,
        "IfEtherJabber": 0,
        "IfEtherMCPkts": 0,
        "IfEtherOverSizePktCnt": 0,
        "IfEtherPkts": 19913829,
        "IfEtherPkts1024To1518Octets": 0,
        "IfEtherPkts128To255Octets": 0,
        "IfEtherPkts256To511Octets": 0,
        "IfEtherPkts512To1023Octets": 0,
        "IfEtherPkts64OrLessOctets": 19913829,
        "IfEtherPkts65To127Octets": 0,
        "IfEtherUnderSizePktCnt": 0,
        "IfInDiscards": 6627914,
        "IfInErrors": 0,
        "IfInOctets": 806105600,
        "IfInUcastPkts": 688137,
        "IfInUnknownProtos": 0,
        "IfIndex": 145,
        "IfOutDiscards": 0,
        "IfOutErrors": 0,
        "IfOutOctets": 468379456,
        "IfOutUcastPkts": 5939804,
        "IntfRef": "fpPort1",
        "LastDownEventTime": "2012-01-01 01:45:42.59442351 +0000 UTC",
        "LastUpEventTime": "2012-01-01 01:45:43.107185471 +0000 UTC",
        "Name": "fpPort1",
        "NumDownEvents": 1,
        "NumUpEvents": 2,
        "OperState": "UP",
        "PRBSRxErrCnt": 0,
        "PcpToCosProfileRef": "default",
        "PresentInHW": "YES",
        "Pvid": 100,
        "SchedProfileRef": "default"
    },
    "ObjectId": "b359db2f-33b6-4f23-70fd-647f5484aee7"
}

VLAN Status

The OperState of Vlan 100 is now UP – since there is now an active port in that vlan:

server$ curl -k -u admin -X GET --header 'Accept: application/json' -d '{"VlanId":100}' 'https://192.168.100.119/public/v1/state/Vlan' | python -m json.tool
Enter host password for user 'admin':
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   174  100   160  100    14  10368    907 --:--:-- --:--:-- --:--:-- 10666
{
    "Object": {
        "IfIndex": 33554532,
        "Name": "vlan100",
        "OperState": "UP",
        "SysInternalDescription": "",
        "VlanId": 100
    },
    "ObjectId": "c9708cb7-3b79-4a9e-4493-81aeb244df8c"
}

Linux Integration

In addition to FlexSwitch APIs, these vlans with IP addresses also appear in Linux:

switch$ sudo ifconfig | grep -A 7 "vlan"

vlan100   Link encap:Ethernet  HWaddr a8:2b:b5:43:c2:c1  
          inet addr:10.10.100.1  Bcast:0.0.0.0  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:410 (410.0 B)

vlan200   Link encap:Ethernet  HWaddr a8:2b:b5:43:c2:c1  
          inet addr:10.10.101.1  Bcast:0.0.0.0  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:188 (188.0 B)

vlan300   Link encap:Ethernet  HWaddr a8:2b:b5:43:c2:c1  
          inet addr:10.10.102.1  Bcast:0.0.0.0  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:110 (110.0 B)

switch$ sudo netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         192.168.100.1   0.0.0.0         UG        0 0          0 ma1
10.10.100.0     0.0.0.0         255.255.255.0   U         0 0          0 vlan100
10.10.101.0     0.0.0.0         255.255.255.0   U         0 0          0 vlan200
10.10.102.0     0.0.0.0         255.255.255.0   U         0 0          0 vlan300
192.168.100.0   0.0.0.0         255.255.255.0   U         0 0          0 ma1

VLAN SVIs in the Routing Table

Now that the SVI for vlan 100 is UP – it has an entry in the hardware routing table, as is programmed on the ASIC:

https://192.168.100.119/public/v1/state/IPv4Routes

Ipv4Routes State REST Result 1

Clearing the Configuration with ResetConfig API

An API is available to clear the FlexSwitch configurations without the need to restart the daemons.

server$ curl -k -u admin -X POST 'https://192.168.100.119/public/v1/action/ResetConfig'

This Result of Success indicates that the configuration reset was successful and the configuration is now back to the default:

{"Result":"Success","Message":"Requested API is executing in background. Query for result using handle ResetConfig1503097874"}

Manually Flush the Configuration Database

If there is a need to manually flush the entire configuration database Redis can be managed directly to clear the database.

1) Enter the CLI for Redis:

switch$ sudo redis-cli flushdb
OK

2) Restart FlexSwitch service:

switch$ sudo service flexswitch restart
[....] Restarting flexswitch: flexswitchStopping Daemon confd

This causes FlexSwitch to restart with an empty Redis database.  

Configuration with JSON

FlexSwitch is bundled with a tool for managing the the device configuration as flat JSON-formatted files.

Save the Current Configuration as a JSON file

Use the monitor.py configuration utility to save the current running configuration.

switch$ cd /opt/flexswitch/apps/cfgmon/
switch$ python monitor.py --saveConfig

When finished, the utility shows the location of the configuration file.

Configuration is saved to /opt/flexswitch//runningConfig.json

Bug

The above should state that the configuration is saved to /opt/flexswitch/startup-config.json

Examining this generated configuration file shows the expected JSON format.

switch$ cat /opt/flexswitch/startup-config.json
{
    "ConfigData": {
        "IPv4Intf": [
            {
                "IntfRef": "vlan100",
                "IpAddr": "10.10.100.1/24",
                "AdminState": "UP"
            },
            {
                "IntfRef": "vlan200",
                "IpAddr": "10.10.101.1/24",
                "AdminState": "UP"
            },
            {
                "IntfRef": "vlan300",
                "IpAddr": "10.10.102.1/24",
                "AdminState": "UP"
            }
        ],
...

Apply a Configuration With a JSON File

Using the previous REST API examples, a JSON file ( desiredConfig.json ) is used to configure the following:

  • Vlan 100 with fpPorts 1-10 and IP address 10.10.100.1/24
  • Vlan 200 with fpPort 12 and IP address 10.10.101.1/24
  • Vlan 300 with fpPort 13 and IP address 10.10.102.1/24
  • fpPort 11 is a trunk carrying vlans 100, 200, and 300 - tagged.
  • Speed is set to 40G for fpPort 1.

Example desiredConfig.json:

{
    "ConfigData": {
        "IPv4Intf": [
            {
                "IntfRef": "vlan100",
                "IpAddr": "10.10.100.1/24",
                "AdminState": "UP"
            },
            {
                "IntfRef": "vlan200",
                "IpAddr": "10.10.101.1/24",
                "AdminState": "UP"
            },
            {
                "IntfRef": "vlan300",
                "IpAddr": "10.10.102.1/24",
                "AdminState": "UP"
            }
        ],
        "Port": [
            {
                "IntfRef": "fpPort1",
                "AdminState": "UP",
                "Speed": 40000
            }
        ],
        "Vlan": [
            {
                "VlanId": 100,
                "AdminState": "UP",
                "Description": "none",
                "AutoState": "UP",
                "IntfList": [
                    "fpPort11"
                ],
                "UntagIntfList": [
                    "fpPort1,fpPort2,fpPort3,fpPort4,fpPort5,fpPort6,fpPort7,fpPort8,fpPort9,fpPort10"
                ]
            },
            {
                "VlanId": 200,
                "AdminState": "UP",
                "Description": "none",
                "AutoState": "UP",
                "IntfList": [
                    "fpPort11"
                ],
                "UntagIntfList": [
                    "fpPort12"
                ]
            },
            {
                "VlanId": 300,
                "AdminState": "UP",
                "Description": "none",
                "AutoState": "UP",
                "IntfList": [
                    "fpPort11"
                ],
                "UntagIntfList": [
                    "fpPort13"
                ]
            }
        ]
    }
}

This JSON file is declarative and not order-dependent, all configurations are ingested at once and executed in the order required.

Apply the sample configuration using the configuration utility:

1) Add JSON configuration to desiredConfig.json (creating the file, if necessary).

switch$ sudo vi /opt/flexswitch/desiredConfig.json

2) Apply the configuration using monitor.py.

switch$ cd /opt/flexswitch/apps/cfgmon/
switch$ python monitor.py --applyConfig

Once the configuration is applied, the operational state can be verified.

https://192.168.100.119/public/v1/state/IPv4Intfs

Ipv4Routes State JSON Result 1

Ansible Integration

Utilizing the JSON file configuration method, it is possible to utilize automation tools like Ansible to manage FlexSwitch.

Setup the Ansible Environment

Prior to utilizing Ansible to manage FlexSwitch, a working Ansible environment must be built.

1) Follow the Operating System appropriate instructions to install Ansible on the desired host.

Ansible Installation

For the purposes of this guide, these steps were performed on an Ubuntu Server running 14.04.

server$ sudo apt-get install software-properties-common
server$ sudo apt-add-repository ppa:ansible/ansible
server$ sudo apt-get update
server$ sudo apt-get install ansible

2) Generate an SSH key for Ansible to use for managing devices.

server$ ssh-keygen

In this example a passphrase is not used and the key is stored in the default location.

/home/ansible/.ssh/id_rsa.pub

3) The generated SSH key must be added to the root user of the device, enabling SSH management by Ansible.

On the device to be managed by Ansible:

switch$ sudo mkdir -p /root/.ssh/
switch$ sudo vi /root/.ssh/authorized_keys

Add the contents of id_rsa.pub from the user on the device running Ansible to the authorized_keys file.

The id_rsa.pub contents should be one line and follow this format:

ssh-rsa <snip> ansible@ansible-server.snaproute.com

4) Add a target host to /etc/ansible/hosts.

server$ sudo vi /etc/ansible/hosts

Add hosts as either IP or resolvable hostname, one on each line. The /etc/ansible/hosts inventory file can be a simple list of hosts or it can be more complex and define groups as outlined in the example.

The following is an example of the contents of the Ansible inventory file.

server$ cat /etc/ansible/hosts
10.1.10.2

5) The ssh key can be tested by issuing a ping from Ansible.

server$ ansible -u root -m ping all

10.1.10.2 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

The example above shows a successful ping response using the remote root user, because that is the user which houses the SSH key on the target system.

Managing FlexSwitch with Ansible

Once Ansible is installed and working with the device, it is possible to manage FlexSwitch configurations.

The following example deploys the JSON configuration file referenced previously.

1) Confirm target host is listed in the Ansible inventory file.

server$ cat /etc/ansible/hosts
10.1.10.2

2) Create directories for playbooks, templates, and host_vars.

server$ sudo mkdir -p /etc/ansible/playbooks
server$ sudo mkdir -p /etc/ansible/templates
server$ sudo mkdir -p /etc/ansible/host_vars

3) Convert the previously deployed JSON configuration into a template.

Ansible uses the Jinja2 Python templating language for building variable-based configuration files.

Jinja2 uses the following syntax for specifying a variable in a template file:

{{ variable_name }}

Using this method of templating, the JSON configuration from the previous example can be templatized:

{
    "ConfigData": {
        "IPv4Intf": [
            {
                "IntfRef": "vlan{{ vlan_1 }}",
                "IpAddr": "{{ vlan_1_ip }}/{{ vlan_cidr_bits }}",
                "AdminState": "UP"
            },
            {
                "IntfRef": "vlan{{ vlan_2 }}",
                "IpAddr": "{{ vlan_2_ip }}/{{ vlan_cidr_bits }}",
                "AdminState": "UP"
            },
            {
                "IntfRef": "vlan{{ vlan_3 }}",
                "IpAddr": "{{ vlan_3_ip }}/{{ vlan_cidr_bits }}",
                "AdminState": "UP"
            }
        ],
        "Port": [
            {
                "IntfRef": "fpPort1",
                "AdminState": "UP",
                "Speed": {{ port_1_speed }}
            }
        ],
        "Vlan": [
            {
                "VlanId": {{ vlan_1 }},
                "AdminState": "UP",
                "Description": "none",
                "AutoState": "UP",
                "IntfList": [
                    "{{ trunk_port_1 }}"
                ],
                "UntagIntfList": [
                    "{{ vlan_1_port_list }}"
                ]
            },
            {
                "VlanId": {{ vlan_2 }},
                "AdminState": "UP",
                "Description": "none",
                "AutoState": "UP",
                "IntfList": [
                    "{{ trunk_port_1 }}"
                ],
                "UntagIntfList": [
                    "{{ vlan_2_port_list }}"
                ]
            },
            {
                "VlanId": {{ vlan_3 }},
                "AdminState": "UP",
                "Description": "none",
                "AutoState": "UP",
                "IntfList": [
                    "{{ trunk_port_1 }}"
                ],
                "UntagIntfList": [
                    "{{ vlan_3_port_list }}"
                ]
            }
        ]
    }
}

Save the template above in this location.

/etc/ansible/templates/flexswitch_example.j2

4) Assign values to the variables used in the template.

Ansible has a flexible structure for assigning variables to hosts and groups, allowing for a hierarchy to be built.

For the following example, variables will be defined for this specific target host.

vlan_1: 100
vlan_2: 200
vlan_3: 300
vlan_1_port_list: fpPort1,fpPort2,fpPort3,fpPort4,fpPort5,fpPort6,fpPort7,fpPort8,fpPort9,fpPort10
vlan_2_port_list: fpPort12
vlan_3_port_list: fpPort13
trunk_port_1: fpPort11
vlan_1_ip: 10.10.100.1
vlan_2_ip: 10.10.101.1
vlan_3_ip: 10.10.102.1
vlan_cidr_bits: 24
port_1_speed: 40000

Save the lines shown above to this file:

/etc/ansible/host_vars/10.1.10.2

5) Build Ansible playbook.

With the template and host_vars files in place, all that is required is an Ansible playbook that builds the FlexSwitch config file and deploys it to the target device.

This playbook does the following:

  • Uses apt-get to install FlexSwitch (if it is not already installed).
  • Ensures that FlexSwitch is currently running.
  • Builds the desiredConfig.json file based on the flexswitch_example.j2 template.
  • The monitory.py application is run to apply the new configuration whenever there is a change to desiredConfig.json (i.e. a variable or the template is updated).

Example Ansible playbook:

---
- hosts: all
  remote_user: root 
  tasks:
  - name: ensure flexswitch is installed
    apt:
      name: flexswitch=1.0.0.190.16
      state: present
      update_cache: yes
      force: yes
  - name: ensure flexswitch is running
    service:
      name: flexswitch
      state: started
  - name: configure flexswitch
    template:
      src: /etc/ansible/templates/flexswitch_example.j2
      dest: /opt/flexswitch/desiredConfig.json
      force: yes
    notify:
    - load flexswitch config
  handlers:
    - name: load flexswitch config
      command: chdir=/opt/flexswitch/apps/cfgmon python monitor.py --applyConfig

The example above assumes that apt-get has been configured to point at a repo that contains the FlexSwitch package (in this case version 1.0.0.190.16) or that FlexSwitch has been manually installed.

Save the playbook as:

/etc/ansible/playbooks/flexswitch.yml

6) Run playbook to configure FlexSwitch.

Using the ansible-playbook command the previously configured playbook can be run to apply FlexSwitch configs to the target host.

server$ ansible-playbook flexswitch.yml 

PLAY [all] *********************************************************************

TASK [setup] *******************************************************************
ok: [10.1.10.2]

TASK [ensure flexswitch is installed] ******************************************
ok: [10.1.10.2]

TASK [ensure flexswitch is running] ********************************************
changed: [10.1.10.2]

TASK [configure flexswitch] ****************************************************
changed: [10.1.10.2]

RUNNING HANDLER [load flexswitch config] ***************************************
changed: [10.1.10.2]

PLAY RECAP *********************************************************************
10.1.10.2                 : ok=5    changed=3    unreachable=0    failed=0   

The output above shows the playbook was successfully applied to 10.1.10.2, indicating which tasks caused changes to be applied. Since this is the first run of the playbook and the target device had no configurations, the result is changed for each of the configuration tasks.

A subsequent run, where neither the variables or the template is updated results in a playbook run where nothing is changed is shown below.

server$ ansible-playbook flexswitch.yml 

PLAY [all] *********************************************************************

TASK [setup] *******************************************************************
ok: [10.1.10.2]

TASK [ensure flexswitch is installed] ******************************************
ok: [10.1.10.2]

TASK [ensure flexswitch is running] ********************************************
changed: [10.1.10.2]

TASK [configure flexswitch] ****************************************************
ok: [10.1.10.2]

PLAY RECAP *********************************************************************
10.1.10.2                 : ok=4    changed=1    unreachable=0    failed=0   

Note

The ensure flexswitch is running task may show “changed” even if FlexSwitch is already running (it will not reload FlexSwitch).

Supporting Documentation

ONIE

OpenBMC

Swagger

JSONView for Chrome

Ansible

Jinja2