bigsuds
33 TopicsManaging ZoneRunner Resource Records with Bigsuds
Over the last several years, there have been questions internal and external on how to manage ZoneRunner (the GUI tool in F5 DNS that allows you to manage DNS zones and records) resources via the REST interface. But that's a no can do with the iControl REST--it doesn't have that functionality. It was brought to my attention by one of our solutions engineers that a customer is using some methods in the SOAP interface that allows you to do just that...which was news to me! The things you learn... In this article, I'll highlight a few of the methods available to you and work on a sample domain in the python module bigsuds that utilizes the suds SOAP library for communication duties with the BIG-IP iControl SOAP interface. Test Domain & Procedure For demonstration purposes, I'll create a domain in the external view, dctest1.local, with the following attributes that mirrors nearly identically one I created in the GUI: Type: master Zone Name: dctest1.local. Zone File Name: db.external.dctest1.local. Options: allow-update from localhost TTL: 500 SOA: ns1.dctest1.local. Email: hostmaster.ns1.dctest1.local. Serial: 2021092201 Refresh: 10800 Retry: 3600 Expire: 604800 Negative TTL: 60 I'll also add a couple type A records to that domain: name: mail.dctest1.local., address: 10.0.2.25, TTL: 86400 name: www.dctest1.local., address: 10.0.2.80, TTL: 3600 After adding the records, I'll update one of them, changing the IP and the TTL: name: mail.dctest1.local., address: 10.0.2.110, ttl: 900 Then I'll delete the other one: name: www.dctest1.local., address: 10.0.2.80, TTL: 3600 And finally, I'll delete the zone: name: dctest1.local. ZoneRunner Methods All the methods can be found on Clouddocs in the ZoneRunner, Zone, and ResourceRecord method pages. The specific methods we'll use in our highlight real are: Management.ResourceRecord.add_a Management.ResourceRecord.delete_a Management.ResourceRecord.get_rrs Management.ResourceRecord.update_a Management.Zone.add_zone_text Management.Zone.get_zone_v2 Management.Zone.zone_exist With each method, there is a data structure that the interface expects. Each link above provides the details, but let's look at an example with the add_a method. The method requires three parameters, view_zones, a_records, and sync_ptrs, which the image of the table shows below. The boolean is just a True/False value in a list. The reason the list ( [] ) is there for all the attributes is because you can send a single request to update more than one zone, and addmore than one record within each zone if desired. The data structure for view_zones and a_records is in the following two images. Now that we have an idea of what the methods require, let's take a look at some code! Methods In Action First, I import bigsuds and initialize the BIG-IP. The arguments are ordered in bigsuds for host, username, and password. If the default “admin/admin” is used, they are assumed, as is shown here. import bigsuds b = bigsuds.BIGIP(hostname='ltm3.test.local') Next, I need to format the ViewZone data in a native python dictionary, and then I check for the existence of that zone. zone_view = {'view_name': 'external', 'zone_name': 'dctest1.local.' } b.Management.Zone.zone_exist([zone_view]) # [0] Note that the return value, which should be a list of booleans, is a list with a 0. I’m guessing that’s either suds or the bigsuds implementation doing that, but it’s important to note if you’re checking for a boolean False. It’s also necessary to set the booleans as 0 or 1 as well when sending requests to BIG-IP with bigsuds. Now I will create the zone since it does not yet exist. From the add_zone_text method description on Clouddocs, note that I need to supply, in separate parameters, the zone info, the appropriate zone records, and the boolean to sync reverse records or not. zone_add_info = {'view_name': 'external', 'zone_name': 'dctest1.local.', 'zone_type': 'MASTER', 'zone_file': 'db.external.dctest1.local.', 'option_seq': ['allow-update { localhost;};']} zone_add_records = 'dctest1.local. 500 IN SOA ns1.dctest1.local. hostmaster.ns1.dctest1.local. 2021092201 10800 3600 604800 60;\n' \ 'dctest1.local. 3600 IN NS ns1.dctest1.local.;\n' \ 'ns1.dctest1.local. 3600 IN A 10.0.2.1;' b.Management.Zone.add_zone_text([zone_add_info], [[zone_add_records]], [0]) b.Management.Zone.zone_exist([zone_view]) # [1] Note that the strings here require a detailed understanding of DNS record formatting, the individual fields are not parameters that can be set like in the ZoneRunner GUI. But, I am confident there is an abundance of modules that manage DNS formatting in the python ecosystem that could simplify the data structuring. After creating the zone, another check to see if the zone exists results in a true condition. Huzzah! Now I’ll check the zone info and the existing records for that zone. zone = b.Management.Zone.get_zone_v2([zone_view]) for k, v in zone[0].items(): print(f'{k}: {v}') # view_name: external # zone_name: dctest1.local. # zone_type: MASTER # zone_file: "db.external.dctest1.local." # option_seq: ['allow-update { localhost;};'] rrs = b.Management.ResourceRecord.get_rrs([zone_view]) for rr in rrs[0]: print(rr) # dctest1.local. 500 IN SOA ns1.dctest1.local. hostmaster.ns1.dctest1.local. 2021092201 10800 3600 604800 60 # dctest1.local. 3600 IN NS ns1.dctest1.local. # ns1.dctest1.local. 3600 IN A 10.0.2.1 Everything checks outs! Next I’ll create the A records for the mail and www services. I’m going to add a filter to only check for the mail/www services for printing to cut down on the lines, but know that they’re still there going forward. a1 = {'domain_name': 'mail.dctest1.local.', 'ip_address': '10.0.2.25', 'ttl': 86400} a2 = {'domain_name': 'www.dctest1.local.', 'ip_address': '10.0.2.80', 'ttl': 3600} b.Management.ResourceRecord.add_a(view_zones=[zone_view], a_records=[[a1, a2]], sync_ptrs=[0]) rrs = b.Management.ResourceRecord.get_rrs([zone_view]) for rr in rrs[0]: if any(item in rr for item in ['mail', 'www']): print(rr) # mail.dctest1.local. 86400 IN A 10.0.2.25 # www.dctest1.local. 3600 IN A 10.0.2.80 Here you can see that I’m adding two records to the zone specified and not creating the reverse records (not included for brevity, but in prod would be likely). Now I’ll update the mail address and TTL. b.Management.ResourceRecord.update_a([zone_view], [[a1]], [[a1_update]], [0]) rrs = b.Management.ResourceRecord.get_rrs([zone_view]) for rr in rrs[0]: if any(item in rr for item in ['mail', 'www']): print(rr) # mail.dctest1.local. 900 IN A 10.0.2.110 # www.dctest1.local. 3600 IN A 10.0.2.80 You can see that the address and TTL updated as expected. Note that with the update_/N/ methods, you need to provide the old and new, not just the new. Let’s get destruction and delete the www record! b.Management.ResourceRecord.delete_a([zone_view], [[a2]], [0]) rrs = b.Management.ResourceRecord.get_rrs([zone_view]) for rr in rrs[0]: if any(item in rr for item in ['mail', 'www']): print(rr) # mail.dctest1.local. 900 IN A 10.0.2.110 And your web service is now unreachable via DNS. Congratulations! But there’s more damage we can do: it’s time to delete the whole zone. b.Management.Zone.delete_zone([zone_view]) b.Management.Zone.zone_exist([zone_view]) # [0] And that’s a wrap! As I said, it’s been years since I have spent time with the iControl SOAP interface. It’s nice to know that even though most of what we do is done through REST, imperatively or declaratively, that some missing functionality in that interface is still alive and kicking via SOAP. H/T to Scott Huddy for the nudge to investigate this. Questions? Drop me a comment below. Happy coding! A gist of these samples is available on GitHub.999Views2likes1CommentPython data class values
I have some python code (bigsuds) I use to display data class members names but do not know how to display the data group values. What I would like is to output the following name value name value name value Any help would be appreciated. def member_list(b,name): try: data = b.get_string_class([name]) except Exception, e: print e for x in data: myclass = x print name for m in myclass['members']: print m b = f5.LocalLB.Class member_list(b,'classname')899Views0likes8CommentsConfig Backup for F5 Review
Eric Flores, author of Config Backup for F5, will be joining John Wagnon and I for a podcast this evening to discuss his project. This open source project is great for the shops that don't have budget for the robust feature sets of Enterprise Manager and BIG-IQ. The bits are offered as a downloadable tgz, or more attractively for those that want something to just work right out of the box, a VMware appliance! For this review, I opted for the latter. One of the more frustrating this about most small pet projects on github, sourceforge, and the like is the crazy lack of good documentation. That is not the case with Eric's project. The backup appliance documentation left no step undocumented, and the user guide is well documented as well, removing almost all the guess work. Deploying the appliance was very easy and the install process clean and tidy, but a few things I'd clarify in the documentation or enhance: Make sure the nic on the appliance belongs to a network that has access to your BIG-IPs before powering it up, though, the default nic the appliance grabbed in my workstation was a bridged network my BIG-IPs don't belong to. The NTP configuration specified an IP, but it would be nice to support names. It may already as I didn't try to add a name, but it would be good to support both and state that in the configuration utility. The NTP configuration utility had my local time and UTC swapped in the display, but in the appliance web GUI it appears fine. I went through the NTP configuration a second time with similar results, so I'm guessing just a variable swap here? Once the appliance was configured and rebooted, I logged in to the web GUI. This is very straight forward and cleanly laid out very similarly to the F5 GUI. The user guide goes through the user functions (devices, backup jobs, certificates) first, but I'd recommend configuring the settings first. In the Backup Settings, you set the backup time and the user name and password. This is important, as no device you add will be touched until this information is present. After updating the backup settings, I added my device. I added/deleted a couple times before changing my backup time and I was wondering what wasn't working. It turns out the initial discovery of the device isn't done until the backup time occurs. I'd recommend in future enhancements to go ahead and do the device discovery shown in this screen and the Certificates screen when the device is added rather than waiting for the backup window. Other than those few minor nits, this is a fantastic effort on Eric's part, and a great testament to the power of community. Thanks Eric for sharing and we look forward to seeing what enhancements and features you have in store for this project! Technorati Tags: Config Backup for F5,Eric Flores,iControl,bigsuds844Views0likes6CommentsGet All Pool Member Status Using LTM, Python, and bigsuds
Problem this snippet solves: I spent a bit of time trying to get this to work. Delivering the data in the correct format to the get_member_session_status method took me a while, so I thought I would post my solution. Code : #!/usr/bin/env python import sys import bigsuds def get_pools(obj): try: return obj.LocalLB.Pool.get_list() except Exception, e: print e def get_members(obj, pool): try: return pool, obj.LocalLB.Pool.get_member_v2(pool) except Exception, e: print e def get_status(obj, pool): try: return obj.LocalLB.Pool.get_member_session_status(pool) except Exception, e: print e try: b = bigsuds.BIGIP( hostname = “ ”, username = "admin", password = “admin”, ) except Exception, e: print e pools = get_pools(b) members = get_members(b, pools) for pool in pools: print "Pool: %s" % pool members = b.LocalLB.Pool.get_member_v2([pool]) status = b.LocalLB.Pool.get_member_session_status([pool], members) print "\tMembers:" for members, status in zip(members, status): count = 0 while count < len(members): print "\t\tHost: %s\tState: %s" % (members[count]["address"], status[count]) count += 1 Tested this on version: 11.6800Views0likes3CommentsBigSuds - bigsuds.ConnectionError: BadStatusLine: ''
On a certain F5 (V11) I keep getting a Connecti : BasStatusLine: '' Looks like BigSuds is getting back a response that is making puke Anyone have any bright ideas? 2014-08-17 18:10:28 INFO: Retrieving interface statistics... 2014-08-17 18:10:28 DEBUG: Executing iControl method: Networking.Interfaces.get_statistics((['mgmt', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7', '1.8', '2.1', '2.2'],), {}) Traceback (most recent call last): File "/opt/f5collect/f5-agent.py", line 715, in main() File "/opt/f5collect/f5-agent.py", line 678, in main metric_list = gather_f5_metrics(ltm_host, user, password, prefix, remote_ts) File "/opt/f5collect/f5-agent.py", line 330, in gather_f5_metrics int_stats = b.Networking.Interfaces.get_statistics(interfaces) File "/usr/local/lib/python2.7/dist-packages/bigsuds-1.0.1-py2.7.egg/bigsuds.py", line 430, in wrapped_method raise Connecti ('BadStatusLine: %s' % e) bigsuds.Connecti : BadStatusLine: ''528Views0likes14CommentsBigsuds - How to enable / disable certain pool members?
Hello all, this is my first post here, to quickly introduce myself - I'm Aled, I work in London (GB) for an online gaming company. I'm currently getting an automated deployment system in place for Continuous Intergration and the part I'm struggling with is automating the BigIP loadbalancer pools which brings me to my question: Here's what I'm trying to achieve, for an automated web deployment I need to disable half the pool members for a given Loadbalanced Pool, and then re-enable them post deployment. Then disable the other half of the pool members and re-enable them post deployment too. So I need a way to disable pool members and to specify which pool members to disable and vice versa. Ive been reading a lot about Bigsuds and I'm very impressed by this and the whole iControl system. I've played around with this within python and can access the BigIP appliance and display pools etc., but I cant figure out the code I need to do the above. I was hoping it would be something like this... b.LocalLB.PoolMember.set_session_enabled_state(pool_names = ['poolnamehere'], members = ['10.10.10.10:80', '10.10.10.11:80'], session_states = ['STATE_ENABLED'], [1]) This doesnt work, Ive got the syntax wrong and its probably not as simple as that. Can anyone help please? Let me know if you need more info etc.. Thanks Aled404Views0likes6CommentsiApp elements in iControl (bigsuds)
I have two LTM boxes running BigIP 11.5 on which I configured several iApps. Now I'd like to use iControl to check the pool/node status, statistics, enable and disable nodes, etc. However, I can't get a list of the iApps and pools configured. Here's what I tried using the (awesome!) bigsuds library: bs = bigsuds.BIGIP(hostname="my_ltm_box", username="my_username", password="some_pass") print bs.Management.ApplicationService.get_list() print bs.LocalLB.Pool.get_list() I would expect at least the first, but preferably also the second print out a list of items. But both commands return an empty list (I currently don't have any pools configured normally, only through iApps, though when I add one it gets listed). To make it even a bit more confusing, the listing of nodes works (both for normally configured nodes as for nodes configured in an iApp): print bs.LocalLB.NodeAddressV2.get_list() Am I missing something? How can I find out which iApps are configured and more importantly, how can I find the pools and possibly other elements related to these iApps, since they don't seem to be available through the regular API calls.Solved383Views0likes2CommentsGet current connection of pool members
Hi, I tried write a script (python) to checking numeber current connection and when is 0 mark member 'disabled'. How can I get only value of current connection and then check is 0 ? member_stat = b.LocalLB.Pool.get_member_statistics( ['/Common/' + pool], [[{'address': member, 'port': port}]]) for statistic in member_stat: .... if ( 'STATISTIC_SERVER_SIDE_CURRENT_CONNECTIONS' == 0 ) : pl.set_member_session_enabled_state(['/Common/' + pool ], [[{'address': member, 'port': port}]], [['STATE_DISABLED']]) pl.set_member_monitor_state(['/Common/' + pool ], [[{'address': member, 'port': port}]], [['STATE_DISABLED']])377Views0likes2Comments