mirror of
				https://github.com/Telecominfraproject/ols-nos.git
				synced 2025-10-31 01:57:48 +00:00 
			
		
		
		
	Add CLI Support for IPv6 Helpers and DHCPv6 Relay Counters (#8593)
This commit is contained in:
		
							
								
								
									
										18
									
								
								dockers/docker-dhcp-relay/cli-plugin-tests/mock_config.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								dockers/docker-dhcp-relay/cli-plugin-tests/mock_config.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| TEST_DATA = [  | ||||
|     [ | ||||
|         "DHCPv6_Helpers", | ||||
|         { | ||||
|             "config_db": { | ||||
|                 "DHCP_RELAY": { | ||||
|                     "Vlan1000": { | ||||
|                         "dhcpv6_servers": [ | ||||
|                             "fc02:2000::1", | ||||
|                             "fc02:2000::2" | ||||
|                         ], | ||||
|                         "dhcpv6_option|rfc6939_support": "true" | ||||
|                     } | ||||
|                 } | ||||
|             }, | ||||
|         }, | ||||
|     ], | ||||
| ] | ||||
| @@ -0,0 +1,43 @@ | ||||
| import sys | ||||
| import os | ||||
| from unittest import mock | ||||
| sys.path.append('../cli/show/plugins/') | ||||
| import show_dhcp_relay as show | ||||
|  | ||||
| from click.testing import CliRunner | ||||
|  | ||||
| try: | ||||
|     modules_path = os.path.join(os.path.dirname(__file__), "../../../src/sonic-utilities") | ||||
|     test_path = os.path.join(modules_path, "tests") | ||||
|     mock_table_path = os.path.join(test_path, "mock_tables") | ||||
|     sys.path.insert(0, modules_path) | ||||
|     sys.path.insert(0, test_path) | ||||
|     sys.path.insert(0, mock_table_path) | ||||
|     import dbconnector | ||||
| except KeyError: | ||||
|     pass | ||||
|  | ||||
| expected_counts = """\ | ||||
|   Message Type     Vlan1000 | ||||
| --------------  ----------- | ||||
|        Solicit | ||||
|      Advertise | ||||
|        Request | ||||
|        Confirm | ||||
|          Renew | ||||
|         Rebind | ||||
|          Reply | ||||
|        Release | ||||
|        Decline | ||||
|  Relay-Forward | ||||
|    Relay-Reply | ||||
|  | ||||
| """ | ||||
|  | ||||
| class TestDhcp6RelayCounters(object): | ||||
|  | ||||
|     def test_show_counts(self):            | ||||
|         runner = CliRunner() | ||||
|         result = runner.invoke(show.dhcp6relay_counters.commands["counts"], ["-i Vlan1000"]) | ||||
|         assert result.output == expected_counts | ||||
|  | ||||
| @@ -0,0 +1,40 @@ | ||||
| import pytest | ||||
| import sys | ||||
| import os | ||||
| sys.path.append('../cli/show/plugins/') | ||||
| import show_dhcp_relay as show | ||||
| from click.testing import CliRunner | ||||
| from swsscommon import swsscommon | ||||
| from mock_config import TEST_DATA | ||||
| from parameterized import parameterized | ||||
| from pyfakefs.fake_filesystem_unittest import patchfs | ||||
|  | ||||
| try: | ||||
|     sys.path.insert(0, '../../../src/sonic-host-services/tests/common') | ||||
|     from mock_configdb import MockConfigDb | ||||
|     swsscommon.ConfigDBConnector = MockConfigDb  | ||||
| except KeyError: | ||||
|     pass | ||||
|      | ||||
| expected_table = """\ | ||||
| --------  ------------ | ||||
| Vlan1000  fc02:2000::1 | ||||
|           fc02:2000::2 | ||||
| --------  ------------ | ||||
| """ | ||||
|  | ||||
| DBCONFIG_PATH = '/var/run/redis/sonic-db/database_config.json' | ||||
|  | ||||
| class TestDhcpRelayHelper(object): | ||||
|  | ||||
|     @parameterized.expand(TEST_DATA) | ||||
|     @patchfs | ||||
|     def test_show_dhcpv6_helper(self, test_name, test_data, fs): | ||||
|         if not os.path.exists(DBCONFIG_PATH): | ||||
|             fs.create_file(DBCONFIG_PATH)  | ||||
|         MockConfigDb.set_config_db(test_data["config_db"]) | ||||
|         runner = CliRunner() | ||||
|         table = MockConfigDb.get_table(self, "DHCP_RELAY") | ||||
|         result = show.get_data(table, "Vlan1000") | ||||
|         assert result == expected_table | ||||
|  | ||||
| @@ -0,0 +1,32 @@ | ||||
| import sys | ||||
| import click | ||||
| sys.path.insert(0, '../../show/plugins/') | ||||
| from show_dhcp6relay_counters import DHCPv6_Counter | ||||
|  | ||||
| import utilities_common.cli as clicommon | ||||
|  | ||||
|  | ||||
| # sonic-clear dhcp6relay_counters | ||||
| @click.group(cls=clicommon.AliasedGroup) | ||||
| def dhcp6relay_clear(): | ||||
|     pass | ||||
|  | ||||
| @dhcp6relay_clear.command('dhcp6relay_counters') | ||||
| @click.option('-i', '--interface', required=False) | ||||
| def dhcp6relay_clear_counters(interface): | ||||
|     """ Clear dhcp6relay message counts """ | ||||
|      | ||||
|     counter = DHCPv6_Counter() | ||||
|     counter_intf = counter.get_interface() | ||||
|  | ||||
|     if interface: | ||||
|         counter.clear_table(interface) | ||||
|     else: | ||||
|         for intf in counter_intf: | ||||
|                 counter.clear_table(intf) | ||||
|  | ||||
| def register(cli): | ||||
|     cli.add_command(dhcp6relay_clear_counters) | ||||
|  | ||||
| if __name__ == '__main__': | ||||
|     dhcp6relay_clear_counters() | ||||
| @@ -1,5 +1,22 @@ | ||||
| import click | ||||
| from natsort import natsorted | ||||
| from tabulate import tabulate | ||||
| import show.vlan as vlan | ||||
| import utilities_common.cli as clicommon | ||||
|  | ||||
| from swsscommon.swsscommon import ConfigDBConnector | ||||
| from swsscommon.swsscommon import SonicV2Connector | ||||
|  | ||||
|  | ||||
| # STATE_DB Table | ||||
| DHCPv6_COUNTER_TABLE = 'DHCPv6_COUNTER_TABLE' | ||||
|  | ||||
| # DHCPv6 Counter Messages | ||||
| messages = ["Solicit", "Advertise", "Request", "Confirm", "Renew", "Rebind", "Reply", "Release", "Decline", "Relay-Forward", "Relay-Reply"] | ||||
|  | ||||
| # DHCP_RELAY Config Table | ||||
| DHCP_RELAY = 'DHCP_RELAY' | ||||
| config_db = ConfigDBConnector() | ||||
|  | ||||
| def get_dhcp_helper_address(ctx, vlan): | ||||
|     cfg, _ = ctx | ||||
| @@ -17,5 +34,99 @@ def get_dhcp_helper_address(ctx, vlan): | ||||
| vlan.VlanBrief.register_column('DHCP Helper Address', get_dhcp_helper_address) | ||||
|  | ||||
|  | ||||
| def register(cli): | ||||
| class DHCPv6_Counter(object): | ||||
|     def __init__(self): | ||||
|         self.db = SonicV2Connector(use_unix_socket_path=False) | ||||
|         self.db.connect(self.db.STATE_DB) | ||||
|         self.table_name = DHCPv6_COUNTER_TABLE + self.db.get_db_separator(self.db.STATE_DB) | ||||
|  | ||||
|  | ||||
|     def get_interface(self): | ||||
|         """ Get all names of all interfaces in DHCPv6_COUNTER_TABLE """ | ||||
|         vlans = [] | ||||
|         for key in self.db.keys(self.db.STATE_DB): | ||||
|             if DHCPv6_COUNTER_TABLE in key: | ||||
|                 vlans.append(key[21:]) | ||||
|         return vlans | ||||
|          | ||||
|  | ||||
|     def get_dhcp6relay_msg_count(self, interface, msg): | ||||
|         """ Get count of a dhcp6relay message """ | ||||
|         count = self.db.get(self.db.STATE_DB, self.table_name + str(interface), str(msg)) | ||||
|         data = [str(msg), count] | ||||
|         return data | ||||
|  | ||||
|      | ||||
|     def clear_table(self, interface): | ||||
|         """ Reset all message counts to 0 """ | ||||
|         for msg in messages: | ||||
|             self.db.set(self.db.STATE_DB, self.table_name + str(interface), str(msg), '0')  | ||||
|  | ||||
| def print_count(counter, intf): | ||||
|     """Print count of each message""" | ||||
|     data = [] | ||||
|     for i in messages: | ||||
|         data.append(counter.get_dhcp6relay_msg_count(intf, i)) | ||||
|     print(tabulate(data, headers = ["Message Type", intf], tablefmt='simple', stralign='right') + "\n") | ||||
|  | ||||
|  | ||||
| # | ||||
| # 'dhcp6relay_counters' group ### | ||||
| # | ||||
|  | ||||
|  | ||||
| @click.group(cls=clicommon.AliasedGroup, name="dhcp6relay_counters") | ||||
| def dhcp6relay_counters(): | ||||
|     """Show DHCPv6 counter""" | ||||
|     pass | ||||
|  | ||||
|  | ||||
| # 'counts' subcommand ("show dhcp6relay_counters counts") | ||||
| @dhcp6relay_counters.command('counts') | ||||
| @click.option('-i', '--interface', required=False) | ||||
| @click.option('--verbose', is_flag=True, help="Enable verbose output") | ||||
| def counts(interface, verbose): | ||||
|     """Show dhcp6relay message counts""" | ||||
|  | ||||
|     counter = DHCPv6_Counter() | ||||
|     counter_intf = counter.get_interface() | ||||
|  | ||||
|     if interface: | ||||
|         print_count(counter, interface) | ||||
|     else: | ||||
|         for intf in counter_intf: | ||||
|                 print_count(counter, intf) | ||||
|  | ||||
|  | ||||
|  | ||||
| @click.group(cls=clicommon.AliasedGroup, name="dhcprelay_helper") | ||||
| def dhcp_relay_helper(): | ||||
|     """Show DHCP_Relay helper information""" | ||||
|     pass | ||||
|  | ||||
| @dhcp_relay_helper.command('ipv6') | ||||
| def get_dhcpv6_helper_address(): | ||||
|     """Parse through DHCP_RELAY table for each interface in config_db.json and print dhcpv6 helpers in table format""" | ||||
|     if config_db is not None: | ||||
|         config_db.connect() | ||||
|         table_data = config_db.get_table(DHCP_RELAY) | ||||
|         if table_data is not None: | ||||
|             vlans = config_db.get_keys(DHCP_RELAY) | ||||
|             for vlan in vlans:  | ||||
|                 output = get_data(table_data, vlan) | ||||
|                 print(output) | ||||
|              | ||||
|  | ||||
| def get_data(table_data, vlan): | ||||
|     vlan_data = table_data.get(vlan) | ||||
|     helpers_data = vlan_data.get('dhcpv6_servers') | ||||
|     if helpers_data is not None: | ||||
|         addr = {vlan:[]} | ||||
|         for ip in helpers_data: | ||||
|             addr[vlan].append(ip) | ||||
|     output = tabulate({'Interface':[vlan], vlan:addr.get(vlan)}, tablefmt='simple', stralign='right') + '\n' | ||||
|     return output | ||||
|  | ||||
| def register(cli): | ||||
|     cli.add_command(dhcp6relay_counters) | ||||
|     cli.add_command(dhcp_relay_helper) | ||||
|   | ||||
| @@ -29,6 +29,7 @@ | ||||
|     }, | ||||
|     "cli": { | ||||
|         "config": "{{ config_cli_plugin|default('') }}", | ||||
|         "show": "{{ show_cli_plugin|default('') }}" | ||||
|         "show": "{{ show_cli_plugin|default('') }}", | ||||
|         "clear": "{{ clear_cli_plugin|default('') }}" | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -53,5 +53,6 @@ $(DOCKER_DHCP_RELAY)_CONTAINER_TMPFS += /var/tmp/ | ||||
|  | ||||
| $(DOCKER_DHCP_RELAY)_CLI_CONFIG_PLUGIN = /cli/config/plugins/dhcp_relay.py | ||||
| $(DOCKER_DHCP_RELAY)_CLI_SHOW_PLUGIN = /cli/show/plugins/show_dhcp_relay.py | ||||
| $(DOCKER_DHCP_RELAY)_CLI_CLEAR_PLUGIN = /cli/clear/plugins/clear_dhcp6relay_counter.py | ||||
|  | ||||
| $(DOCKER_DHCP_RELAY)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) | ||||
|   | ||||
| @@ -196,6 +196,7 @@ define generate_manifest | ||||
|     $(eval export tmpfs=$($(1).gz_CONTAINER_TMPFS)) | ||||
|     $(eval export config_cli_plugin=$($(1).gz_CLI_CONFIG_PLUGIN)) | ||||
|     $(eval export show_cli_plugin=$($(1).gz_CLI_SHOW_PLUGIN)) | ||||
|     $(eval export clear_cli_plugin=$($(1).gz_CLI_CLEAR_PLUGIN)) | ||||
|     j2 $($*.gz_PATH)/Dockerfile$(2).j2 > $($(1).gz_PATH)/Dockerfile$(2) | ||||
|     j2 --customize scripts/j2cli/json_filter.py files/build_templates/manifest.json.j2 > $($(1).gz_PATH)/manifest.common.json | ||||
|     if [ -f $($*.gz_PATH)/manifest.part.json.j2 ]; then | ||||
|   | ||||
| @@ -486,6 +486,10 @@ EXPOSE 22 | ||||
| RUN git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git /usr/share/depot_tools | ||||
| ENV PATH /usr/share/depot_tools:$PATH | ||||
|  | ||||
| # Install dependencies for dhcp relay test  | ||||
| RUN pip3 install parameterized==0.8.1 | ||||
| RUN pip3 install pyfakefs | ||||
|  | ||||
| # Install docker engine 17.03.2~ce-0 inside docker and enable experimental feature | ||||
| RUN apt-get update | ||||
| RUN apt-get install -y \ | ||||
|   | ||||
| @@ -291,6 +291,10 @@ RUN apt-get update && apt-get install -y \ | ||||
|         python-lxml \ | ||||
|         libexpat1-dev | ||||
|  | ||||
| # Install dependencies for dhcp relay test  | ||||
| RUN pip3 install parameterized==0.8.1 | ||||
| RUN pip3 install pyfakefs | ||||
|  | ||||
| ## Config dpkg | ||||
| ## install the configuration file if it’s currently missing | ||||
| RUN sudo augtool --autosave "set /files/etc/dpkg/dpkg.cfg/force-confmiss" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 kellyyeh
					kellyyeh