Giter VIP home page Giter VIP logo

cpal's Introduction

Author: Jason Edelman Email: [email protected]

cpal.py is the main module. It requires other modules such as Cisco, Arista, pandums, jformat, and counter.

For background on CPAL, please read first two links and watch the demo at the 3rd link:

http://www.jedelman.com/1/post/2014/02/common-programmable-abstraction-layer.html http://www.jedelman.com/1/post/2014/02/the-power-of-a-programmable-abstraction-layer.html http://www.jedelman.com/1/post/2014/03/demo-common-programmable-abstraction-layer.html

If you want to contirubte, you are more than welcome. There is still a ton to do on the first two module (onePK and eAPI) and it would be great to see more modules. As more modules evolve, we'll need to update the main cpal.py file to include more variables/function that will in turn call the new modules.

Current plan (for me or you):

  • Convert many of the functions in cpal/device variables. This will make it easier for users to call them
  • This is just a module now, but am going to include something in 'main' to be able to call specific functions for specific devices. Good for helpdesk/admin types that don't need or want to be at the shell
  • Adding ODL as a southbound module
  • Update names from the vendor like Cisco and Arista. Will change to cisco-onepk and arista-eapi to allow for more API types from the same vendor.
  • Jeremy Schulman also has the Juniper PyEZ module. It would be great to build cohesiveness or just integrate that here as well.

Things others have talked about:

  • Adding NX-API
  • Adding F5 APIs

Side note, as more APIs are added, we can get fancier with the function calls correlating data between routers, switches, load balancers, and the like! This is where it'll get fun. We'll need to think about this one.

If you want to contribute to an existing module, just let me know before you do. It'll streamline the integration process.

cpal's People

Contributors

jedelman8 avatar ktbyers avatar mierdin avatar sjiveson avatar

Stargazers

 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

cpal's Issues

Arista eaAPI - show hostname

Yandy

Does this work for you? I thought it was odd when you changed it to 'show hostname' in the eapi getHostname() methond. It doesn't work for me...this is why I was parsing through text of another command.

Does this work for you?

def getHostname(self):
        output = self.getCmd("show hostname")
        hostname = output[0]['hostname']
        return hostname

'show hostname' isn't even a valid command when at the command prompt on the box. Not sure what I'm missing.

Standardized classes for inter-vendor data structures

Jason, I'm wondering if we should build some additional classes for data types that are specific to networking devices, yet applicable to all vendor implementations. For instance - all routers have a routing table, but are represented in different ways.

It might be valuable to build out a class for this and other things like it. Each vendor module (cisco, junos, etc) is responsible for translating that vendor's specific representation of that data, and instantiating/populating the relevant class(es), and placing them into an array within each device instance.

For instance, I built this as an example into Cisco's NXAPI repo:
https://github.com/Mierdin/nexus9000/blob/master/examples/RoutingTable.py

If you think that's a good direction, we can build files for classes like these into a dedicated folder within the cpal repo.

Thoughts?

Move device to it's own module (device.py)

What do you guys think about moving device() out of main.py and putting it in it's own module? This way we can have a true representation of the Model/View/Controller. Can also help in modularizing things a bit more.

So in this case:

Things contained under vendors are the Model for this.
Device would be the Controller
and main would be the view, the representation of the data that Device is interpreting from the model classes.

Keeping device in main, can make it cumbersome as this grows.

Just an idea. Thoughts?

What's the Plan?

All,

I'm keen to do more with the F5 module but I'm not sure it's worthwhile until we all have an idea of what's next and what the future feature roadmap might be. I'm sure we all have a lot of ideas but obviously some agreement and discussion is needed.

I'd like to add the F5 REST API as well as the SOAP one I've used so far but in more general, project-wide terms I've been thinking about;

-SSH support (using Paramiko/pexpect)
-Prompting for username/password (per device or per group)
-Ability to group devices (including from different vendors)
-Standardising (where possible) on output formats across all the supported vendor modules (MAC address formatting is a prime example)
-Ability to output to CSV file (relates to previous two)
-Full configuration pull (if possible)

and so on, you get the idea.

Thoughts? I'm sure we're all busy but I'd rather not go off on a tangent.

Attribute License

@jedelman8 should select and specify the license applied to the project, will be important for inclusion and/or use in other projects.

changes to main.py --> device() as testing

Not a pull request, but created a branch on my own fork to pass something by you guys. I basically deleted all the methods from device that had getXXX in the name, so getCPU, getFacts, getHostname and so on..

I made it so that in main, createDevice() calls dev.run(function) and that checks if the called manufacturer implements the function and returns it. This way, we don't have to add a method to device() every time there's a new method added to the individual manufacturer APIs.

If a function does not exist, it still runs the display() function, except it's now part of device's methods.

Like so

$ python core/main.py -m arista -n sw1 -i 10.17.31.51 -f getCPUs
********************************************************
***IP Address (-i), manufacturer (-m), AND one of*******
***the following functions (-f) are required************
***Use 'python main.py -h' for more info on proper usage
********************************************************
*** address
*** facts
*** getCPU
*** getCmd
*** getFQDN
*** getFacts
*** getHostname
*** getPlatform
*** getUptime
*** getVersion
*** getVersionInfo
*** getfreeMemory
*** getserialNumber
*** gettotalMemory
*** jconnect
*** native
*** obj
*** password
*** setLogin
*** username
*** version_info

Same if the -f or -c flags are not passed, won't paste it because it's the same output.

But if the correct arguments are passed, then it works as expected.

$ python core/main.py -m arista -n sw1 -i 10.17.31.51 -f getCPU
Cpu(s):  9.9%us
$ python core/main.py -m arista -n sw1 -i 10.17.31.51 -f getFacts
{   'connect_ip': '10.17.31.51',
    'cpu_utilization': u'Cpu(s):  9.9%us',
    'free_system_memory': 1336128,
    'hostname': u'eos-sw01',
    'platform': u'DCS-7050T-64-R',
    'serial_number': u'JPE13020644',
    'system_uptime': u' 9:47',
    'total_sytem_memory': 3990500,
    'var_name': 'sw1',
    'vendor': 'arista',
    'version': u'4.13.2F'}

Let me know what you think, the branch is called exp-run.

CHECK IT OU HERE

Use a bit of Inheritance? - Open discussion

One thing I noticed from the code is that, the same methods are defined and implemented for every object. Hear me (or read me out?.. sounds weird) out if you will for a bit. What if we use a bit of inheritance and polymorphism already built into Python?

Create a base parent class, say Switch (example below)

class Switch(object):
    """docstring for Switch"""
    def __init__(self, args):
        super(Switch, self).__init__()
        self.args = args

    def version(self):
        # generic 
        pass 

    def getCpu(self):
        pass

Then all other Vendor specifics inherit from this Parent class. Now I know there will be allot of methods that will have to be re-implemented in the child classes, but not all, any repetitive code that we can cut is a win.

example:

class cisco(Switch):
    """docstring for cisco"""
    def __init__(self, arg):
        super(cisco, self).__init__()
        # only specifics to this class, things like IP address, command, user/password
        # can be inherited from Switch class
        self.arg = arg

    # no getVerions()
    # version info for most cisco, arista devices are the same
    # return different data, but that can be abstracter later

    def getCpu(self):
        # cisco specific CPU here
        pass


class arista(Switch):
    """docstring for arista"""
    def __init__(self, arg):
        super(arista, self).__init__()
        # only specifics to this class, things like IP address, command, user/password
        # can be inherited from Switch class
        self.arg = arg

    # no getVerions()
    # version info for most cisco, arista devices are the same
    # return different data, but that can be abstracter later

    def getCpu(self):
        # cisco specific CPU here
        pass

Then device() in main will essentially inherit from all vendors, stopping the need to call

return self.thisDevice.getFunctionNameHere()

something like this:

class device(Switch, arista, cisco, junos):
    """docstring for device"""
    def __init__(self):
        super(device, self).__init__()
        # initialized by Switch parent and passed to the correct child
        # based on 'manufacturer' info

    # no need to create methods to return information
    # only relevant to device() class methods are defined

hence, when doing something like:

sw1 = device(obj, 'cisco', '192.168.1.1')
sw1.getVersion()

Using python's built in inheritance and polymorphism, the correct method would be called without the need to re-implement. Code changes in only one place, and no need to look back for specifics.

It's an idea, details can be worked out. Still thinking how to initialize Switch from device() since device is called first. Not even sure it's possible, may need to remove that level, but I'm sure you get the gist.

Takers? Ideas? It's okay to say I'm crazy or otherwise.

@jedelman8
@Mierdin

Thanks

method for arg parsing

Yandy,
I started the work to create a method for arg parsing as mentioned earlier. Now you can see what I mean. The method is only used when running it as a program. Feel free to finish it....if not, I'll try to later in the week too... :)

Using cpal as standalone program

I recently named 'main.py' to 'main' and modified the file permissions to make it an executable. Original 'main.py is also kept for now as 'main1.py' just in case someone doesn't think this is a good idea.

Output...notice how I am using "./main *args" instead of "python main.py *args"

Trying to improve user experience.

Tested from python shell, and this doesn't seem to affect anything as far as I can tell. Let me know if you see otherwise.

cisco@onepk:~/apps/cpal/core$ ./main -i 10.1.1.110 -m cisco -f getFacts
{   'connect_ip': '10.1.1.110',
    'cpu_utilization': 11,
    'free_system_memory': 71741952,
    'hostname': 'Router1',
    'interfaces': [   'GigabitEthernet0/3',
                      'GigabitEthernet0/2',
                      'GigabitEthernet0/1',
                      'GigabitEthernet0/0',
                      'GigabitEthernet0/7',
                      'GigabitEthernet0/6',
                      'GigabitEthernet0/5',
                      'GigabitEthernet0/4',
                      'GigabitEthernet0/9',
                      'GigabitEthernet0/8'],
    'last_reboot_reason': 'Unknown reason',
    'platform': 'IOSv',
    'serial_number': '91OSGB4XI9613IB48IJL4',
    'system_uptime': 22737,
    'tags': {   'other': '',
                'pin': 'wan',
                'primary_dept': 'police',
                'region': 'west',
                'site_id': '79'},
    'total_sytem_memory': 134380696,
    'var_name': 'dev',
    'vendor': 'cisco'}

Please consider an explicit license for the repo

Hello,

How is this repo licensed? If it's licensed MIT, then that's permissive and I can almost do anything with it; however, if it's licensed GPL, derived works must be licensed the same way and published. I'm interested in potentially integrating this with other libraries, but I'd like to understand the terms and conditions. If you're not sure which license to use, there is a pretty good guide here:

http://choosealicense.com/

Even if you just declare it as WTFPL, that's better than no explicit licensing terms

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.