#!/usr/bin/perl -w
################################################################################
# 
# "This software program is licensed subject to the GNU General Public License 
# (GPL). Version 2, June 1991, available at 
# <http://www.fsf.org/copyleft/gpl.html>"
# 
# GNU General Public License 
# 
# Version 2, June 1991
# 
# Copyright (C) 1989, 1991 Free Software Foundation, Inc.  
# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
# 
# Everyone is permitted to copy and distribute verbatim copies of this license
# document, but changing it is not allowed.
# 
# Preamble
# 
# The licenses for most software are designed to take away your freedom to 
# share and change it. By contrast, the GNU General Public License is intended
# to guarantee your freedom to share and change free software--to make sure 
# the software is free for all its users. This General Public License applies 
# to most of the Free Software Foundation's software and to any other program 
# whose authors commit to using it. (Some other Free Software Foundation 
# software is covered by the GNU Library General Public License instead.) You 
# can apply it to your programs, too.
# 
# When we speak of free software, we are referring to freedom, not price. Our
# General Public Licenses are designed to make sure that you have the freedom 
# to distribute copies of free software (and charge for this service if you 
# wish), that you receive source code or can get it if you want it, that you 
# can change the software or use pieces of it in new free programs; and that 
# you know you can do these things.
# 
# To protect your rights, we need to make restrictions that forbid anyone to 
# deny you these rights or to ask you to surrender the rights. These 
# restrictions translate to certain responsibilities for you if you distribute
# copies of the software, or if you modify it.
# 
# For example, if you distribute copies of such a program, whether gratis or 
# for a fee, you must give the recipients all the rights that you have. You 
# must make sure that they, too, receive or can get the source code. And you 
# must show them these terms so they know their rights.
#  
# We protect your rights with two steps: (1) copyright the software, and (2) 
# offer you this license which gives you legal permission to copy, distribute 
# and/or modify the software. 
# 
# Also, for each author's protection and ours, we want to make certain that 
# everyone understands that there is no warranty for this free software. If 
# the software is modified by someone else and passed on, we want its 
# recipients to know that what they have is not the original, so that any 
# problems introduced by others will not reflect on the original authors' 
# reputations. 
# 
# Finally, any free program is threatened constantly by software patents. We 
# wish to avoid the danger that redistributors of a free program will 
# individually obtain patent licenses, in effect making the program 
# proprietary. To prevent this, we have made it clear that any patent must be 
# licensed for everyone's free use or not licensed at all. 
# 
# The precise terms and conditions for copying, distribution and modification 
# follow. 
# 
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
# 
# 0. This License applies to any program or other work which contains a notice
#    placed by the copyright holder saying it may be distributed under the 
#    terms of this General Public License. The "Program", below, refers to any
#    such program or work, and a "work based on the Program" means either the 
#    Program or any derivative work under copyright law: that is to say, a 
#    work containing the Program or a portion of it, either verbatim or with 
#    modifications and/or translated into another language. (Hereinafter, 
#    translation is included without limitation in the term "modification".) 
#    Each licensee is addressed as "you". 
# 
#    Activities other than copying, distribution and modification are not 
#    covered by this License; they are outside its scope. The act of running 
#    the Program is not restricted, and the output from the Program is covered 
#    only if its contents constitute a work based on the Program (independent 
#    of having been made by running the Program). Whether that is true depends
#    on what the Program does. 
# 
# 1. You may copy and distribute verbatim copies of the Program's source code 
#    as you receive it, in any medium, provided that you conspicuously and 
#    appropriately publish on each copy an appropriate copyright notice and 
#    disclaimer of warranty; keep intact all the notices that refer to this 
#    License and to the absence of any warranty; and give any other recipients 
#    of the Program a copy of this License along with the Program. 
# 
#    You may charge a fee for the physical act of transferring a copy, and you 
#    may at your option offer warranty protection in exchange for a fee. 
# 
# 2. You may modify your copy or copies of the Program or any portion of it, 
#    thus forming a work based on the Program, and copy and distribute such 
#    modifications or work under the terms of Section 1 above, provided that 
#    you also meet all of these conditions: 
# 
#    * a) You must cause the modified files to carry prominent notices stating 
#         that you changed the files and the date of any change. 
# 
#    * b) You must cause any work that you distribute or publish, that in 
#         whole or in part contains or is derived from the Program or any part 
#         thereof, to be licensed as a whole at no charge to all third parties
#         under the terms of this License. 
# 
#    * c) If the modified program normally reads commands interactively when 
#         run, you must cause it, when started running for such interactive 
#         use in the most ordinary way, to print or display an announcement 
#         including an appropriate copyright notice and a notice that there is
#         no warranty (or else, saying that you provide a warranty) and that 
#         users may redistribute the program under these conditions, and 
#         telling the user how to view a copy of this License. (Exception: if 
#         the Program itself is interactive but does not normally print such 
#         an announcement, your work based on the Program is not required to 
#         print an announcement.) 
# 
#    These requirements apply to the modified work as a whole. If identifiable 
#    sections of that work are not derived from the Program, and can be 
#    reasonably considered independent and separate works in themselves, then 
#    this License, and its terms, do not apply to those sections when you 
#    distribute them as separate works. But when you distribute the same 
#    sections as part of a whole which is a work based on the Program, the 
#    distribution of the whole must be on the terms of this License, whose 
#    permissions for other licensees extend to the entire whole, and thus to 
#    each and every part regardless of who wrote it. 
# 
#    Thus, it is not the intent of this section to claim rights or contest 
#    your rights to work written entirely by you; rather, the intent is to 
#    exercise the right to control the distribution of derivative or 
#    collective works based on the Program. 
# 
#    In addition, mere aggregation of another work not based on the Program 
#    with the Program (or with a work based on the Program) on a volume of a 
#    storage or distribution medium does not bring the other work under the 
#    scope of this License. 
# 
# 3. You may copy and distribute the Program (or a work based on it, under 
#    Section 2) in object code or executable form under the terms of Sections 
#    1 and 2 above provided that you also do one of the following: 
# 
#    * a) Accompany it with the complete corresponding machine-readable source 
#         code, which must be distributed under the terms of Sections 1 and 2 
#         above on a medium customarily used for software interchange; or, 
# 
#    * b) Accompany it with a written offer, valid for at least three years, 
#         to give any third party, for a charge no more than your cost of 
#         physically performing source distribution, a complete machine-
#         readable copy of the corresponding source code, to be distributed 
#         under the terms of Sections 1 and 2 above on a medium customarily 
#         used for software interchange; or, 
# 
#    * c) Accompany it with the information you received as to the offer to 
#         distribute corresponding source code. (This alternative is allowed 
#         only for noncommercial distribution and only if you received the 
#         program in object code or executable form with such an offer, in 
#         accord with Subsection b above.) 
# 
#    The source code for a work means the preferred form of the work for 
#    making modifications to it. For an executable work, complete source code 
#    means all the source code for all modules it contains, plus any 
#    associated interface definition files, plus the scripts used to control 
#    compilation and installation of the executable. However, as a special 
#    exception, the source code distributed need not include anything that is 
#    normally distributed (in either source or binary form) with the major 
#    components (compiler, kernel, and so on) of the operating system on which
#    the executable runs, unless that component itself accompanies the 
#    executable. 
# 
#    If distribution of executable or object code is made by offering access 
#    to copy from a designated place, then offering equivalent access to copy 
#    the source code from the same place counts as distribution of the source 
#    code, even though third parties are not compelled to copy the source 
#    along with the object code. 
# 
# 4. You may not copy, modify, sublicense, or distribute the Program except as
#    expressly provided under this License. Any attempt otherwise to copy, 
#    modify, sublicense or distribute the Program is void, and will 
#    automatically terminate your rights under this License. However, parties 
#    who have received copies, or rights, from you under this License will not
#    have their licenses terminated so long as such parties remain in full 
#    compliance. 
# 
# 5. You are not required to accept this License, since you have not signed 
#    it. However, nothing else grants you permission to modify or distribute 
#    the Program or its derivative works. These actions are prohibited by law 
#    if you do not accept this License. Therefore, by modifying or 
#    distributing the Program (or any work based on the Program), you 
#    indicate your acceptance of this License to do so, and all its terms and
#    conditions for copying, distributing or modifying the Program or works 
#    based on it. 
# 
# 6. Each time you redistribute the Program (or any work based on the 
#    Program), the recipient automatically receives a license from the 
#    original licensor to copy, distribute or modify the Program subject to 
#    these terms and conditions. You may not impose any further restrictions 
#    on the recipients' exercise of the rights granted herein. You are not 
#    responsible for enforcing compliance by third parties to this License. 
# 
# 7. If, as a consequence of a court judgment or allegation of patent 
#    infringement or for any other reason (not limited to patent issues), 
#    conditions are imposed on you (whether by court order, agreement or 
#    otherwise) that contradict the conditions of this License, they do not 
#    excuse you from the conditions of this License. If you cannot distribute 
#    so as to satisfy simultaneously your obligations under this License and 
#    any other pertinent obligations, then as a consequence you may not 
#    distribute the Program at all. For example, if a patent license would 
#    not permit royalty-free redistribution of the Program by all those who 
#    receive copies directly or indirectly through you, then the only way you 
#    could satisfy both it and this License would be to refrain entirely from 
#    distribution of the Program. 
# 
#    If any portion of this section is held invalid or unenforceable under any
#    particular circumstance, the balance of the section is intended to apply
#    and the section as a whole is intended to apply in other circumstances. 
# 
#    It is not the purpose of this section to induce you to infringe any 
#    patents or other property right claims or to contest validity of any 
#    such claims; this section has the sole purpose of protecting the 
#    integrity of the free software distribution system, which is implemented 
#    by public license practices. Many people have made generous contributions
#    to the wide range of software distributed through that system in 
#    reliance on consistent application of that system; it is up to the 
#    author/donor to decide if he or she is willing to distribute software 
#    through any other system and a licensee cannot impose that choice. 
# 
#    This section is intended to make thoroughly clear what is believed to be 
#    a consequence of the rest of this License. 
# 
# 8. If the distribution and/or use of the Program is restricted in certain 
#    countries either by patents or by copyrighted interfaces, the original 
#    copyright holder who places the Program under this License may add an 
#    explicit geographical distribution limitation excluding those countries, 
#    so that distribution is permitted only in or among countries not thus 
#    excluded. In such case, this License incorporates the limitation as if 
#    written in the body of this License. 
# 
# 9. The Free Software Foundation may publish revised and/or new versions of 
#    the General Public License from time to time. Such new versions will be 
#    similar in spirit to the present version, but may differ in detail to 
#    address new problems or concerns. 
# 
#    Each version is given a distinguishing version number. If the Program 
#    specifies a version number of this License which applies to it and "any 
#    later version", you have the option of following the terms and 
#    conditions either of that version or of any later version published by 
#    the Free Software Foundation. If the Program does not specify a version 
#    number of this License, you may choose any version ever published by the 
#    Free Software Foundation. 
# 
# 10. If you wish to incorporate parts of the Program into other free programs
#     whose distribution conditions are different, write to the author to ask 
#     for permission. For software which is copyrighted by the Free Software 
#     Foundation, write to the Free Software Foundation; we sometimes make 
#     exceptions for this. Our decision will be guided by the two goals of 
#     preserving the free status of all derivatives of our free software and 
#     of promoting the sharing and reuse of software generally. 
# 
#    NO WARRANTY
# 
# 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 
#     FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 
#     OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 
#     PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER 
#     EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
#     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 
#     ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH 
#     YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL 
#     NECESSARY SERVICING, REPAIR OR CORRECTION. 
# 
# 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 
#     WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 
#     REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR 
#     DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL 
#     DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM 
#     (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED 
#     INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF 
#     THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR 
#     OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 
# 
# END OF TERMS AND CONDITIONS
# 
# How to Apply These Terms to Your New Programs
# 
# If you develop a new program, and you want it to be of the greatest 
# possible use to the public, the best way to achieve this is to make it free 
# software which everyone can redistribute and change under these terms. 
# 
# To do so, attach the following notices to the program. It is safest to 
# attach them to the start of each source file to most effectively convey the
# exclusion of warranty; and each file should have at least the "copyright" 
# line and a pointer to where the full notice is found. 
# 
# one line to give the program's name and an idea of what it does.
# Copyright (C) yyyy  name of author
# 
# This program is free software; you can redistribute it and/or modify it 
# under the terms of the GNU General Public License as published by the Free 
# Software Foundation; either version 2 of the License, or (at your option) 
# any later version.
# 
# This program is distributed in the hope that it will be useful, but WITHOUT 
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
# more details.
# 
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 
# Temple Place - Suite 330, Boston, MA  02111-1307, USA.
# 
# Also add information on how to contact you by electronic and paper mail. 
# 
# If the program is interactive, make it output a short notice like this when 
# it starts in an interactive mode: 
# 
# Gnomovision version 69, Copyright (C) year name of author Gnomovision comes 
# with ABSOLUTELY NO WARRANTY; for details type 'show w'.  This is free 
# software, and you are welcome to redistribute it under certain conditions; 
# type 'show c' for details.
# 
# The hypothetical commands 'show w' and 'show c' should show the appropriate 
# parts of the General Public License. Of course, the commands you use may be 
# called something other than 'show w' and 'show c'; they could even be 
# mouse-clicks or menu items--whatever suits your program. 
# 
# You should also get your employer (if you work as a programmer) or your 
# school, if any, to sign a "copyright disclaimer" for the program, if 
# necessary. Here is a sample; alter the names: 
# 
# Yoyodyne, Inc., hereby disclaims all copyright interest in the program 
# 'Gnomovision' (which makes passes at compilers) written by James Hacker.
# 
# signature of Ty Coon, 1 April 1989
# Ty Coon, President of Vice
# 
# This General Public License does not permit incorporating your program into 
# proprietary programs. If your program is a subroutine library, you may 
# consider it more useful to permit linking proprietary applications with the 
# library. If this is what you want to do, use the GNU Library General Public 
# License instead of this License.
################################################################################

use strict;

my $APP = "/usr/sbin/ianscfg";
my $IANS_CONF = "/etc/ians/ians.conf";

my @MODES = ("AFT", "SFT", "ALB", "SLA", "802.3ad", "NONE");
my @PRIORITIES = ("none", "primary", "secondary");
my @VLAN_MODES = ("none", "static", "GVRP");

#
# add_opt opts subs name sub - add a menu option
#
# $opts: reference to an array of menu option names
# $subs: reference to an array of sub-routines
# $name: option name
# $sub: option sub-routine
#
sub add_opt
{
    my $opts = shift;
    my $subs = shift;

    push(@{$opts}, shift);
    push(@{$subs}, shift);
}

sub options
{
    my($def, $others) = @_;
    my $disp_def = $def;
    my $disp_others =  $others;

    $disp_others =~ s/(.)/$1\//g;
    $disp_def =~ tr/[a-z]/[A-Z]/;
    chop ($disp_others);

    $_ = "";
    while (! /^[$def$others]/) {
        print "([$disp_def]/$disp_others): ";
        $_ = <STDIN>;
        chomp;
        tr/[A-Z]/[a-z]/;
        s/^\s*//;
        $_ = $def unless ($_);
    }
    s/^(.).*/$1/;
    return $_;
}

#
# find_adapters - find adapters that are available as members (i.e. not busy)
#
sub find_adapters
{
    my @adapters = `ifconfig -a | egrep "^eth" | awk '{print \$1}'`;
    chomp @adapters;

    my @members = `$APP -s | egrep "\\bMember\\b" | awk '{print \$2}'`;
    chomp @members;

    foreach (@members) {
        for (my $i = 0; $i <= $#adapters; $i++) {
            if ($_ eq $adapters[$i]) {
                splice(@adapters, $i, 1);
            }
        }
    }

    return @adapters;
}

#
# select_from_list array case [def] - select a value from an array
#
# $array: a reference to the array to select from
# $case: is the array case sensitive
# $def: Optional default value
#
# Returns the selected value, or the default if the user chose nothing and the
# $def argument was specified.
#
sub select_from_list
{
    my $list = shift;
    my $case = shift;
    my $def = "";
    my $isdef = 0;
    my $val = "";

    if (@_) {
        $def = shift;
        $isdef = 1;
    }

    while (!$val) {
        print "One of [@{$list}]";
        if ($def) {
            print " (default - $def)";
        }
        print ": ";

        $val = <STDIN>;
        chomp $val;
        if (!$val) {
            if ($isdef) {
                $val = $def;
                last;
            }

            next;
        }
        my @foo;

        if ($case) {
            @foo = grep(/^$val\b/, @{$list});
        } else {
            @foo = grep(/^$val\b/i, @{$list});
        }
        $val = $foo[0];
    }

    return $val;
}

#
# select_team - select a team and return it
#
sub select_team
{
    my @teams = `$APP -s | egrep "^Mux" | awk '{print \$2}'`;
    chomp @teams;

    if (!@teams) {
        print "No teams available\n";
        return "";
    }

    print "\nSelect team:\n";
    return select_from_list(\@teams, 1);
}

#
# get_team_entities team name - retreive entities of a team
#
# $team: the team to work with
# $name: entity's name in status block
#
# Returns a list of entity names for the specified team.
# Entity names can be anything in the team's status block.
#
sub get_team_entities
{
    my $team = shift;
    my $name = shift;
    my @status;
    my @entities;

    get_team_status($team, \@status);

    map {
        if (s/^\s*$name\s*(\w+)\b/$1/) {
            chomp;
            push(@entities, $_);
        }
    } @status;

    return @entities;
}

#
# get_team_mode - select a teaming mode
#
# Prompt the user for a teaming mode, including RLB.
# Return the relevant config string of the form: "-M $mode"
#
sub get_team_mode
{
    my $team_mode;
    my $RLB_mode = "";

    print "\nSelect teaming mode:\n";
    $team_mode = select_from_list(\@MODES, 0, "AFT");

    if ($team_mode eq "ALB") {
        print "Do you want RLB to be enabled? ";
        my $r_opt = options("y", "n");
        if ($r_opt ne "n") {
            $RLB_mode = "-R enable";
        } else {
            $RLB_mode = "-R disable";
        }
    }

    return "-M $team_mode $RLB_mode";
}

#
#
# get_vlan_id - prompt the user vor a vlan id
#
# Return the relevant config string of the form: "-i $vlan_id"
#
sub get_vlan_id
{
    my $vlan_id = "";

    while (!$vlan_id) {
        print "Enter VLAN id: ";
        $vlan_id = <STDIN>;
        chomp $vlan_id;

        if ($vlan_id !~ /^[0-9]+$/) {
            redo;
        }
    }

    return "-i $vlan_id";
}

#
# get_team_status team [output] - retrieve the status of the specified team
#
# $team: the team to query
# $output: Optional. A reference to an array to write to.
#
# If the $output argument is used put in it the relevant status, otherwise
# write it to STDOUT.
#
sub get_team_status
{
    my $team = shift;

    my @status = `$APP -s`;
    my $print = 0;
    my $team_status = "";

    if (@_) {
        $team_status = shift;
    }

    foreach (@status) {
        if (/^Mux/) {
            if (/\b$team\b/) {
                $print = 1;

            } else {
                $print = 0;
            }
        }

        if ($print) {
            if ($team_status) {
                push(@{$team_status}, $_);

            } else {
                print;
            }
        }
    }
}

#
# add_member team [must] - add a member to the specified team
#
# $team: the team to work with
# $must: Optional. Must we *try* to add a member (default: true)
#
sub add_member
{
    my $team = shift;
    my $must = 1;
    my $member;
    my $priority;
    my @adapters = find_adapters();

    if (@_) {
        $must = shift;
    }

    if (!@adapters) {
        if ($must) {
            print "No adapters are available as team members\n";
        }

        return "";
    }

    do {
        print "\nEnter member name, <Enter> to end:\n";

        $member = select_from_list(\@adapters, 1, "");
        if (!$member) {
            return $member;
        }

        print "\nSelect member priority:\n";
        $priority = select_from_list(\@PRIORITIES, 0, "none");

    } while (system("$APP -a -t$team -m $member -p $priority"));

    return $member;
}

#
# add_members team - add members to the specified team
#
# $team: the team to work with
#
# Returns the number of members added
#
sub add_members
{
    my $team = shift;
    my $team_members = 0;
    my $member = "";
    my $must = 1;

    do {
        $member = add_member($team, $must);

        $must = 0;
        $team_members++;
    } while ($member);

    $team_members--;
    return $team_members;
}

#
# add_one_vadapter team vlan_mode must - add a member to the specified team
#
# $team: the team to work with
# $vlan_mode: are VLANs enabled in the team
# $must: Optional. Must we add the vadapter (default: true)
#
sub add_one_vadapter
{
    my $team = shift;
    my $vlan_mode = shift;
    my $must = 1;
    my $vlan_id = "";
    my $vadapter;

    if (@_) {
        $must = shift;
    }

    # We need double {{ }} here for the 'redo'
    do {{
        print "\nEnter virtual adapter name";
        if (!$must) {
            print ", <Enter> to end";
        }
        print ": ";

        $vadapter = <STDIN>;
        chomp $vadapter;
        if (!$vadapter) {
            if ($must) {
                redo;
            }

            return $vadapter;
        }

        if ($vlan_mode) {
            $vlan_id = get_vlan_id();
        }

        # watch out here. $vadapter might end with a backslash
    }} while (system("$APP -a -t$team $vlan_id -v $vadapter"));

    return $vadapter;
}

#
# add_vadapter team - add a vadapter to the specified team
#
# $team: the team to work with
#
sub add_vadapter
{
    my $team = shift;
    my @vlan_modes;
    my $vlan_mode = 0;
    my $team_vadapters = get_team_entities($team, "Vadapter");

    @vlan_modes = get_team_entities($team, "VLAN State");
    if (@vlan_modes && ($vlan_modes[0] =~ /enabled/i)) {
        $vlan_mode = 1;
    }

    if ($team_vadapters && !$vlan_mode) {
        print "Can't add more than one virtual adapter in a non-VLAN team\n";
        return;
    }

    add_one_vadapter($team, $vlan_mode);
}

#
# add_vadapters team vlan_mode - add vadapters to the specified team
#
# $team: the team to work with
# $vlan_mode: are VLANs enabled in the team
#
sub add_vadapters
{
    my $team = shift;
    my $vlan_mode = shift;

    my $team_vadapters = get_team_entities($team, "Vadapter");

    while (!$team_vadapters || $vlan_mode) {
        my $must = 1;

        if ($team_vadapters && $vlan_mode) {
            $must = 0;
        }

        my $vadapter = add_one_vadapter($team, $vlan_mode, $must);
        if (!$vadapter) {
            last;
        }

        $team_vadapters++;
    }
}

#
# del_member team - delete a member from the specified team
#
# $team: the team to work with
#
sub del_member
{
    my $team = shift;
    my $member;
    my @members;

    @members = get_team_entities($team, "Member");

    if (!@members) {
        print "Team $team has no members\n";
        return;
    }

    print "Select member to delete:\n";
    $member = select_from_list(\@members, 1);

    system("$APP -d -m $member");
}

#
# del_vadapter team - delete a vadapter from the specified team
#
# $team: the team to work with
#
sub del_vadapter
{
    my $team = shift;
    my $vadapter;
    my @vadapters;

    @vadapters = get_team_entities($team, "Vadapter");

    if (!@vadapters) {
        print "Team $team has no vadapters\n";
        return;
    }

    print "Select vadapter to delete:\n";
    $vadapter = select_from_list(\@vadapters, 1);

    system("$APP -d -v $vadapter");
}

#
# add_team - add a team
#
sub add_team
{
    my $team;
    my $vlan_mode = "";
    my $team_mode = "";
    my $v_opt;
    my @adapters = find_adapters();

    if (!@adapters) {
        print "No adapters are available as team members\n";
        return;
    }

    print "\nEnter team name: ";
    $team = <STDIN>;
    chomp $team;

    if (!$team) {
        print "Team creation canceled\n";
        return;
    }

    $team_mode = get_team_mode();

    print "\nSelect VLAN mode:\n";
    $v_opt = select_from_list(\@VLAN_MODES, 0, "none");

    if ($v_opt ne "none") {
        $vlan_mode = "-V";
    }

    if (system("$APP -a -t$team $team_mode $vlan_mode")) {
        print "Team creation canceled\n";
        return;
    }

    if ($v_opt eq "GVRP") {
        if (system("$APP -C -t$team -G enable")) {
            system("$APP -d -t$team -r");
            print "Team creation canceled\n";
            return;
        }
    }

    if (! add_members($team)) {
        system("$APP -d -t$team -r");
        print "No members were added to team '$team'. Team creation canceled\n";
        return;
    }

    add_vadapters($team, $vlan_mode);

    if (system("$APP -c $team")) {
        system("$APP -d -t$team -r");
        print "Team creation canceled\n";
        return;
    }

    print "Team $team activated\n";
}

#
# del_team - delete a team
#
sub del_team
{
    my $team = select_team();
    if (!$team) {
        return;
    }

    system("$APP -d -t $team -r");
}

#
# view_team - view a team's status block
#
sub view_team
{
    my $team = select_team();
    if (!$team) {
        return;
    }

    get_team_status($team);
}

#
# conf_team - configure a team
#
sub conf_team
{
    my $opt;

    my $team = select_team();
    if (!$team) {
        return;
    }

    my @opts = ("");
    my @subs = (sub {});

    add_opt(\@opts, \@subs, "Add member", \&add_member);
    add_opt(\@opts, \@subs, "Del member", \&del_member);
    add_opt(\@opts, \@subs, "Add vadapter", \&add_vadapter);
    add_opt(\@opts, \@subs, "Del vadapter", \&del_vadapter);

    for (my $i = 1; $i <= $#opts; $i++) {
        print "$i. $opts[$i]\n";
    }
    print "\nSelect configuration option for team $team: ";

    $opt = <STDIN>;
    chomp $opt;

    # $opt must be a number
    if ($opt !~ /^[0-9]+$/) {
        next;
    }

    if (($opt < 1) || ($opt > $#opts)) {
        next;
    }

    $subs[$opt]->($team);
    print "\n";
}

#
# save_topology [onboot] - save the current topology to a file
#
# $onboot: Optional. If set, save also for boot (default: false)
#
sub save_topology
{
    my $file;
    my $onboot = "";

    print "Enter file name to save to (default - $IANS_CONF): ";
    $file = <STDIN>;
    chomp $file;
    if (!$file) {
        $file = $IANS_CONF;
    }

    print "Do you want to save the topology across boots? ";
    my $b_opt = options("y", "n");
    if ($b_opt ne "n") {
        $onboot = "-b";
    }

    system("$APP -w $onboot -f $file");
}

sub main_menu
{
    my $opt = "";

    my @opts = ("");
    my @subs = (sub {});

    add_opt(\@opts, \@subs, "Add team", \&add_team);
    add_opt(\@opts, \@subs, "Del team", \&del_team);
    add_opt(\@opts, \@subs, "View team", \&view_team);
    add_opt(\@opts, \@subs, "Configure team", \&conf_team);
    add_opt(\@opts, \@subs, "Save topology", \&save_topology);
    add_opt(\@opts, \@subs, "Exit", sub {exit 0;});

    while (1) {
        for (my $i = 1; $i <= $#opts; $i++) {
            print "$i. $opts[$i]\n";
        }
        print "\nSelect menu option: ";

        $opt = <STDIN>;
        chomp $opt;

        # $opt must be a number
        if ($opt !~ /^[0-9]+$/) {
            next;
        }

        if (($opt < 1) || ($opt > $#opts)) {
            next;
        }

        $subs[$opt]->();
        print "\n";
    }
}

############# MAIN #############

if (!(-x "$APP")) {
    die "Cannot find config application. Run `make install` first\n";
}

if (! `egrep "^ians\\b" /proc/modules`) {
    print "Loading ians module...\n";
    if (system("insmod ians")) {
        die print "Failed to load ians module\n";
    }
}

main_menu();

