pyControl v2 – Understanding the TypeFactory
I admit it—I’ve been away from pyControl working on some other hot stove projects. When pyControl v2 launched in December, I ported some of the lighter scripts I’d written, but I put aside the scripts that required creating objects on the BIG-IP via iControl. After receiving a request to create a region in GTM via pyControl, I figured it was time to spend some energy learning the new techniques.
Background
The GTM Region is a user-defined collection of records that an administrator can use for topology decisions. I’ve created one in the GUI for use later in the article:
The Methods
Sometimes the methods are a little tricky to find, but in this case I know I need to create a GTM Region, so the GlobalLB::Region interface seemed like a pretty appropriate place to start. The methods we’re interested in are in the list below, complete with any additional information we’ll need to write the script.
- get_list – Gets a list of region definitions
- parameters – none
- get_region_item – Gets the list of region items that define the specified regions
- parameters - regions
- create – Creates the specified region definitions with the specified region items
- parameters
- regions
- parameters
- name (ie, myTestRegion)
- db_type (REGION_DB_TYPE_USER_DEFINED)
- parameters
- items
- parameters
- content (ie, US/Colorado)
- type (REGION_TYPE_STATE)
- negate (False)
- parameters
- regions
- parameters
Retrieve the Current Regions
It’s always a little easier for me to work backwards, retrieving the data I’m going to set so I can get a feel for the format. Let’s start with a simple query for the region I created in the GUI. I removed the default regions returned for clarity
In [1]: import pycontrol.pycontrol as pc
In [2]: b = pc.BIGIP(hostname = '10.10.20.5', username = 'admin', password = 'ad
min', fromurl = True, wsdls = ['GlobalLB.Region'])
In [3]: reg = b.GlobalLB.RegionIn [4]: reg.get_list()
Out[4]:
[(GlobalLB.Region.RegionDefinition){
name = "myRegion_GUI"
db_type = "REGION_DB_TYPE_USER_DEFINED"
}]
No rocket science here. I initialized my BIG-IP and then used the get_list method to query the regions. Now, I want to return the items in the myRegion_GUI region, so I’ll use the get_region_item method for that. Again, the default region items are not shown here:
In [20]: regions = reg.get_list()
In [21]: regItems = reg.get_region_item(regions = regions)
In [22]: for x in regItems:
....: print xOUt [22]:
[(GlobalLB.Region.RegionItem){
content = "US/Illinois"
type = "REGION_TYPE_STATE"
negate = False
}, (GlobalLB.Region.RegionItem){
content = "US/Missouri"
type = "REGION_TYPE_STATE"
negate = False
}]
In both sets of returned data, you’ll notice the parameters are all populated with information that will be required for creation. As provided in the method definitions above, we’ll set the same parameter values when we create a new region.
Creating the Region Items
First thing we need to do is look at the parameters required in building the typefactory
In [35]: reg.create.params
Out[35]:
[(regions, u'GlobalLB.Region.RegionDefinitionSequence'),
(items, u'GlobalLB.Region.RegionItemSequenceSequence')]
So, from this output, we’ll need to build a RegionItem, a RegionItemSequence, and a RegionDefinition. The final script will require a file to be supplied for the region contents, one content entry per line with no quotes. For now, we’ll just define them in a list.
In [25]: regions = ['US/Illinois', 'US/Missouri']
In [26]: print regions
-------> print(regions)
['US/Illinois', 'US/Missouri']
Next, we’ll build the region item type and populate with the type and negate parameters.
In [27]: reg_list = []
In [28]: for x in range(1,len(regions)+1):
....: x = reg.typefactory.create('GlobalLB.Region.RegionItem')
....: x.type = 'REGION_TYPE_STATE'
....: x.negate = False
....: reg_list.append(x)
....:
....:In [29]: print reg_list
-------> print(reg_list)
[(GlobalLB.Region.RegionItem){
content = None
type = "REGION_TYPE_STATE"
negate = False
}, (GlobalLB.Region.RegionItem){
content = None
type = "REGION_TYPE_STATE"
negate = False
}]
Notice the content above is None. Now we can loop through our items and populate the content attribute:
In [30]: for index,region in enumerate(regions):
....: reg_list[index].content = region
....:
....:In [31]: print reg_list
-------> print(reg_list)
[(GlobalLB.Region.RegionItem){
content = "US/Illinois"
type = "REGION_TYPE_STATE"
negate = False
}, (GlobalLB.Region.RegionItem){
content = "US/Missouri"
type = "REGION_TYPE_STATE"
negate = False
}]
Now that we have our content defined, we can create the sequence type and add the region items, then create the region definition type as well:
In [36]: reg_seq = reg.typefactory.create('GlobalLB.Region.RegionItemSequence')
In [37]: reg_seq.item = reg_listIn [38]: reg_def = reg.typefactory.create('GlobalLB.Region.RegionDefinition')
In [39]: reg_def.name = 'myRegion_pyControl'
In [40]: reg_def.db_type = 'REGION_DB_TYPE_USER_DEFINED'
Now that we have all our types created, we can now create the region!
In [43]: reg.create(regions = [reg_def], items = [reg_seq])
In [44]: reg.get_list()
Out[44]:
[(GlobalLB.Region.RegionDefinition){
name = "myRegion_pyControl"
db_type = "REGION_DB_TYPE_USER_DEFINED"
},
(GlobalLB.Region.RegionDefinition){
name = "myRegion_GUI"
db_type = "REGION_DB_TYPE_USER_DEFINED"
}]
And that’s it! For the full script, check out the pyControl_Create_GTM_Region codeshare sample. Happy coding!
- L4L7_53191
Nimbostratus
Excellent write up, thanks!