GithubHelp home page GithubHelp logo

f5networks / f5-common-python Goto Github PK

View Code? Open in Web Editor NEW
261.0 69.0 160.0 2.71 MB

Python SDK for configuration and monitoring of F5® BIG-IP® devices via the iControl® REST API.

Home Page: https://f5-sdk.readthedocs.org

License: Apache License 2.0

Python 99.58% Shell 0.24% Groovy 0.16% Dockerfile 0.03%
f5sdk

f5-common-python's Introduction

f5-common-python

Build Status Documentation Status Slack

NO LONGER UNDER ACTIVE DEVELOPMENT

NOTICE: This project is no longer under active development. F5 may still use internally for other project(s) but is no longer maintaining it publicly.

Introduction

This project implements an SDK for the iControl® REST interface for BIG-IP®. Use this library to use python to automate a BIG-IP® via its REST API.

Documentation

Please see the project documentation on Read the Docs: http://f5-sdk.readthedocs.io.

Installation

$ pip install f5-sdk

Note

If you are using a pre-release version you must use the --pre option for the pip command.

Usage

from f5.bigip import ManagementRoot

# Connect to the BIG-IP
mgmt = ManagementRoot("bigip.example.com", "admin", "somepassword")

# Get a list of all pools on the BigIP and print their name and their
# members' name
pools = mgmt.tm.ltm.pools.get_collection()
for pool in pools:
    print pool.name
    for member in pool.members_s.get_collection():
        print member.name

# Create a new pool on the BigIP
mypool = mgmt.tm.ltm.pools.pool.create(name='mypool', partition='Common')

# Load an existing pool and update its description
pool_a = mgmt.tm.ltm.pools.pool.load(name='mypool', partition='Common')
pool_a.description = "New description"
pool_a.update()

# Delete a pool if it exists
if mgmt.tm.ltm.pools.pool.exists(name='mypool', partition='Common'):
    pool_b = mgmt.tm.ltm.pools.pool.load(name='mypool', partition='Common')
    pool_b.delete()

Design Patterns

I intend the SDK to be easy to use and easy to hack. These overarching goals have a strong influence on my thinking when I am reviewing contributions, this means it is in their own interest that I make them as explicit as possible!

The original interface specification was given to me by Shawn Wormke, who I believe was influenced by the Jira and Django projects. At the time I was reading Brett Slatkin's 'Effective Python', and I tried to follow its advice where possible.

List of Patterns For Contributing Developers

  1. Hack this list to make it more correct/complete

    For list additions assign @zancas as the PR reviewer.

  2. The call operator () means: "Try to communicate with the device."

    This is a strong contract we offer the consumer of the SDK. If an SDK function is invoked with the call operator () the program is initiating a communication with the device. That communication may fail before reaching the wire, but it has nonetheless been initiated. Conversely, if an SDK user evaluates an SDK expression that DOES NOT invoke the () call operator, then the SDK does NOT initiate a communication with the device. Any extension to the SDK that is not consistent with this contract is unlikely to be incorporated into the supported repository.

  3. The SDK is stupid

    The SDK doesn't decide things for the consumer, it's simply an interface so that Python programs can manipulate device resources without implementing custom URI/HTTP/network logic. Implications:

    1. NO DEFAULTS
      The consumers of this library are themselves Python programs. The Application programmer must say what they mean in their SDK-using program. It violates a critical separation of concerns to add default values to the SDK. Don't do it! (Unless you have a good reason.)
    2. Failures generate exceptions
      If the SDK enters a surprising or unexpected state it raises an exception. That's it. It's not generally up to the SDK to implement decision logic that handles edge-cases.. EXCEPT where the SDK is smoothing known issues in the device REST server. (See below.)
    3. The SDK never interprets responses
      It just records whatever response the device returns as attributes of the relevant object. (Except where handling significant inconsistencies in the device interface.)
  4. public-nonpublic pairs

    e.g. 'create' and '_create' XXX add content here.

  5. Handle known issues in the device REST server.

    The SDK intends to provide a rational interface to consumers that does the right thing. This means that one case where it does NOT simply do the stupid thing is when it handles a known idiosyncrasy in the device REST server. For example, some? resources ignore 'disable' and 'enable' configuration options when they are set to 'False'. Rather than force a consumer to learn about this quirk in the server, the SDK guesses that '"disable": False' means '"enable": True' , and submits that value on the consumers behalf.

  6. Implement-Reimplement-Abstract

    Solve the problem concretely and simply, if the same problem arises again, solve it concretely, then take the two concrete solutions and use them as your specification to generate an abstraction. In the SDK this usually goes something like this:

    1. Add logic to a concrete subclass
    2. Add similar logic to another concrete subclass
    3. Create a new method in a mixin or Abstract 'resource.py' base class and have both concrete subclasses inherit and use that method.

Submodules

bigip

Python API for configuring objects on a BIG-IP® device and gathering information from the device via the REST API.

Filing Issues

See the Issues section of Contributing.

Contributing

See Contributing

Test

Before you open a pull request, your code must have passing pytest unit tests. In addition, you should include a set of functional tests written to use a real BIG-IP device for testing. Information on how to run our set of tests is included below.

Unit Tests

We use pytest for our unit tests.

  1. If you haven't already, install the required test packages listed in requirements.test.txt in your virtual environment.

    $ pip install -r requirements.test.txt
  2. Run the tests and produce a coverage report. The --cov-report=html will create a htmlcov/ directory that you can view in your browser to see the missing lines of code.

    py.test --cov ./icontrol --cov-report=html
    open htmlcov/index.html

Style Checks

We use the hacking module for our style checks (installed as part of step 1 in the Unit Test section).

$ flake8 ./

Copyright

Copyright 2014-2016 F5 Networks Inc.

License

Apache V2.0

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Contributor License Agreement

Individuals or business entities who contribute to this project must have completed and submitted the F5 Contributor License Agreement to [email protected] prior to their code submission being included in this project.

f5-common-python's People

Contributors

b225ccc avatar bastig avatar caphrim007 avatar edarzins avatar f5-rahm avatar hemantsk avatar jbnance avatar jgruber avatar jlongstaf avatar jputrino avatar kavitha-f5 avatar kmaloney avatar magnuswatn avatar mattgreene avatar nikitafedoraev avatar nkadel avatar prashantsunkari avatar preyansh91 avatar priyalpalkar avatar richbrowne avatar robbycuenot avatar sorensf5 avatar sravyap135 avatar swormke avatar szakeri avatar triangularcover avatar ujwalbendale avatar wojtek0806 avatar zancas avatar zhaoqin-github avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

f5-common-python's Issues

Get local device call fails in cluster.py with AttributeError

This issue occurs during the peering process. Here is the traceback:

Nov 09 23:12:35: delaying prior to checking hostname
Nov 09 23:12:37: set folder to /Common blindly attempting to avoid exception on get_hostname
Nov 09 23:12:37: check hostname: host-10-4-4-49.int.liTraceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/f5/onboard/bigip/cluster_generic.py", line 533, in main
    BIGIP_CLUSTER_GENERIC.set_up()
  File "/usr/lib/python2.7/dist-packages/f5/onboard/bigip/cluster_generic.py", line 103, in set_up
    self.cluster_devices(all_devices, tg_list)
  File "/usr/lib/python2.7/dist-packages/f5/onboard/bigip/cluster_generic.py", line 223, in cluster_devices
    bigip_config['password']
  File "/usr/lib/python2.7/dist-packages/f5/bigip/interfaces/__init__.py", line 235, in wrapper
    return method(*args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/f5/bigip/interfaces/cluster.py", line 333, in add_peer
    % os.path.basename(self.mgmt_dev.get_local_device())
AttributeError: 'Cluster' object has no attribute 'mgmt_dev'
neratesystems.com
Nov 09 23:12:37: host name set

Will drop this into the debugger to investigate.

Refactor bigip/__init__.py

There's a reference to a different (ltm/arp) RESTInterfaceCollection from the ltm/pool RESTInterfaceCollection. Since the BigIP object is necessarily the mediator for inter-RESTInterfaceCollection interactions, I need to refactor it now.

Refactor ltm/nat.py

Maybe this is done... in which case I guess you should just close this issue.

Does the bigip/rest_collection --> RESTInterfaceCollection.delete_all method need to exists?

The delete_all method seems to delete resources from a BigIP object in a way that is defined in the interface, i.e. it's a method of the RESTInterfaceCollection, but in a way that doesn't use any of the particular structure of the BigIP itself.

My thought is that this may be an improper location for this abstraction.

Lower level (closer to the BigIP) operations live in the appropriate interface-collection that inherits from the RESTInterfaceCollection, (e.g. a pool, or a nat) those classes support operations that make sense in the context of a pool (e.g. the delete operation of a pool systematically removes all /members of a particular ~folder~name 'd pool). So the delete operation in a pool removes multiple things, but in a way that's constrained by its definition. This seems correct to me.

A consumer of the RESTInterfaceCollection class should also be able to call its delete method with arbitrary suffixes in order to delete resources in a way that is unconstrained by the structure of the resources on the BigIP object itself.

So... in short, I don't think we should implement support for operations on the BigIP object, except those that respect the BigIP's structure, and are implemented inside the RESTInterfaceCollections that inherit from the RESTInterfaceCollection.

Add a set method to the common base class

Many of the methods in the RESTInterfaceCollection subclasses have set_* methods that all do very similar things. This can be added to the base class in a way they can use.

After peers are added and the devices are clustered, traffic group failover causes some hosts to go into standby

All traffic groups are forced to standby once they are created. This is presumably to test that the failover process works correctly. From F5's Official Documentation, when all traffic groups defined on a host failover to the standby, thus the host has no active traffic groups left, then the system itself is labeled as Online (STANDBY). https://support.f5.com/kb/en-us/products/big-ip_ltm/manuals/product/bigip-device-service-clustering-admin-11-5-0/8.html

You can use the BIG-IP® Configuration utility to view the current failover state of a device in a device group. An Active failover state indicates that at least one traffic group is currently active on the device. A Standby failover state indicates that all traffic groups on the device are in a Standby state.

The simple bug here may be that there were no standby traffic groups defined on one or more devices, so when all active traffic groups failover (to the standby devices defined), one or more devices goes into standby because it is not listed as a standby for any of the traffic groups.

Functional test POC

Create a sample functional test using a live BIG-IP VE to demonstrate how to test the API against real resources.

Consistent error-handling in python API functions

API functions should return an object when calling create, for the new "thing" created, otherwise raise an error. The current code is inconsistent in that it returns True or False for some errors and raise for others. The caller cannot tell from a False return what went wrong.

We need to publish and implement a policy that dictates how test dependencies are to be handled

Should test dependencies (e.g. mock, responses, pytest) be in requirements.txt?
Should there be a switch that allows an installer to choose whether or not they want test dependencies? If yes, then how should the switch be implemented?
What should it be set to by default?

I suppose @jlongstaf, @pjbreaux, @swormke, and I should at least know what policy we decide on, so we can correctly implement in future repositories.

I'm tentatively assigning this to @richbrowne since he's the packaging czar. (As always I believe we should feel free to reassign issues willy-nilly.)

During clustering, script can become stuck in a changes pending state and never come out

This is usually after a device is peered, as shown in the snippet below. From the official F5 Documentation, this issue usually reflects a possible conflict among two or more devices because more than one device contains changes that have not been synchronized to the device group. Possibly a timing issue in the cluster.py code.

Nov 10 16:11:18: Adding peer host-10-4-4-55.int.lineratesystems.com
Nov 10 16:11:23: Added peer host-10-4-4-55.int.lineratesystems.com
Nov 10 16:11:23: waiting 5 secs for peer to add
Nov 10 16:11:28: Wait until device_trust_group is in sync...
Nov 10 16:11:29: device_trust_group sync status: red, Disconnected
Nov 10 16:11:29: Waiting 2 seconds fore checking sync state again.
Nov 10 16:11:31: device_trust_group sync status: red, Disconnected
Nov 10 16:11:31: Waiting 2 seconds fore checking sync state again.
Nov 10 16:11:33: device_trust_group sync status: yellow, Changes Pending
Nov 10 16:11:33: Waiting 2 seconds fore checking sync state again.
Nov 10 16:11:35: device_trust_group sync status: yellow, Changes Pending
Nov 10 16:11:35: Waiting 2 seconds fore checking sync state again.

Link to F5 BigIP documentation where the information about sync states was pulled from (https://support.f5.com/kb/en-us/products/big-ip_ltm/manuals/product/bigip-device-service-clustering-11-2-1/7.html)

Pool interface add_member() does not provide informational failure message

The add_member() method in the pool.py interface accepts default keyword arguments, yet the first if statement checks to ensure these keyword arguments are set. If not, then the method returns false, and the member is not created. It should raise an exception (of some kind) and the necessary keyword arguments should just become positional (required) arguments.

https://github.com/F5Networks/f5-common-python/blob/develop/f5/bigip/interfaces/pool.py#L364

Intuitive argument definition in public API

API functions currently declare all arguments as 'conditional' (i.e. key=default). This makes it impossible to know how to use an API without code and live VE exploration. For instance, the nat create API only requires name, ip_address and orig_ip_address. But I have to look in the GUI to figure that out, and also iterate in the code trying different combinations.

Required args MUST NOT have a default value to force proper usage by the caller.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.