#!/usr/bin/python3

# Copyright (C) Citrix Systems Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation; version 2.1 only.
#
# 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

import os
import sys
import re
import json
import subprocess

from sm.core import util
from sm.core import xs_errors
from sm.core import mpath_cli
from sm import mpathcount

if __name__ == '__main__':
    try:
        session = util.get_localAPI_session()
    except:
        print("Unable to open local XAPI session")
        sys.exit(-1)

    localhost = session.xenapi.host.get_by_uuid(mpathcount.get_localhost_uuid())
    mpathcount.check_xapi_is_enabled()
    # Check whether multipathing is enabled (either for root dev or SRs)
    try:
        if mpathcount.get_root_dev_major() != mpathcount.get_dm_major():
            hconf = session.xenapi.host.get_other_config(localhost)
            assert(hconf['multipathing'] == 'true')
            mpathcount.mpath_enabled = True
    except:
        mpathcount.mpath_enabled = False

    # Check root disk if multipathed
    try:
        def _remove(key):
            session.xenapi.host.remove_from_other_config(localhost, key)


        def _add(key, val):
            session.xenapi.host.add_to_other_config(localhost, key, val)
        config = session.xenapi.host.get_other_config(localhost)
        maps = mpath_cli.list_maps()
        mpathcount.check_root_disk(config, maps, _remove, _add)

    except:
        util.SMlog("MPATH: Failure updating Host.other-config:mpath-boot db")
        mpathcount.mpc_exit(session, -1)

    try:
        pbds = session.xenapi.PBD.get_all_records_where(f'field "host" = "{localhost}"')
    except:
        mpathcount.mpc_exit(session, -1)

    try:
        mpath_status = {}
        for pbd in pbds:
            def remove(key):
                session.xenapi.PBD.remove_from_other_config(pbd, key)


            def add(key, val):
                session.xenapi.PBD.add_to_other_config(pbd, key, val)
            record = pbds[pbd]
            config = record['other_config']
            SR = record['SR']
            srtype = session.xenapi.SR.get_type(SR)
            if srtype in mpathcount.supported:
                devconfig = record["device_config"]
                sm_config = session.xenapi.SR.get_sm_config(SR)
                mpathcount.check_devconfig(devconfig, sm_config, config, remove, add, mpath_status)
        mpath_status = mpath_status if mpathcount.mpath_enabled else {}
        util.atomicFileWrite(mpathcount.MPATH_FILE_NAME, mpathcount.MPATHS_DIR, json.dumps(mpath_status))
        os.chmod(mpathcount.MPATH_FILE_NAME, 0o0644)
    except:
        util.SMlog(f'MPATH: Failure updating db. {sys.exc_info()}')
        mpathcount.mpc_exit(session, -1)

    util.SMlog("MPATH: Update done")

    mpathcount.mpc_exit(session, 0)
