This will walk you through how to make a L2 shell in python for CloudShell 7.1.
- First, have API access to a CloudShell server
- Install PyCharm and the PyCharm CloudShell plugin
- Install shellfoundry with
pip install shellfoundry
- 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 shellnamewhere
shellnameis 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
- 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.
- In the src directory, we want to add add a method called
get_inventorywhich 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
- There is now a .zip file in the
- 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
Implementing L2 Capabilities
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
ApplyConnectivityChangeswith 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
requestin 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.