Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inability to cahnge where PrefixPools connectTo #13

Closed
ytti opened this issue Aug 17, 2018 · 4 comments
Closed

Inability to cahnge where PrefixPools connectTo #13

ytti opened this issue Aug 17, 2018 · 4 comments

Comments

@ytti
Copy link

ytti commented Aug 17, 2018

When I create prefixPools they connect to 'ethernet', which means my ISIS and BGP both will advertise everything I have, which is undesirable.
I could not find way to chnge the connectedTo key.

def monkey_ixianet_configPrefixPoolsConnector(self, prefixPoolsObj, **kwargs):
    url = self.ixnObj.httpHeader + prefixPoolsObj + '/connector'
    response = self.ixnObj.get(url)
    current = response.json()["connectedTo"]
    self.ixnObj.logInfo('Configuring PrefixPool Connector connecedTo from %s to %s' % (current, kwargs['connectedTo']))
    self.ixnObj.patch(url, data={'connectedTo': kwargs['connectedTo']})

setattr(Protocol, "configIpv4LoopNgpf", monkey_ixianet_configIpv4LoopNgpf)
setattr(Protocol, "configIpv6LoopNgpf", monkey_ixianet_configIpv6LoopNgpf)
setattr(Protocol, "configPrefixPoolsConnector", monkey_ixianet_configPrefixPoolsConnector)
setattr(Protocol, "configIpv6NetworkGroup", monkey_ixia_configIpv6NetworkGroup)

The Rest Python API is quite wet and unidiomatic. I see no particular reason why it should implement AFI specific methods and it even changes the AFI-agnostic keys of REST api to AFI-specific keys, for no particular reason.
It seems it would be lot drier to just use same AFI agnostic keys that REST API expects, and to use single method regardless of API.
Also it's not obvious to me what is the target audience of the Python REST API, it doesn't seem to add much value to using raw REST.

What I've implemented on top of now, and what I think is significantly drier and idiomatic:

#!/usr/bin/env python3

import nttixia.ixia

ports  = ["3/1"]
ixia   = nttixia.ixia.Ixia(steal_ports=True, api_port=12010)
ports  = ixia.add_ports(ports)
topo   = ixia.add_topology(ports)
group  = topo.add_group(multiplier=4)
eth    = group.add_ethernet()
ipv4   = eth.add_connected(ip="204.42.112.2", mask=24, gw="204.42.112.1")
ipv6   = eth.add_connected(ip="2001:418:3f9:1000::112:2", mask=112, gw="2001:418:3f9:1000::112:1")
isis   = eth.add_isis()
net1   = group.add_network(ip="204.42.110.100")
net2   = group.add_network(ip="100.100.100.0")
net3   = group.add_network(ip="100.100.101.0")
net4   = group.add_network(ip="2001:418:3f9:1000::100")
loop4  = group.add_loopback(ip="204.42.110.100")
loop6  = group.add_loopback(ip="2001:418:3f9:1000::100")
bgp    = loop4.add_bgp(ip="204.42.110.40")
bgp.add_network(net2)
bgp.add_network(net3)
isis.add_network(net1)
isis.add_network(net4)
ixia.start()

Example of Loopback class:

from .rest import Args
from .bgp import Bgp

class Loopback:
  IP   = "10.255.0.2"

  def __init__(self, group, **kwargs):
    self.log = kwargs.pop("log")
    self.group = group

    kwargs.setdefault("ip", self.IP)
    ip = { "start": kwargs["ip"],
           "direction": "increment" }

    args = Args(kwargs)
    args.map(args.name(), "name")
    self.name = args.get("name")

    if ":" in kwargs["ip"]:
      self.loopback = self.ipv6(ip, args)
    else:
      self.loopback = self.ipv4(ip, args)

    self.ipObj = self.loopback
    self.bgps = {}

  def ipv4(self, ip, args):
    ip["step"] = "0.0.0.1"
    args.map(32, "mask", "prefix")
    args.set("ipv4Address", ip)
    args.map("disabled", "ipv4AddressPortStep")
    self.log.debug("setting loop with args: %s" % args.rest)
    return self.group.topology.ixia.protocol.configIpv4LoopNgpf(self.group.group, **args.rest)

  def ipv6(self, ip, args):
    ip["step"] = "0:0:0:0:0:0:0:1"
    args.map(128, "mask", "prefix")
    args.set("ipv6Address", ip)
    args.map("disabled", "ipv6AddressPortStep")
    self.log.debug("setting loop with args: %s" % args.rest)
    return self.group.topology.ixia.protocol.configIpv6LoopNgpf(self.group.group, **args.rest)

  def add_bgp(self, **kwargs):
    kwargs["log"] = self.log
    bgp = Bgp(self, **kwargs)
    self.bgps[bgp.name] = bgp
    return self.get_bgp(bgp.name)

  def get_bgp(self, name):
    return self.bgps[name]

This works just fine, but I likely need to revert to raw rest, as I continue to add functionality, I continue to monkey patch the API, and my monkey patches are equally wet, as I cannot write them very dry without significant refactoring.
It seems to me anyone needing to do anything over the REST API, will over time spend less time by writing it without the library.

@hubertgee
Copy link
Contributor

Hi Ytti,

I'm going to close this case because this is a support issue. Please email support.ix@keysight.com and someone will help you on this.

Keep in mind that this Github/OpenIxia/IxNetwork repository is not an official Ixia product. This will never have everything people need. It is only meant to help people get started with ReST API automation. You could continue using this and Ixia support will help you with it when you clone it on your local filesystem to make this your own.
The best way to use this is by doing Python Class inheritance. There is a sample to show in https://github.com/OpenIxia/IxNetwork/blob/master/RestApi/Python/Modules/ClassInheritance.py. This method allows you to add your own functions and allows you to get OpenIxia updates without interfering your own additions.

Hubert

@ytti
Copy link
Author

ytti commented Aug 22, 2018

I agree you can't support everything for every case, but that's not what I'm asking.

What I'd like to see is to support passing dict to the underlaying REST call, so if something isn't supported by your own kwargs, then one of those kwargs could be 'rest_args' which you pass as-is to the HTTP JSON call.
This way, I could add "rest_args": { "connectedTo": "foobar" }, when creating networkGroup, without you specifically supporting such kwarg, just blindly passing it to the underlaying REST call.

I.e. the high-level rest API would just add convenience, but not forbid using all current and future arguments possible.

@hubertgee
Copy link
Contributor

hubertgee commented Aug 22, 2018 via email

@ytti
Copy link
Author

ytti commented Aug 22, 2018

Yes this is very interesting development, and sounds like very good approach. Get full 'raw REST' feature parity, with OO access.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants