-
Notifications
You must be signed in to change notification settings - Fork 185
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
enhance: add base class 'OVSvsctlList' (#3575)
* enhance: add a basic class 'OVSvsctlList' for parser 'OVSvsctlListBridge' Signed-off-by: shlao <[email protected]> * Refactor the hierarchy for command 'ovs-vsctl' * Call the 'deprecated' function Signed-off-by: shlao <[email protected]>
- Loading branch information
Showing
4 changed files
with
238 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.. automodule:: insights.parsers.ovs_vsctl | ||
:members: | ||
:show-inheritance: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
""" | ||
Open vSwitch ``ovs-vsctl`` - utility for querying ovs-vswitchd | ||
============================================================== | ||
Classes in this module are: | ||
OVSvsctlList - command ``/usr/bin/ovs-vsctl list TBL [REC]`` | ||
------------------------------------------------------------ | ||
Parsers in this module are: | ||
OVSvsctlListBridge - command ``/usr/bin/ovs-vsctl list bridge`` | ||
--------------------------------------------------------------- | ||
""" | ||
|
||
from insights import CommandParser, get_active_lines, parser | ||
from insights.parsers import SkipException, optlist_to_dict | ||
from insights.specs import Specs | ||
|
||
|
||
class OVSvsctlList(CommandParser, list): | ||
""" | ||
Class to parse output of command ``ovs-vsctl list TBL [REC]``. | ||
Generally, the data is in ``key:value`` format with values having | ||
data types as string, numbers, list or dictionary. | ||
Raises: | ||
SkipException: When file is empty. | ||
""" | ||
def parse_content(self, content): | ||
""" | ||
Details of the subset of the Open vSwitch database, which holds the configuration | ||
for the Open vSwitch daemon, are extracted and stored in a list as a dictionary. | ||
""" | ||
# No content found or file is empty | ||
if not content: | ||
raise SkipException("Empty file") | ||
|
||
record = {} | ||
for line in get_active_lines(content): | ||
key, value = [i.strip() for i in line.split(":", 1)] | ||
parsed_value = value.strip('"') | ||
if value.startswith("{") and value.endswith("}"): | ||
parsed_value = {} | ||
value = value.strip("{}") | ||
if value: | ||
parsed_value = optlist_to_dict(value, opt_sep=", ", strip_quotes=True) | ||
elif value.startswith("[") and value.endswith("]"): | ||
parsed_value = [] | ||
value = value.strip("[]") | ||
if value: | ||
parsed_value = [i.strip(' \t\"\'') for i in value.split(",")] | ||
|
||
if key in record: | ||
# A new record comes | ||
self.append(record) | ||
record = {} | ||
|
||
record[key] = parsed_value | ||
|
||
# Add the last record | ||
self.append(record) | ||
|
||
@property | ||
def data(self): | ||
""" | ||
Set data as property to keep compatibility | ||
""" | ||
return self | ||
|
||
|
||
@parser(Specs.ovs_vsctl_list_bridge) | ||
class OVSvsctlListBridge(OVSvsctlList): | ||
""" | ||
Class to parse output of command ``ovs-vsctl list bridge``. | ||
Sample command output:: | ||
name : br-int | ||
other_config : {disable-in-band="true", mac-table-size="2048"} | ||
name : br-tun | ||
other_config : {} | ||
Examples: | ||
>>> bridge_lists[0]["name"] | ||
'br-int' | ||
>>> bridge_lists[0]["other_config"]["mac-table-size"] | ||
'2048' | ||
>>> bridge_lists[0]["other_config"]["disable-in-band"] | ||
'true' | ||
>>> bridge_lists[1].get("name") | ||
'br-tun' | ||
>>> len(bridge_lists[1]["other_config"]) == 0 | ||
True | ||
""" | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
from insights.parsers import SkipException | ||
from insights.parsers import ovs_vsctl | ||
from insights.parsers.ovs_vsctl import OVSvsctlListBridge | ||
from insights.tests import context_wrap | ||
import doctest | ||
import pytest | ||
|
||
OVS_VSCTL_LIST_BRIDGES_ALL = """ | ||
_uuid : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | ||
auto_attach : [] | ||
controller : [xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx] | ||
datapath_id : "0000a61fd19ea54f" | ||
datapath_type : "enp0s9" | ||
datapath_version : "<unknown>" | ||
external_ids : {a="0"} | ||
fail_mode : secure | ||
flood_vlans : [1000] | ||
flow_tables : {1=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} | ||
ipfix : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | ||
mcast_snooping_enable: false | ||
mirrors : [xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx] | ||
name : br-int | ||
netflow : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | ||
other_config : {disable-in-band="true", mac-table-size="2048"} | ||
ports : [xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, 0000000-0000-0000-0000-0000000000000, 1111111-1111-1111-1111-1111111111111] | ||
protocols : ["OpenFlow11", "OpenFlow11", "OpenFlow12", "OpenFlow13"] | ||
rstp_enable : true | ||
rstp_status : {rstp_bridge_id="8.000.a61fd19ea54f", rstp_bridge_port_id="0000", rstp_designated_id="8.000.a61fd19ea54f", rstp_designated_port_id="0000", rstp_root_id="8.000.a61fd19ea54f", rstp_root_path_cost="0"} | ||
sflow : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | ||
status : {"0"="1"} | ||
stp_enable : true | ||
_uuid : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | ||
auto_attach : [] | ||
controller : [] | ||
datapath_id : "0000d29e6a8acc4c" | ||
datapath_type : "" | ||
datapath_version : "<unknown>" | ||
external_ids : {} | ||
fail_mode : [] | ||
flood_vlans : [] | ||
flow_tables : {} | ||
ipfix : [] | ||
mcast_snooping_enable: false | ||
mirrors : [] | ||
name : br-tun | ||
netflow : [] | ||
other_config : {} | ||
ports : [xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx] | ||
protocols : [] | ||
rstp_enable : false | ||
rstp_status : {} | ||
sflow : [] | ||
status : {} | ||
stp_enable : false | ||
""".strip() | ||
|
||
OVS_VSCTL_LIST_BRIDGES_FILTERED1 = """ | ||
name : br-int | ||
other_config : {disable-in-band="true", mac-table-size="2048"} | ||
name : br-tun | ||
other_config : {} | ||
""".strip() | ||
|
||
OVS_VSCTL_LIST_BRIDGES_FILTERED2 = """ | ||
_uuid : xxxxxxxx-xxxx-xxxx-xxxxx-xxxxxxxxxxxx | ||
name : br-int | ||
netflow : [] | ||
other_config : {disable-in-band="true", mac-table-size="2048"} | ||
stp_enable : false | ||
_uuid : aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa | ||
name : br-tun | ||
netflow : [] | ||
other_config : {mac-table-size="4096"} | ||
stp_enable : true | ||
""".strip() | ||
|
||
EXCEPTION1 = """ | ||
""".strip() | ||
|
||
|
||
def test_ovs_vsctl_documentation(): | ||
env = { | ||
"bridge_lists": OVSvsctlListBridge(context_wrap(OVS_VSCTL_LIST_BRIDGES_FILTERED1)), | ||
} | ||
failed, total = doctest.testmod(ovs_vsctl, globs=env) | ||
assert failed == 0 | ||
|
||
|
||
def test_ovs_vsctl_all(): | ||
bridges = OVSvsctlListBridge(context_wrap(OVS_VSCTL_LIST_BRIDGES_ALL)) | ||
assert bridges[0]["name"] == "br-int" | ||
assert bridges[0]["external_ids"] == {"a": "0"} | ||
assert bridges[0]["flow_tables"] == {"1": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"} | ||
assert bridges[0].get("flood_vlans") == ["1000"] | ||
assert bridges[0]["protocols"][-1] == "OpenFlow13" | ||
assert bridges[0]["other_config"]["mac-table-size"] == "2048" | ||
assert bridges[0]["rstp_status"]["rstp_root_path_cost"] == "0" | ||
assert bridges[1]["name"] == "br-tun" | ||
assert bridges[1]["mirrors"] == [] | ||
assert bridges[1]["datapath_type"] == "" | ||
assert bridges[1]["status"] == {} | ||
assert bridges[1].get("stp_enable") == "false" | ||
|
||
|
||
def test_ovs_vsctl(): | ||
bridges = OVSvsctlListBridge(context_wrap(OVS_VSCTL_LIST_BRIDGES_FILTERED2)) | ||
assert bridges[0].get("name") == "br-int" | ||
assert bridges[0]["other_config"]["mac-table-size"] == "2048" | ||
assert bridges[1]["name"] == "br-tun" | ||
|
||
|
||
def test_ovs_vsctl_exception1(): | ||
with pytest.raises(SkipException) as e: | ||
OVSvsctlListBridge(context_wrap(EXCEPTION1)) | ||
assert "Empty file" in str(e) |