#!/usr/bin/env python
# Copyright (C) 2012-2013  Peter Hatina <phatina@redhat.com>
#
# 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, see <http://www.gnu.org/licenses/>.

import os
import sys

from lmi.lmi_options import LmiBasicOptions
from lmi.lmi_address import LmiIpv4Addr, LmiHostGenerator
from lmi.lmi_client_user import LmiUserClient

class LmiUserOptions(LmiBasicOptions):
    def __init__(self):
        script_name = os.path.basename(__file__)
        super(self.__class__, self).__init__(
            "Available actions:\n"
            "  list-users, list-groups, group-members\n"
            "  useradd\n\n"
            "Group-members:\n"
            "  " + script_name + " [options] group-members group_name\n\n"
            "Useradd:\n"
            "  " + script_name + " [options] useradd new_username\n\n")
        self._parser.set_usage("Usage: %prog [options] action")
        self._parser.add_option("-s", "--shell",
            action = "store",
            dest = "shell",
            help = "login shell of the new account")
        self._parser.add_option("-r", "--system-account",
            action = "store_true",
            dest = "system_account",
            help = "create a system account")
        self._parser.add_option("-m", "--create-home",
            action = "store_true",
            dest = "create_home",
            help = "create the user's home directory")
        self._parser.add_option("-M", "--no-create-home",
            action = "store_false",
            dest = "create_home",
            help = "do not create the user's home directory")
        self._parser.add_option("-N", "--no-user-group",
            action = "store_false",
            dest = "create_group",
            help = "do not create a group with the same name as the user")
        self._parser.add_option("-g", "--gid",
            action = "store",
            dest = "gid",
            help = "name or ID of the primary group of the new account")
        self._parser.add_option("", "--gecos",
            action = "store",
            dest = "gecos",
            help = "GECOS information for new user")
        self._parser.add_option("-d", "--home-dir",
            action = "store",
            dest = "home_dir",
            help = "home directory of the new account")
        self._parser.add_option("-n", "--new-password",
            action = "store",
            dest = "new_password",
            help = "password for the new account")
        self._parser.add_option("-i", "--uid",
            action = "store",
            dest = "uid",
            help = "user ID of the new account")

    @property
    def good(self):
        if not len(self._pos_options):
            return False
        elif self._pos_options[0] == "group-members":
            return len(self._pos_options) == 2
        elif self._pos_options[0] == "useradd":
            return len(self._pos_options) == 2
        return len(self._pos_options) == 1

    @property
    def action(self):
        return self._pos_options[0] if self.good and self._pos_options[0] else ""

    @property
    def group(self):
        return self._pos_options[1] if self.good and self._pos_options[1] else ""

    @property
    def new_username(self):
        return self._pos_options[1] if self.good and self._pos_options[1] else ""

    @property
    def shell(self):
        return self._options.shell if self.good and self._options.shell else ""

    @property
    def system_account(self):
        return self._options.system_account if self.good and self._options.system_account else False

    @property
    def create_home(self):
        return self._options.create_home in (None, True) if self.good else False

    @property
    def create_group(self):
        return self._options.create_group in (None, True) if self.good else True

    @property
    def gid(self):
        return self._options.gid if self.good and self._options.gid else ""

    @property
    def gecos(self):
        return self._options.gecos if self.good and self._options.gecos else ""

    @property
    def home_dir(self):
        return self._options.home_dir if self.good and self._options.home_dir else ""

    @property
    def new_password(self):
        return self._options.new_password if self.good and self._options.new_password else ""

    @property
    def uid(self):
        return self._options.uid if self.good and self._options.uid else ""

if __name__ == "__main__":
    options = LmiUserOptions()
    options.parse(sys.argv)
    if not options.good:
        options.print_wrong_usage()
        sys.exit(1)

    client_failed = False
    client_hostnames = LmiHostGenerator.enumerate(options.hostname)
    client_action = options.action.lower()
    for client_hostname in client_hostnames:
        if not client_hostname:
            continue
        client = LmiUserClient(client_hostname.name, options.username, options.password)
        actions = {
            "list-users" : client.list_users,
            "list-groups" : client.list_groups
        }

        if client_action == "group-members":
            (rval, _, errorstr) = client.list_group_members(options.group)
        elif client_action == "useradd":
            (rval, _, errorstr) = client.user_add(
                options.new_username,
                shell = options.shell,
                systemAccount = options.system_account,
                createHome = options.create_home,
                createGroup = options.create_group,
                homeDir = options.home_dir,
                uid = options.uid,
                gid = options.gid,
                password = options.new_password,
                gecos = options.gecos)
        elif client_action in actions:
            (rval, _, errorstr) = actions[client_action]()
        else:
            sys.stderr.write("No such action to perform!\n")
            sys.exit(1)

        if rval:
            sys.stdout.write("%s: %s\n" % (client_hostname.name, errorstr if errorstr else "ok"))
        else:
            sys.stderr.write("%s: %s\n" % (client_hostname.name, errorstr))
            client_failed = True

    sys.exit(client_failed)
