#!/usr/bin/env python
# ***************************************************************************
# Copyright 2015-2017 VMware, Inc.  All rights reserved. VMware Confidential.
# ***************************************************************************
# $Id$
# $DateTime$
# $Change$
# $Author$
# ***************************************************************************
import os
import grp
import pwd
import shutil
import sys


_FILESTORE = "/var/vmware/nsx/file-store"
_FILESTORE_FILE_PARTS = 6


ERROR_MOVE_FAILED = 1
ERROR_FILE_EXISTS = 2
ERROR_INVALID_FILE = 3
ERROR_INVALID_SRCDIR = 4


_SRCDIR_INFO = {
    "nsxtmp": ("/var/vmware/nsx/tmp", 6),
    "tmp": ("/tmp", 3)}


if __name__ == "__main__":
    """USAGE: move_tmpfile_to_filestore <srcdir> <src_filename> <dst_filename>
              [<dst_file_mode> [<dst_file_group_name>]]

    This script moves a file from under the <srcdir> directory with filename
    as <src_filename> to the file-store directory (/var/vmware/nsx/file-store)
    with filename as <dst_filename>. The caller must have sufficient privileges
    to read <filename> and write to the file-store directory. <srcdir> must be
    one of the following keywords:
    - nsxtmp (which maps to /var/vmware/nsx/tmp)
    - tmp (which maps to /tmp)

    After the file is moved successfully, this script also attempts to
    change ownership of the file to www-data and mode to 0644. But if
    an error is encountered, it is ignored.

    Returns:
        0: if move operation is successful.
        ERROR_MOVE_FAILED:    if move operation is unsuccessful.
        ERROR_FILE_EXISTS:    if file already exists in file-store directory.
        ERROR_INVALID_FILE:   if <filename> is not specified or is invalid.
        ERROR_INVALID_SRCDIR: if <srcdir> is not one of the allowed keywords.
    """
    # Check srcdir, filename specified, and srcdir valid
    argv_len = len(sys.argv)
    if argv_len < 2 or sys.argv[1] not in _SRCDIR_INFO:
        sys.exit(ERROR_INVALID_SRCDIR)
    elif argv_len < 4:
        sys.exit(ERROR_INVALID_FILE)
    # Check tmp file exists and is under srcdir
    src_dir, parts = _SRCDIR_INFO[sys.argv[1]]
    src_filename = sys.argv[2]
    dst_filename = sys.argv[3]
    src = os.path.normpath(os.path.join(src_dir, src_filename))
    if (not src.startswith(src_dir + "/") or
            len(src.split("/")) != parts or
            not os.path.exists(src)):
        sys.exit(ERROR_INVALID_FILE)
    # Check destination file in file-store
    dst = os.path.normpath(os.path.join(_FILESTORE, dst_filename))
    if (not dst.startswith(_FILESTORE + "/") or
            len(dst.split("/")) != _FILESTORE_FILE_PARTS):
        sys.exit(ERROR_INVALID_FILE)
    # Check destination file doesn't already exist
    if os.path.exists(dst):
        sys.exit(ERROR_FILE_EXISTS)
    try:
        shutil.move(src, dst)
    except:
        sys.exit(ERROR_MOVE_FAILED)
    try:
        # Configure destination file ownership,
        # customize gid if <dst_file_group_name> specified
        user_data = pwd.getpwnam("www-data")
        if argv_len > 5:
            gid = grp.getgrnam(sys.argv[5]).gr_gid
        else:
            gid = user_data.pw_gid
        os.chown(dst, user_data.pw_uid, gid)
        # Configure destination file mode,
        # customize per <dst_file_mode> if specified
        if argv_len > 4:
            os.chmod(dst, int(sys.argv[4], 8))
        else:
            os.chmod(dst, 0o644)
    except:
        pass
