#!/usr/bin/env python
#
# Copyright 2016 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import argparse
import os
import readline
import sys
from optparse import make_option
from time import sleep, time

import grpc
import requests
from cmd2 import Cmd, options
from consul import Consul
from google.protobuf.empty_pb2 import Empty
from simplejson import dumps

from cli.device import DeviceCli
from cli.xpon import XponCli
from cli.omci import OmciCli
from cli.alarm_filters import AlarmFiltersCli
from cli.logical_device import LogicalDeviceCli
from cli.table import print_pb_list_as_table
from voltha.core.flow_decomposer import *
from voltha.protos import third_party
from voltha.protos import voltha_pb2
from voltha.protos.openflow_13_pb2 import FlowTableUpdate, FlowGroupTableUpdate

_ = third_party
from cli.utils import pb2dict

defs = dict(
    # config=os.environ.get('CONFIG', './cli.yml'),
    consul=os.environ.get('CONSUL', 'localhost:8500'),
    voltha_grpc_endpoint=os.environ.get('VOLTHA_GRPC_ENDPOINT',
                                        'localhost:50055'),
    voltha_sim_rest_endpoint=os.environ.get('VOLTHA_SIM_REST_ENDPOINT',
                                            'localhost:18880'),
    global_request=os.environ.get('GLOBAL_REQUEST', False)
)

banner = """\
         _ _   _            ___ _    ___
__ _____| | |_| |_  __ _   / __| |  |_ _|
\ V / _ \ |  _| ' \/ _` | | (__| |__ | |
 \_/\___/_|\__|_||_\__,_|  \___|____|___|
(to exit type quit or hit Ctrl-D)
"""


class VolthaCli(Cmd):
    prompt = 'voltha'
    history_file_name = '.voltha_cli_history'

    # Settable CLI parameters
    voltha_grpc = 'localhost:50055'
    voltha_sim_rest = 'localhost:18880'
    global_request = False
    max_history_lines = 500
    default_device_id = None
    default_logical_device_id = None

    Cmd.settable.update(dict(
        voltha_grpc='Voltha GRPC endpoint in form of <host>:<port>',
        voltha_sim_rest='Voltha simulation back door for testing in form '
                        'of <host>:<port>',
        max_history_lines='Maximum number of history lines stored across '
                          'sessions',
        default_device_id='Device id used when no device id is specified',
        default_logical_device_id='Logical device id used when no device id '
                                  'is specified',
    ))

    # cleanup of superfluous commands from cmd2
    del Cmd.do_cmdenvironment
    del Cmd.do_load
    del Cmd.do__relative_load

    def __init__(self, voltha_grpc, voltha_sim_rest, global_request=False):
        VolthaCli.voltha_grpc = voltha_grpc
        VolthaCli.voltha_sim_rest = voltha_sim_rest
        VolthaCli.global_request = global_request
        Cmd.__init__(self)
        self.prompt = '(' + self.colorize(
            self.colorize(self.prompt, 'blue'), 'bold') + ') '
        self.channel = None
        self.stub = None
        self.device_ids_cache = None
        self.device_ids_cache_ts = time()
        self.logical_device_ids_cache = None
        self.logical_device_ids_cache_ts = time()

    # we override cmd2's method to avoid its optparse conflicting with our
    # command line parsing
    def cmdloop(self):
        self._cmdloop()

    def load_history(self):
        """Load saved command history from local history file"""
        try:
            with file(self.history_file_name, 'r') as f:
                for line in f.readlines():
                    stripped_line = line.strip()
                    self.history.append(stripped_line)
                    readline.add_history(stripped_line)
        except IOError:
            pass  # ignore if file cannot be read

    def save_history(self):
        try:
            with open(self.history_file_name, 'w') as f:
                f.write('\n'.join(self.history[-self.max_history_lines:]))
        except IOError as e:
            self.perror('Could not save history in {}: {}'.format(
                self.history_file_name, e))
        else:
            self.poutput('History saved as {}'.format(
                self.history_file_name))

    def perror(self, errmsg, statement=None):
        # Touch it up to make sure error is prefixed and colored
        Cmd.perror(self, self.colorize('***ERROR: ', 'red') + errmsg,
                   statement)

    def get_channel(self):
        if self.channel is None:
            self.channel = grpc.insecure_channel(self.voltha_grpc)
        return self.channel

    def get_stub(self):
        if self.stub is None:
            self.stub = \
                voltha_pb2.VolthaGlobalServiceStub(self.get_channel()) \
                    if self.global_request else \
                        voltha_pb2.VolthaLocalServiceStub(self.get_channel())
        return self.stub

    # ~~~~~~~~~~~~~~~~~ ACTUAL COMMAND IMPLEMENTATIONS ~~~~~~~~~~~~~~~~~~~~~~~~

    def do_reset_history(self, line):
        """Reset CLI history"""
        while self.history:
            self.history.pop()

    def do_launch(self, line):
        """If Voltha is not running yet, launch it"""
        raise NotImplementedError('not implemented yet')

    def do_restart(self, line):
        """Launch Voltha, but if it is already running, terminate it first"""
        pass

    def do_adapters(self, line):
        """List loaded adapter"""
        stub = self.get_stub()
        res = stub.ListAdapters(Empty())
        omit_fields = {'config.log_level', 'logical_device_ids'}
        print_pb_list_as_table('Adapters:', res.items, omit_fields, self.poutput)

    def get_devices(self):
        stub = self.get_stub()
        res = stub.ListDevices(Empty())
        return res.items

    def get_logical_devices(self):
        stub = self.get_stub()
        res = stub.ListLogicalDevices(Empty())
        return res.items

    def do_devices(self, line):
        """List devices registered in Voltha"""
        devices = self.get_devices()
        omit_fields = {
            'adapter',
            'vendor',
            'model',
            'hardware_version',
            'images',
            'firmware_version',
            'vendor_id'
        }
        print_pb_list_as_table('Devices:', devices, omit_fields, self.poutput)

    def do_logical_devices(self, line):
        """List logical devices in Voltha"""
        stub = self.get_stub()
        res = stub.ListLogicalDevices(Empty())
        omit_fields = {
            'desc.mfr_desc',
            'desc.hw_desc',
            'desc.sw_desc',
            'desc.dp_desc',
            'desc.serial_number',
            'switch_features.capabilities'
        }
        print_pb_list_as_table('Logical devices:', res.items, omit_fields,
                               self.poutput)

    def do_device(self, line):
        """Enter device level command mode"""
        device_id = line.strip() or self.default_device_id
        if not device_id:
            raise Exception('<device-id> parameter needed')
        if device_id not in self.device_ids():
            self.poutput( self.colorize('Error: ', 'red') +
                            'There is no such device')
            raise Exception('<device-id> is not a valid one')
        sub = DeviceCli(device_id, self.get_stub)
        sub.cmdloop()

    def do_logical_device(self, line):
        """Enter logical device level command mode"""
        logical_device_id = line.strip() or self.default_logical_device_id
        if not logical_device_id:
            raise Exception('<logical-device-id> parameter needed')
        if logical_device_id not in self.logical_device_ids():
            self.poutput( self.colorize('Error: ', 'red') +
                            'There is no such device')
            raise Exception('<logical-device-id> is not a valid one')
        sub = LogicalDeviceCli(logical_device_id, self.get_stub)
        sub.cmdloop()

    def device_ids(self, force_refresh=False):
        if force_refresh or self.device_ids is None or \
                        (time() - self.device_ids_cache_ts) > 1:
            self.device_ids_cache = [d.id for d in self.get_devices()]
            self.device_ids_cache_ts = time()
        return self.device_ids_cache

    def logical_device_ids(self, force_refresh=False):
        if force_refresh or self.logical_device_ids is None or \
                        (time() - self.logical_device_ids_cache_ts) > 1:
            self.logical_device_ids_cache = [d.id for d
                                             in self.get_logical_devices()]
            self.logical_device_ids_cache_ts = time()
        return self.logical_device_ids_cache

    def complete_device(self, text, line, begidx, endidx):
        if not text:
            completions = self.device_ids()[:]
        else:
            completions = [d for d in self.device_ids() if d.startswith(text)]
        return completions

    def complete_logical_device(self, text, line, begidx, endidx):
        if not text:
            completions = self.logical_device_ids()[:]
        else:
            completions = [d for d in self.logical_device_ids()
                           if d.startswith(text)]
        return completions

    def do_xpon(self, line):
        """xpon <optional> [device_ID] - Enter xpon level command mode"""
        device_id = line.strip()
        if device_id:
            stub = self.get_stub()
            try:
                res = stub.GetDevice(voltha_pb2.ID(id=device_id))
            except Exception:
                self.poutput(
                    self.colorize('Error: ', 'red') + 'No device id ' +
                    self.colorize(device_id, 'blue') + ' is found')
                return
        sub = XponCli(self.get_channel, device_id)
        sub.cmdloop()

    def do_omci(self, line):
        """omci <device_ID> - Enter OMCI level command mode"""

        device_id = line.strip() or self.default_device_id
        if not device_id:
            raise Exception('<device-id> parameter needed')
        sub = OmciCli(device_id, self.get_stub)
        sub.cmdloop()

    def do_pdb(self, line):
        """Launch PDB debug prompt in CLI (for CLI development)"""
        from pdb import set_trace
        set_trace()

    def do_version(self, line):
        """Show the VOLTHA core version"""
        stub = self.get_stub()
        voltha = stub.GetVoltha(Empty())
        self.poutput('{}'.format(voltha.version))

    def do_health(self, line):
        """Show connectivity status to Voltha status"""
        stub = voltha_pb2.HealthServiceStub(self.get_channel())
        res = stub.GetHealthStatus(Empty())
        self.poutput(dumps(pb2dict(res), indent=4))

    @options([
        make_option('-t', '--device-type', action="store", dest='device_type',
                    help="Device type", default='simulated_olt'),
        make_option('-m', '--mac-address', action='store', dest='mac_address',
                    default='00:0c:e2:31:40:00'),
        make_option('-i', '--ip-address', action='store', dest='ip_address'),
        make_option('-H', '--host_and_port', action='store',
                    dest='host_and_port'),
    ])
    def do_preprovision_olt(self, line, opts):
        """Preprovision a new OLT with given device type"""
        stub = self.get_stub()
        kw = dict(type=opts.device_type)
        if opts.host_and_port:
            kw['host_and_port'] = opts.host_and_port
        elif opts.ip_address:
            kw['ipv4_address'] = opts.ip_address
        elif opts.mac_address:
            kw['mac_address'] = opts.mac_address.lower()
        else:
            raise Exception('Either IP address or Mac Address is needed')
        # Pass any extra arguments past '--' to the device as custom arguments
        kw['extra_args'] = line

        device = voltha_pb2.Device(**kw)
        device = stub.CreateDevice(device)
        self.poutput('success (device id = {})'.format(device.id))
        self.default_device_id = device.id

    def do_enable(self, line):
        """
        Enable a device. If the <id> is not provided, it will be on the last
        pre-provisioned device.
        """
        device_id = line or self.default_device_id
        self.poutput('enabling {}'.format(device_id))
        try:
            stub = self.get_stub()
            stub.EnableDevice(voltha_pb2.ID(id=device_id))

            while True:
                device = stub.GetDevice(voltha_pb2.ID(id=device_id))
                # If this is an OLT then acquire logical device id
                if device.oper_status == voltha_pb2.OperStatus.ACTIVE:
                    if device.type.endswith('_olt'):
                        assert device.parent_id
                        self.default_logical_device_id = device.parent_id
                        self.poutput('success (logical device id = {})'.format(
                            self.default_logical_device_id))
                    else:
                        self.poutput('success (device id = {})'.format(device.id))
                    break
                self.poutput('waiting for device to be enabled...')
                sleep(.5)
        except Exception as e:
            self.poutput('Error enabling {}.  Error:{}'.format(device_id, e))

    complete_activate_olt = complete_device

    def do_reboot(self, line):
        """
        Rebooting a device. ID of the device needs to be provided
        """
        device_id = line or self.default_device_id
        self.poutput('rebooting {}'.format(device_id))
        try:
            stub = self.get_stub()
            stub.RebootDevice(voltha_pb2.ID(id=device_id))
            self.poutput('rebooted {}'.format(device_id))
        except Exception as e:
            self.poutput('Error rebooting {}.  Error:{}'.format(device_id, e))

    def do_self_test(self, line):
        """
        Self Test a device. ID of the device needs to be provided
        """
        device_id = line or self.default_device_id
        self.poutput('Self Testing {}'.format(device_id))
        try:
            stub = self.get_stub()
            res = stub.SelfTest(voltha_pb2.ID(id=device_id))
            self.poutput('Self Tested {}'.format(device_id))
            self.poutput(dumps(pb2dict(res), indent=4))
        except Exception as e:
            self.poutput('Error in self test {}.  Error:{}'.format(device_id, e))

    def do_delete(self, line):
        """
        Deleting a device. ID of the device needs to be provided
        """
        device_id = line or self.default_device_id
        self.poutput('deleting {}'.format(device_id))
        try:
            stub = self.get_stub()
            stub.DeleteDevice(voltha_pb2.ID(id=device_id))
            self.poutput('deleted {}'.format(device_id))
        except Exception as e:
            self.poutput('Error deleting {}.  Error:{}'.format(device_id, e))

    def do_disable(self, line):
        """
        Disable a device. ID of the device needs to be provided
        """
        device_id = line
        self.poutput('disabling {}'.format(device_id))
        try:
            stub = self.get_stub()
            stub.DisableDevice(voltha_pb2.ID(id=device_id))

            # Do device query and verify that the device admin status is
            # DISABLED and Operational Status is unknown
            device = stub.GetDevice(voltha_pb2.ID(id=device_id))
            if device.admin_state == voltha_pb2.AdminState.DISABLED:
                self.poutput('disabled successfully {}'.format(device_id))
            else:
                self.poutput('disabling failed {}.  Admin State:{} '
                             'Operation State: {}'.format(device_id,
                                                          device.admin_state,
                                                          device.oper_status))
        except Exception as e:
            self.poutput('Error disabling {}.  Error:{}'.format(device_id, e))

    def do_test(self, line):
        """Enter test mode, which makes a bunch on new commands available"""
        sub = TestCli(self.history, self.voltha_grpc,
                      self.get_stub, self.voltha_sim_rest)
        sub.cmdloop()

    def do_alarm_filters(self, line):
        sub = AlarmFiltersCli(self.get_stub)
        sub.cmdloop()


class TestCli(VolthaCli):
    def __init__(self, history, voltha_grpc, get_stub, voltha_sim_rest):
        VolthaCli.__init__(self, voltha_grpc, voltha_sim_rest)
        self.history = history
        self.get_stub = get_stub
        self.prompt = '(' + self.colorize(self.colorize('test', 'cyan'),
                                          'bold') + ') '

    def get_device(self, device_id, depth=0):
        stub = self.get_stub()
        res = stub.GetDevice(voltha_pb2.ID(id=device_id),
                             metadata=(('get-depth', str(depth)),))
        return res

    def do_arrive_onus(self, line):
        """
        Simulate the arrival of ONUs (available only on simulated_olt)
        """
        device_id = line or self.default_device_id

        # verify that device is of type simulated_olt
        device = self.get_device(device_id)
        assert device.type == 'simulated_olt', (
            'Cannot use it on this device type (only on simulated_olt type)')

        requests.get('http://{}/devices/{}/detect_onus'.format(
            self.voltha_sim_rest, device_id
        ))

    complete_arrive_onus = VolthaCli.complete_device

    def get_logical_ports(self, logical_device_id):
        """
        Return the NNI port number and the first usable UNI port of logical
        device, and the vlan associated with the latter.
        """
        stub = self.get_stub()
        ports = stub.ListLogicalDevicePorts(
            voltha_pb2.ID(id=logical_device_id)).items
        nni = None
        unis = []
        for port in ports:
            if port.root_port:
                assert nni is None, "There shall be only one root port"
                nni = port.ofp_port.port_no
            else:
                uni = port.ofp_port.port_no
                uni_device = self.get_device(port.device_id)
                vlan = uni_device.vlan
                unis.append((uni, vlan))

        assert nni is not None, "No NNI port found"
        assert unis, "Not a single UNI?"

        return nni, unis

    def do_install_eapol_flow(self, line):
        """
        Install an EAPOL flow on the given logical device. If device is not
        given, it will be applied to logical device of the last pre-provisioned
        OLT device.
        """
        logical_device_id = line or self.default_logical_device_id

        # gather NNI and UNI port IDs
        nni_port_no, unis = self.get_logical_ports(logical_device_id)

        # construct and push flow rule
        stub = self.get_stub()
        for uni_port_no, _ in unis:
            update = FlowTableUpdate(
                id=logical_device_id,
                flow_mod=mk_simple_flow_mod(
                    priority=2000,
                    match_fields=[in_port(uni_port_no), eth_type(0x888e)],
                    actions=[
                        # push_vlan(0x8100),
                        # set_field(vlan_vid(4096 + 4000)),
                        output(ofp.OFPP_CONTROLLER)
                    ]
                )
            )
            res = stub.UpdateLogicalDeviceFlowTable(update)
            self.poutput('success for uni {} ({})'.format(uni_port_no, res))

    complete_install_eapol_flow = VolthaCli.complete_logical_device

    def do_install_all_controller_bound_flows(self, line):
        """
        Install all flow rules for controller bound flows, including EAPOL,
        IGMP and DHCP. If device is not given, it will be applied to logical
        device of the last pre-provisioned OLT device.
        """
        logical_device_id = line or self.default_logical_device_id

        # gather NNI and UNI port IDs
        nni_port_no, unis = self.get_logical_ports(logical_device_id)

        # construct and push flow rules
        stub = self.get_stub()

        for uni_port_no, _ in unis:
            stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
                id=logical_device_id,
                flow_mod=mk_simple_flow_mod(
                    priority=2000,
                    match_fields=[
                        in_port(uni_port_no),
                        eth_type(0x888e)
                    ],
                    actions=[output(ofp.OFPP_CONTROLLER)]
                )
            ))
            stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
                id=logical_device_id,
                flow_mod=mk_simple_flow_mod(
                    priority=1000,
                    match_fields=[
                        in_port(uni_port_no),
                        eth_type(0x800),
                        ip_proto(2)
                    ],
                    actions=[output(ofp.OFPP_CONTROLLER)]
                )
            ))
            stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
                id=logical_device_id,
                flow_mod=mk_simple_flow_mod(
                    priority=1000,
                    match_fields=[
                        in_port(uni_port_no),
                        eth_type(0x800),
                        ip_proto(17),
                        udp_dst(67)
                    ],
                    actions=[output(ofp.OFPP_CONTROLLER)]
                )
            ))
        self.poutput('success')

    complete_install_all_controller_bound_flows = \
        VolthaCli.complete_logical_device

    def do_install_all_sample_flows(self, line):
        """
        Install all flows that are representative of the virtualized access
        scenario in a PON network.
        """
        logical_device_id = line or self.default_logical_device_id

        # gather NNI and UNI port IDs
        nni_port_no, unis = self.get_logical_ports(logical_device_id)

        # construct and push flow rules
        stub = self.get_stub()

        for uni_port_no, c_vid in unis:
            # Controller-bound flows
            stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
                id=logical_device_id,
                flow_mod=mk_simple_flow_mod(
                    priority=2000,
                    match_fields=[in_port(uni_port_no), eth_type(0x888e)],
                    actions=[
                        # push_vlan(0x8100),
                        # set_field(vlan_vid(4096 + 4000)),
                        output(ofp.OFPP_CONTROLLER)
                    ]
                )
            ))
            stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
                id=logical_device_id,
                flow_mod=mk_simple_flow_mod(
                    priority=1000,
                    match_fields=[eth_type(0x800), ip_proto(2)],
                    actions=[output(ofp.OFPP_CONTROLLER)]
                )
            ))
            stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
                id=logical_device_id,
                flow_mod=mk_simple_flow_mod(
                    priority=1000,
                    match_fields=[eth_type(0x800), ip_proto(17), udp_dst(67)],
                    actions=[output(ofp.OFPP_CONTROLLER)]
                )
            ))

            # Unicast flows:
            # Downstream flow 1
            stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
                id=logical_device_id,
                flow_mod=mk_simple_flow_mod(
                    priority=500,
                    match_fields=[
                        in_port(nni_port_no),
                        vlan_vid(4096 + 1000),
                        metadata(c_vid)  # here to mimic an ONOS artifact
                    ],
                    actions=[pop_vlan()],
                    next_table_id=1
                )
            ))
            # Downstream flow 2
            stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
                id=logical_device_id,
                flow_mod=mk_simple_flow_mod(
                    priority=500,
                    table_id=1,
                    match_fields=[in_port(nni_port_no), vlan_vid(4096 + c_vid)],
                    actions=[set_field(vlan_vid(4096 + 0)), output(uni_port_no)]
                )
            ))
            # Upstream flow 1 for 0-tagged case
            stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
                id=logical_device_id,
                flow_mod=mk_simple_flow_mod(
                    priority=500,
                    match_fields=[in_port(uni_port_no), vlan_vid(4096 + 0)],
                    actions=[set_field(vlan_vid(4096 + c_vid))],
                    next_table_id=1
                )
            ))
            # Upstream flow 1 for untagged case
            stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
                id=logical_device_id,
                flow_mod=mk_simple_flow_mod(
                    priority=500,
                    match_fields=[in_port(uni_port_no), vlan_vid(0)],
                    actions=[push_vlan(0x8100), set_field(vlan_vid(4096 + c_vid))],
                    next_table_id=1
                )
            ))
            # Upstream flow 2 for s-tag
            stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
                id=logical_device_id,
                flow_mod=mk_simple_flow_mod(
                    priority=500,
                    table_id=1,
                    match_fields=[in_port(uni_port_no), vlan_vid(4096 + c_vid)],
                    actions=[
                        push_vlan(0x8100),
                        set_field(vlan_vid(4096 + 1000)),
                        output(nni_port_no)
                    ]
                )
            ))

        # Push a few multicast flows
        # 1st with one bucket for our uni 0
        stub.UpdateLogicalDeviceFlowGroupTable(FlowGroupTableUpdate(
            id=logical_device_id,
            group_mod=mk_multicast_group_mod(
                group_id=1,
                buckets=[
                    ofp.ofp_bucket(actions=[
                        pop_vlan(),
                        output(unis[0][0])
                    ])
                ]
            )
        ))
        stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
            id=logical_device_id,
            flow_mod=mk_simple_flow_mod(
                priority=1000,
                match_fields=[
                    in_port(nni_port_no),
                    eth_type(0x800),
                    vlan_vid(4096 + 140),
                    ipv4_dst(0xe4010101)
                ],
                actions=[group(1)]
            )
        ))

        # 2nd with one bucket for uni 0 and 1
        stub.UpdateLogicalDeviceFlowGroupTable(FlowGroupTableUpdate(
            id=logical_device_id,
            group_mod=mk_multicast_group_mod(
                group_id=2,
                buckets=[
                    ofp.ofp_bucket(actions=[pop_vlan(), output(unis[0][0])])
                    #                    ofp.ofp_bucket(actions=[pop_vlan(), output(unis[1][0])])
                ]
            )
        ))
        stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
            id=logical_device_id,
            flow_mod=mk_simple_flow_mod(
                priority=1000,
                match_fields=[
                    in_port(nni_port_no),
                    eth_type(0x800),
                    vlan_vid(4096 + 140),
                    ipv4_dst(0xe4020202)
                ],
                actions=[group(2)]
            )
        ))

        # 3rd with empty bucket
        stub.UpdateLogicalDeviceFlowGroupTable(FlowGroupTableUpdate(
            id=logical_device_id,
            group_mod=mk_multicast_group_mod(
                group_id=3,
                buckets=[]
            )
        ))
        stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
            id=logical_device_id,
            flow_mod=mk_simple_flow_mod(
                priority=1000,
                match_fields=[
                    in_port(nni_port_no),
                    eth_type(0x800),
                    vlan_vid(4096 + 140),
                    ipv4_dst(0xe4030303)
                ],
                actions=[group(3)]
            )
        ))

        self.poutput('success')

    complete_install_all_sample_flows = VolthaCli.complete_logical_device

    def do_install_dhcp_flows(self, line):
        """
        Install all dhcp flows that are representative of the virtualized access
        scenario in a PON network.
        """
        logical_device_id = line or self.default_logical_device_id

        # gather NNI and UNI port IDs
        nni_port_no, unis = self.get_logical_ports(logical_device_id)

        # construct and push flow rules
        stub = self.get_stub()

        # Controller-bound flows
        for uni_port_no, _ in unis:
            stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
                id=logical_device_id,
                flow_mod=mk_simple_flow_mod(
                    priority=1000,
                    match_fields=[
                        in_port(uni_port_no),
                        eth_type(0x800),
                        ip_proto(17),
                        udp_dst(67)
                    ],
                    actions=[output(ofp.OFPP_CONTROLLER)]
                )
            ))

        self.poutput('success')

    complete_install_dhcp_flows = VolthaCli.complete_logical_device

    def do_delete_all_flows(self, line):
        """
        Remove all flows and flow groups from given logical device
        """
        logical_device_id = line or self.default_logical_device_id
        stub = self.get_stub()
        stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
            id=logical_device_id,
            flow_mod=ofp.ofp_flow_mod(
                command=ofp.OFPFC_DELETE,
                table_id=ofp.OFPTT_ALL,
                cookie_mask=0,
                out_port=ofp.OFPP_ANY,
                out_group=ofp.OFPG_ANY
            )
        ))
        stub.UpdateLogicalDeviceFlowGroupTable(FlowGroupTableUpdate(
            id=logical_device_id,
            group_mod=ofp.ofp_group_mod(
                command=ofp.OFPGC_DELETE,
                group_id=ofp.OFPG_ALL
            )
        ))
        self.poutput('success')

    complete_delete_all_flows = VolthaCli.complete_logical_device

    def do_send_simulated_upstream_eapol(self, line):
        """
        Send an EAPOL upstream from a simulated OLT
        """
        device_id = line or self.default_device_id
        requests.get('http://{}/devices/{}/test_eapol_in'.format(
            self.voltha_sim_rest, device_id
        ))

    complete_send_simulated_upstream_eapol = VolthaCli.complete_device

    def do_inject_eapol_start(self, line):
        """
        Send out an an EAPOL start message into the given Unix interface
        """
        pass


if __name__ == '__main__':

    parser = argparse.ArgumentParser()

    _help = '<hostname>:<port> to consul agent (default: %s)' % defs['consul']
    parser.add_argument(
        '-C', '--consul', action='store', default=defs['consul'], help=_help)

    _help = 'Lookup Voltha endpoints based on service entries in Consul'
    parser.add_argument(
        '-L', '--lookup', action='store_true', help=_help)

    _help = 'All requests to the Voltha gRPC service are global'
    parser.add_argument(
        '-G', '--global_request', action='store_true', help=_help)

    _help = '<hostname>:<port> of Voltha gRPC service (default={})'.format(
        defs['voltha_grpc_endpoint'])
    parser.add_argument('-g', '--grpc-endpoint', action='store',
                        default=defs['voltha_grpc_endpoint'], help=_help)

    _help = '<hostname>:<port> of Voltha simulated adapter backend for ' \
            'testing (default={})'.format(
        defs['voltha_sim_rest_endpoint'])
    parser.add_argument('-s', '--sim-rest-endpoint', action='store',
                        default=defs['voltha_sim_rest_endpoint'], help=_help)

    args = parser.parse_args()

    if args.lookup:
        host = args.consul.split(':')[0].strip()
        port = int(args.consul.split(':')[1].strip())
        consul = Consul(host=host, port=port)

        _, services = consul.catalog.service('voltha-grpc')
        if not services:
            print('No voltha-grpc service registered in consul; exiting')
            sys.exit(1)
        args.grpc_endpoint = '{}:{}'.format(services[0]['ServiceAddress'],
                                            services[0]['ServicePort'])

        _, services = consul.catalog.service('voltha-sim-rest')
        if not services:
            print('No voltha-sim-rest service registered in consul; exiting')
            sys.exit(1)
        args.sim_rest_endpoint = '{}:{}'.format(services[0]['ServiceAddress'],
                                                services[0]['ServicePort'])

    c = VolthaCli(args.grpc_endpoint, args.sim_rest_endpoint,
                  args.global_request)
    c.poutput(banner)
    c.load_history()
    c.cmdloop()
    c.save_history()
