Open sebbbastien opened 5 years ago
Hi Sebbastien, Yes, the easiest way to inspect an element is to create in SMC, then pull down with smc-python, like this. I have this multilink:
Then pull down and inspect:
a = Multilink('outbound-sdwan')
pprint(vars(a.data))
results in:
{'_etag': '"MTU4ODY5MjQxNjcxNTA5MDQxMzI2NDE2"',
'data': {u'etag': u'MTU4ODY5MjQxNjcxNTA5MDQxMzI2NDE2',
u'key': 158869,
u'link': [{u'href': u'http://172.18.1.150:8082/6.5/elements/outbound_multilink/158869',
u'rel': u'self',
u'type': u'outbound_multilink'},
{u'href': u'http://172.18.1.150:8082/6.5/elements/outbound_multilink/158869/export',
u'rel': u'export'},
{u'href': u'http://172.18.1.150:8082/6.5/elements/outbound_multilink/158869/history',
u'rel': u'history'},
{u'href': u'http://172.18.1.150:8082/6.5/elements/outbound_multilink/158869/search_category_tags_from_element',
u'rel': u'search_category_tags_from_element'},
{u'href': u'http://172.18.1.150:8082/6.5/elements/outbound_multilink/158869/duplicate',
u'rel': u'duplicate'}],
u'multilink_member': [{u'ip_range': u'172.18.1.241',
u'netlink_ref': u'http://172.18.1.150:8082/6.5/elements/netlink/164554',
u'netlink_role': u'active',
u'network_ref': u'http://172.18.1.150:8082/6.5/elements/network/979',
u'qos_role': [{u'netlink_role': u'active',
u'qos_class_ref': u'http://172.18.1.150:8082/6.5/elements/qos_class/7'}]},
{u'ip_range': u'10.0.0.254',
u'netlink_ref': u'http://172.18.1.150:8082/6.5/elements/netlink/164555',
u'netlink_role': u'active',
u'network_ref': u'http://172.18.1.150:8082/6.5/elements/network/120',
u'qos_role': [{u'netlink_role': u'active',
u'qos_class_ref': u'http://172.18.1.150:8082/6.5/elements/qos_class/2'},
{u'netlink_role': u'standby',
u'qos_class_ref': u'http://172.18.1.150:8082/6.5/elements/qos_class/7'}]}],
u'multilink_method': u'rtt',
u'multilink_qos_class': [{u'balance_method': u'rtt',
u'qos_class_ref': u'http://172.18.1.150:8082/6.5/elements/qos_class/2'},
{u'balance_method': u'rtt',
u'qos_class_ref': u'http://172.18.1.150:8082/6.5/elements/qos_class/7'}],
u'name': u'outbound-sdwan',
u'read_only': False,
u'retries': 2,
u'system': False,
u'timeout': 3600}}
Multilink members are somewhat complex because they require resolution to other element references that must already exist in SMC. Although generic element will handle that properly as long as you use the same structure.
Hi David,
I've "patched" the Multilink.update_or_create()
method to understand (added two print()
lines):
@classmethod
def update_or_create(cls, with_status=False, **kwargs):
element, updated, created = super(Multilink, cls).update_or_create(
with_status=True, defer_update=True, **kwargs)
if not created:
multilink_members = kwargs.pop('multilink_members', [])
if multilink_members:
+ print(multilink_members)
+ print(element.members)
if set(multilink_members) ^ set(element.members):
element.data['multilink_member'] = multilink_members
updated = True
if updated:
element.update()
if with_status:
return element, updated, created
return element
Using smc-python
I get:
In [62]: Multilink.update_or_create(name='OML_Test', multilink_members=[MultilinkMember.create(DynamicNetlink(name='dynamic_netlink-C0001-(IPv4)-Interface 0 (3)'))])
[MultilinkMember(netlink=DynamicNetlink(name=dynamic_netlink-C0001-(IPv4)-Interface 0 (3)),netlink_role=active,ip_range=0.0.0.0)]
[MultilinkMember(netlink=StaticNetlink(name=NL_TEST),netlink_role=active,ip_range=1.2.3.3-1.2.3.4)]
Out[62]: Multilink(name=OML_Test)
multilink_members
is xor (^
) with element.members
, both are lists of MultilinkMember objects.
Using this playbook:
- name: Create a network element
hosts: localhost
gather_facts: no
tasks:
- name: Example network element creation
generic_element:
elements:
- outbound_multilink:
name: OML_Test
multilink_members:
- multilink_member:
staticnetlink:
name: "NL_TEST"
netlink_role: "standby"
ip_range: "1.2.3.1-1.2.3.2"
the error message is:
fatal: [localhost]: FAILED! => {
"changed": false,
"module_stderr": "<stdin>:17: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses\nTraceback (most recent call last):\n File \"<stdin>\", line 113, in <module>\n File \"<stdin>\", line 105, in _ansiballz_main\n File \"<stdin>\", line 48, in invoke_module\n File \"/usr/lib/python3.7/imp.py\", line 234, in load_module\n return load_source(name, filename, file)\n File \"/usr/lib/python3.7/imp.py\", line 169, in load_source\n module = _exec(spec, sys.modules[name])\n File \"<frozen importlib._bootstrap>\", line 630, in _exec\n File \"<frozen importlib._bootstrap_external>\", line 728, in exec_module\n File \"<frozen importlib._bootstrap>\", line 219, in _call_with_frames_removed\n File \"/tmp/ansible_generic_element_payload_wx5v3j4l/__main__.py\", line 186, in <module>\n File \"/tmp/ansible_generic_element_payload_wx5v3j4l/__main__.py\", line 183, in main\n File \"/tmp/ansible_generic_element_payload_wx5v3j4l/__main__.py\", line 131, in __init__\n File \"/tmp/ansible_generic_element_payload_wx5v3j4l/ansible_generic_element_payload.zip/ansible/module_utils/stonesoft_util.py\", line 487, in __init__\n File \"/tmp/ansible_generic_element_payload_wx5v3j4l/__main__.py\", line 158, in exec_module\n File \"/home/seb/dev/ansible-stonesoft-sbt/env/lib/python3.7/site-packages/smc/elements/netlink.py\", line 398, in update_or_create\n if set(multilink_members) ^ set(element.members):\nTypeError: unhashable type: 'dict'\n",
"module_stdout": "[{'multilink_member': {'staticnetlink': {'name': 'NL_TEST'}, 'netlink_role': 'standby', 'ip_range': '1.2.3.1-1.2.3.2'}}]\n[MultilinkMember(netlink=DynamicNetlink(name=dynamic_netlink-C0001-(IPv4)-Interface 0 (3)),netlink_role=active,ip_range=0.0.0.0)]\n",
"msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
"rc": 1
}
Module stdout is:
Here, the second print still show a list of MultilinkMember
, but first argument is "raw" json.
Although generic element will handle that properly as long as you use the same structure.
I don't understand how generic_element
can handle [Static|Dynamic]Netlink when creating a MultilinkMember.
Hi David,
Not sure if I have to open a new case or respond to #30, but the question is different, so I choose to open a new issue.
Until now I create Multilink using smc-python, but
generic_element
could allow me to save some time on idempotency work. I manage to use generic_element to create some simple elements, but I'm stuck on Multilink element.generic_element
library useMultilink.update_or_create()
, and this function usemultilink_members
. Next argument should be a list ofmultilink_member
, each build fromname
,netlink_role
and eventualyip_range
. I tried a lot of syntax, but none was working.Is-it possible to deduct the attended structure from smc-python output (from
element.data.data
for example)?Regards,