Creating an L2 Shell in CloudShell 7.1

Creating an L2 Shell in CloudShell 7.1

High Level

This will walk you through how to make a L2 shell in python for CloudShell 7.1.



  • Note that the Shell is a term used to describe a driver (automation code) and any metadata associated with it, including the resource structure, family/model definition, any arbitrary attribtues we are tracking, etc.

Building the Shell

Getting the Template

  • Open up your terminal. CD to your Desktop and run shellfoundry new --template networking/switch shellname where shellname is the name you want to give to this shell
  • The shellfoundry command needs to be in PATH for this to work. If not, on a Windows system it is probably in C:\Program Files (x86)\QualiSystems\TestShell\ExecutionServer\python\2.7.10\Scripts
  • Open PyCharm and open the directory you just created. Here it would be Desktop\shellname
  • The default resource structure for the shell has a chassis, blades, ports, and attributes already set. You can use this guide to clean up that XML or change it to work how you want.

Implementing Autoload

  • In the src directory, we want to add add a method called get_inventory which will automatically be called when you add a new instance of this resource using this shell. It will use that method to autodiscover the sub resources of that resource (blades, ports, etc).
  • There is a guide here that will explain how to write that method.
  • Of note, you must change the config XML mentioned in this guide to tell it the shell supports autoload!
  • Now we will upload the shell to the server. First we need to pack it. Go back to your console, cd to Desktop\shellname and run shellfoundry pack
  • There is now a .zip file in the dist folder
  • Open CloudShell, login as an admin, and drag and drop this zip folder into the CloudShell tab (if using Chrome). Otherwise click on your username in the top right of CloudShell and press "Import Package" and point to the zip file
  • This will import the shell. It will now ask you to create an instance of a resource using this shell. You will notice the last step is it will auto inventory that device using the code in the get_inventory method

Implementing L2 Capabilities

Mapping Connectivity

Just like using any other L2 or L1 device, you must map connectivity:

  • Open Resource Manager and login as an admin
  • Right click on the resource you just created above that was autoloaded and click "Configuration"
  • At the bottom, choose "Connections"
  • Add the L1 connectivity as described here


  • If you change driver logic, you can press the CloudShell icon in the top right of PyCharm to push the new driver to CloudShell. Note that this pushes the driver code, not the entire shell! If you want to push the shell, you need to repack it using shellfoundry and upload it.
  • Create a new method called ApplyConnectivityChanges with the signature below

def ApplyConnectivityChanges(self, context, request): """ Configures VLANs on multiple ports or port-channels :param ResourceCommandContext context: The context object for the command with resource and reservation info :param str request: A JSON object with the list of requested connectivity changes :return: a json object with the list of connectivity changes which were carried out by the switch :rtype: str """ """ :type context: drivercontext.ResourceCommandContext :type json: str """

  • To see a working example, click here

  • Also need to add this XML to the drivermetadata.xml

    <Command Name="ApplyConnectivityChanges" DisplayName="ApplyConnectivityChanges" Tags="allow_unreserved"> <Parameters> <Parameter Name="request" Type="String" Mandatory = "True" DefaultValue="" Description=""/> </Parameters> </Command>

  • This will take in request in the form of json. You can parse that, do any device-specific logic you need to provision the circuit, then return back json to let CloudShell know it worked

  • The json format is listed here

  • This method will automatically be called whenever you draw a connection between devices. This resource doesn't even need to be in the reservation

  • Note that it will automatically reserve a VLAN when this is called, as seen in the JSON. This is freed up when the connection is removed. The logic for this is explained here.