#!/usr/bin/env python
#
# Copyright 2006-2016 Hunan Kylin, Inc.  All Rights Reserved.
# 
# NOTICE: ALL INFORMATION CONTAINED HEREIN IS, AND REMAINS THE PROPERTY OF
# HUNAN KYLIN, INC. AND ITS SUPPLIERS, IF ANY. THE INTELLECTUAL AND
# TECHNICAL CONCEPTS CONTAINED HEREIN ARE PROPRIETARY TO HUNAN KYLIN, INC.
# AND ITS SUPPLIERS AND MAY BE COVERED BY U.S. AND FOREIGN PATENTS, PATENTS IN
# PROCESS, AND ARE PROTECTED BY TRADE SECRET OR COPYRIGHT LAW. DISSEMINATION
# OF THIS INFORMATION OR REPRODUCTION OF THIS MATERIAL IS STRICTLY FORBIDDEN
# UNLESS PRIOR WRITTEN PERMISSION IS OBTAINED FROM HUNAN KYLIN, INC.
#
# -*- coding: utf-8 -*-

#
# Offer the Main KYLINOS configuration and management menu
#

import sys
import pdb 
import json
from os.path import join, dirname, abspath
import fcntl 

# Find our python libraries
sys.path.append(join(dirname(dirname(abspath(sys.argv[0]))), 'etc/python'))

import KsvdApp
from KsvdUtil import xl_
import KsvdUtil
import KsvdNetConfigApi

class KsvdLocalCliApp(KsvdApp.KsvdApp):
	#
	# Initialize the application framework
	#
	def __init__(self, appArgs):
		KsvdApp.KsvdApp.__init__(
			self,
			appArgs,
			add_help_option = False)

	#
	# Options other than the standard ones (-v, -V, -i, -l)
	#
	def AddOptions(self):
		self.parser.add_option(
			'-a', '--action',
			action='store',
			default='default_action',
			help=xl_('point the act, such as set-data-storage.'))
		self.parser.add_option(
			'-J', '--jsonvar',
			action = 'store',
			help = xl_('Get args in json format'),
			metavar='JSON')
		self.parser.add_option(
			'-h', '--help',
			action = 'store_true',
			default=False,
			help = xl_('Get help info'))

	#
	# Execute the ksvd-local-cli interface
	#
	def InvokeApp(self):
		if len(self.appArgs) == 1:
			self.options.action = 'list-node'
		# Analyze the options
		if self.options.help:
			self.Help()
			return 0
		rc = 0
		rJson = {}

		# lock the write apis when updating KsvdNetConfig.pkl, avoiding conflict between apis .
		# set-data-storage/del-data-storage api may waste a lot of time, so put lock in it.
		writeAPI = ['add-node', 'set-role', 'set-manage-storage','set-docker-ip',
			'del-docker-ip','set-network','set-all-data-storage', 'set-branch']
		pklLockFile = "/var/run/KsvdNetConfig-pkl.lock"
		if not KsvdUtil.FileExists(pklLockFile):
			rc = KsvdUtil.TouchFile(pklLockFile)
			if rc != 0:
				rJson = {"stdin": None, "stdout": None, "stderr": "Failed to touch KsvdNetConfig-pkl.lock file ."}
				KsvdUtil.Log(json.dumps(rJson))
				return rc
		if self.options.action in writeAPI:
			try:
				pklFd = open('/var/run/KsvdNetConfig-pkl.lock', 'rb')
			except:
				rJson = {"stdin": None, "stdout": None, "stderr": "Failed to open KsvdNetConfig-pkl.lock file ."}
				KsvdUtil.Log(json.dumps(rJson))
				return -1
			fcntl.flock(pklFd.fileno(), fcntl.LOCK_EX)

		inOption, inArgs = self.parser.parse_args()
		if self.options.action == 'list-node':
			rc, rJson = KsvdNetConfigApi.ListNode()
		elif self.options.action == 'add-node':
			dict=json.loads(self.options.jsonvar)
			rc, rJson = KsvdNetConfigApi.AddNode(dict)
		elif self.options.action == 'set-role':
			dict=json.loads(self.options.jsonvar)
			rc, rJson = KsvdNetConfigApi.SetRole(dict)
		elif self.options.action == 'list-storage':
			rc, rJson = KsvdNetConfigApi.ListStorage()
		elif self.options.action == 'list-manage-storage':
			rc, rJson = KsvdNetConfigApi.ListManageStorage()
		elif self.options.action == 'set-manage-storage':
			dict=json.loads(self.options.jsonvar)
			rc, rJson = KsvdNetConfigApi.SetManageStorage(dict)
		elif self.options.action == 'list-data-storage':
			rc, rJson = KsvdNetConfigApi.ListDataStorage()
		elif self.options.action == 'get-docker-ip':
			rc, rJson = KsvdNetConfigApi.GetDockerIP()
		elif self.options.action == 'set-docker-ip':
			dict=json.loads(self.options.jsonvar)
			rc, rJson = KsvdNetConfigApi.SetDockerIP(dict)
		elif self.options.action == 'del-docker-ip':
			rc, rJson = KsvdNetConfigApi.DelDockerIP()
		elif self.options.action == 'get-network':
			rc, rJson = KsvdNetConfigApi.GetNetwork()
		elif self.options.action == 'set-network':
			dict=json.loads(self.options.jsonvar)
			rc, rJson = KsvdNetConfigApi.SetNetwork(dict)
		elif self.options.action == 'set-data-storage':
			dict=json.loads(self.options.jsonvar)
			rc, rJson = KsvdNetConfigApi.AddDataStorage(dict)
		elif self.options.action == 'del-data-storage':
			dict=json.loads(self.options.jsonvar)
			rc, rJson = KsvdNetConfigApi.DeleteDataStorage(dict)
		elif self.options.action == 'remount-data-storage':
			dict=json.loads(self.options.jsonvar)
			rc, rJson = KsvdNetConfigApi.RemountDataStorage(dict)
		elif self.options.action == 'update-gluster-fuse-ip':
			dict=json.loads(self.options.jsonvar)
			rc, rJson = KsvdNetConfigApi.UpdateGlusterFuseIP(dict)
		elif self.options.action == 'set-all-data-storage':
			dict=json.loads(self.options.jsonvar)
			rc, rJson = KsvdNetConfigApi.SetDataStorage(dict)
		elif self.options.action == 'list-branch':
			rc, rJson = KsvdNetConfigApi.ListBranch()
		elif self.options.action == 'set-branch':
			dict=json.loads(self.options.jsonvar)
			rc, rJson = KsvdNetConfigApi.SetBranch(dict)
		else:
			rJson = {"stdin": None, "stdout": None, "stderr": "Unkown action paramters: " + self.options.action + ", see more in: /usr/lib/ksvd/bin/ksvd-local-cli -h"}
			rc=-1

		# unlock this api when it updates KsvdNetConfig.pkl, avoiding conflict between apis.
		if self.options.action in writeAPI:
			fcntl.flock(pklFd.fileno(), fcntl.LOCK_UN)
			if not pklFd.closed:
				pklFd.close()

		KsvdUtil.Log(json.dumps(rJson))
		return rc

	#
	# print help info 
	#
	def Help(self):
		helpInfo = '''
This python script is used for local settings, called by web or the boot service.

Usage: ksvd-local-cli [options]
	/usr/lib/ksvd/bin/ksvd-local-cli -h
	/usr/lib/ksvd/bin/ksvd-local-cli --action="list-node"
	/usr/lib/ksvd/bin/ksvd-local-cli --action="list-node"|jq

jq: a json cmd tool.

Options:
  -a ACTION, --action=ACTION     Soint the act, such as set-data-storage
  -J JSON, --jsonvar=JSON        Get args in json format

  -h, --help                     Show this help message and exit
  -V, --version                  Show the version of this cmd

Output format:
	json string: used as interface, called by web or other cmd.
	general string: used directly,such as show version or help info.

Configuration file: 
	/var/lib/ksvd/KsvdNetConfig.pkl

Log file:
	/var/log/ksvd-network/ksvd-local-cli-log.txt

Example:
	If set action manually, backup /var/lib/ksvd/KsvdNetConfig.pkl first and read following text

[node]
 - desc: show all node info in KsvdNetConfig.pkl
./ksvd-local-cli --action="list-node"

 Add node: delete the KsvdNetConfig.pkl and create a new one, operate after KSVD service is stopped.
 -         manage storage: Local
./ksvd-local-cli --action="add-node" --jsonvar='{
  "role": {"serverRole": "CM_VDI"},
  "branch": {},
  "network": {
    "publicAddr": "192.168.200.111"
  },
  "storage": {
    "manageStorage": {"type": "Local"}
  }
}'

 -         manage storage: NFS 
./ksvd-local-cli --action="add-node" --jsonvar='{
  "role": {"serverRole": "CM_VDI"},
  "branch": {},
  "network": {
    "publicAddr": "192.168.200.111"
  },
  "storage": {
    "manageStorage": {
        "type": "NFS",
        "nfs_server": "node1",
        "nfs_mount_path": "/home/ksvd_data/nfs_xxx",
        "nfs_version": 4
    }
  }
}'

 -         manage storage: CIFS 
./ksvd-local-cli --action="add-node" --jsonvar='{
  "role": {"serverRole": "CM_VDI"},
  "branch": {},
  "network": {
    "publicAddr": "192.168.200.111"
  },
  "storage": {
    "manageStorage":{
      "type":"CIFS",
      "cifs_mount_path":"//192.168.200.112/MStorage",
      "cifs_username":"kylin",
      "cifs_password":"xxxxx",
      "cifs_domain_name":"",
      "cifs_version":"1.0"}
  }
}'

 -         manage storage: GlusterFS
./ksvd-local-cli --action="add-node" --jsonvar='{
  "role": {"serverRole": "CM_VDI"},
  "branch": {},
  "network": {
    "publicAddr": "192.168.200.111"
  },
  "storage": {
    "manageStorage": {
      "type": "GlusterFS",
      "gfs_node": "node1",
      "gfs_volume": "ksvd_vol",
      "gfs_option": "node2"
    }
  }
}'

 - add a branch node, if same_as_center=no, use storage_location
./ksvd-local-cli --action="add-node" --jsonvar='{
  "role": {"serverRole": "CM_VDI"},
  "branch": {
    "branchSyncInterval": 5,
    "branchCredentials": {
      "address": "192.168.200.111",
      "username": "aaa",
      "password": "aaa",
      "backup_time": "01:00",
      "same_as_center":"yes",
      "storage_location":"/home/kylin-data/branch"
    }},
  "network": {"publicAddr": "192.168.121.101"},
  "storage": {
    "manageStorage": {"type": "Local"}
  }
}'

[storage]
 - list-manage-storage/list-data-storage: show manage storage or data storage in KsvdNetConfig.pkl
./ksvd-local-cli --action="list-manage-storage"
./ksvd-local-cli --action="list-data-storage"

 - set-data-storage: add a data storage to KsvdNetConfig.pkl, try to mount 3 times
./ksvd-local-cli --action="set-data-storage" --jsonvar='{"ksvd_data_gfs": {"gfs_option": "node2", "gfs_node": "node1", "type": "GlusterFS", "gfs_volume": "ksvd_data_gfs"}}'

 - del-data-storage: remove a data storage to KsvdNetConfig.pkl, try to umount 3 times
./ksvd-local-cli --action="del-data-storage" --jsonvar='{"name": "gfs_data"}'

 - set-manage-storage: replace manage storage in KsvdNetConfig.pkl when KSVD service is stopped, systemctl stop KSVD
./ksvd-local-cli --action="set-manage-storage" --jsonvar='{"type": "GlusterFS", "gfs_option": "node2", "gfs_node": "node1", "gfs_volume": "ksvd_vol"}'

./ksvd-local-cli --action="get-docker-ip"
./ksvd-local-cli --action="set-docker-ip" --jsonvar='{"docker_ip": "192.168.100.200"}'
./ksvd-local-cli --action="del-docker-ip"

 - set-all-data-storage: replace data storage in KsvdNetConfig.pkl when KSVD service is stopped, systemctl stop KSVD
./ksvd-local-cli --action="set-all-data-storage" --jsonvar='{"ksvd_data": {"gfs_option": "node2", "gfs_node": "node1", "type": "GlusterFS", "gfs_volume": "ksvd_data"},"ksvd_data1": {"gfs_option": "node2", "gfs_node": "node1", "type": "GlusterFS", "gfs_volume": "ksvd_data1"}}'

 - remount-data-storage: used when changed storage ip
./ksvd-local-cli --action="remount-data-storage"  --jsonvar='{"name":["dotest1","dotest3"]}'

- update-gluster-fuse-ip: used when changed storage ip
./ksvd-local-cli --action="update-gluster-fuse-ip" --jsonvar='{"dotest1":[["10.60.6.161","100.60.6.161"],["10.60.6.162","100.60.6.162"]],"dotest3":[["10.60.6.161","100.60.6.161"],["10.60.6.162","100.60.6.162"]]}'

[role]
 - set-role: use set-role action to replace server role in KsvdNetConfig.pkl after stopping KSVD service, systemctl stop KSVD
./ksvd-local-cli --action="set-role" --jsonvar='{"role": {"serverRole": "VDI_Only"}}'

[network]
 - get-network: get network information
./ksvd-local-cli --action="get-network"

 - set-network: change one or more value in network, change what you want
./ksvd-local-cli --action="set-network" --jsonvar='{"publicAddr": "192.168.100.200"}'
./ksvd-local-cli --action="set-network" --jsonvar='{"publicAddr": "192.168.100.200","publicAddrForClient": "10.20.2.33","gatewayCMList": ["10.20.1.3"]}'

[branch]
 - list-branch: show branch info in KsvdNetConfig.pkl anytime
./ksvd-local-cli --action="list-branch"

 - set-branch: replace branch info in KsvdNetConfig.pkl when KSVD service is stopped, systemctl stop KSVD
./ksvd-local-cli --action="set-branch" --jsonvar='{"branchSyncInterval": 5,
 "branchCredentials": {
  "address": "192.168.200.111",
  "username": "aaa",
  "password": "aaa",
  "backup_time": "01:00",
  "same_as_center":"yes",
  "storage_location":"/home/kylin-data/branch"
}}'
'''
		print(helpInfo)

# Run this program, that's all.
KsvdLocalCliApp(appArgs = sys.argv).RunApp()

