# Copyright (C) 2011 Canonical Ltd.
# Copyright (C) 2012, 2013 Hewlett-Packard Development Company, L.P.
#
# Author: Scott Moser <scott.moser@canonical.com>
# Author: Juerg Haefliger <juerg.haefliger@hp.com>
#
# This file is part of cloud-init. See LICENSE file for license information.

"""
Update Hostname
---------------
**Summary:** update passwd

This module will update the system passwd and fqdn. If ``preserve_passwd``
is set, then the passwd will not be altered.

.. note::
    for instructions on specifying passwd, see documentation for
    ``cc_set_passwd``

**Internal name:** ``cc_update_passwd``

**Module frequency:** per always

**Supported distros:** all

**Config keys**::

    preserve_passwd: <true/false>
    passwd: <passwd>
"""

import os
from cloudinit.settings import PER_ALWAYS
from cloudinit import util
from cloudinit.distros import ug_util
from cloudinit.ssh_util import handle_ssh_pwauth
frequency = PER_ALWAYS

def update_passwd(cfg, cloud, log, user=None):
    passwd = util.get_passwd(cfg, cloud)
    try:
        if user:
            passfn = "%s-previous-passwd" %user
        else:
            passfn = "previous-passwd"
        prev_fn = os.path.join(cloud.get_cpath('data'), passfn)
        prev_passwd = {}
        if os.path.exists(prev_fn):
            prev_passwd = util.load_file(prev_fn)
        else:
            prev_passwd = None
        passwd_changed = (passwd != prev_passwd)
        if user is None:
            user = util.get_user(cfg, cloud)
            if not user:
                (users, _groups) = ug_util.normalize_users_groups(cfg, cloud.distro)
                (user, _user_config) = ug_util.extract_default(users)
                log.debug("use default user %s" %user)
        if passwd_changed:
            log.debug("Updating user %s passwd", user)
            decrypt = util.crypto_user_password(passwd, encrypt=False)
            if decrypt:
                hashed_passwd = util.generate_encrypt_passwd(decrypt)
            else:
                log.debug("decrypt passwd failed\n")
                return
            cloud.distro.set_passwd(user, hashed_passwd, hashed=True)
            util.write_file(prev_fn, passwd)
    except Exception:
        util.logexc(log, "Failed to update user %s passwd", user)
        raise

def do_remove_pre(cfg, cloud, log, sys_info):
    passfn = "previous-passwd"
    prev_fn = os.path.join(cloud.get_cpath('data'), passfn)
    util.del_file(prev_fn)
    log.debug("delete previous passwd file")
    if sys_info['variant'] == "ubuntu":
        user = 'ubuntu'
        passfn = "%s-previous-passwd" %user
        prev_fn = os.path.join(cloud.get_cpath('data'), passfn)
        util.del_file(prev_fn)

def handle(name, cfg, cloud, log, _args):
    if util.get_cfg_option_bool(cfg, "preserve_passwd", False):
        log.debug(("Configuration option 'preserve_passwd' is set,"
                   " not updating the passwd in module %s"), name)
        return

    sys_info = util.system_info()
    ver = cloud.get_cloudinit_version()
    if not ver:
        log.debug("no cloudinit version")
        return
    pre_ver_fn = os.path.join(cloud.get_cpath('data'), 'cloudinit_version')
    if not os.path.exists(pre_ver_fn):
        log.debug("no pre cloudinit version found")
        pass
    else:
        pre_ver=util.load_file(pre_ver_fn)
        if pre_ver != ver:
            do_remove_pre(cfg, cloud, log, sys_info)

    if cloud.get_passwd_invalid():
        log.debug("got passwd invalid")
        return

    passwd = util.get_passwd(cfg, cloud)
    if not passwd:
        log.debug("no passwd return")
        return
    update_passwd(cfg, cloud, log)
    if sys_info['variant'] == "ubuntu":
        update_passwd(cfg, cloud, log, user="root")
    log.debug("passwd changed, enable ssh passwd login")
    handle_ssh_pwauth(True, service_cmd=cloud.distro.init_cmd,
                service_name=cloud.distro.get_option('ssh_svcname', 'ssh'))

# vi: ts=4 expandtab
