Index: /branches/rel_apv_10_7/tools/update/ustacksystem.ks
===================================================================
--- /branches/rel_apv_10_7/tools/update/ustacksystem.ks	(revision 38947)
+++ /branches/rel_apv_10_7/tools/update/ustacksystem.ks	(working copy)
@@ -461,8 +461,10 @@
 echo "Environment=\"PGDATA=/ca/pgsql/\"" >> /etc/systemd/system/postgresql.service.d/override.conf
 
 
-# install azure-mgmt-compute azure-mgmt-network azure-identity azure-mgmt-resource psutil 
+# install azure-mgmt-compute azure-mgmt-network azure-identity azure-mgmt-resource psutil
 LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/ca/lib/ pip3 install -i http://192.168.100.11/pypirepo/py3/simple azure-mgmt-compute azure-mgmt-network azure-identity azure-mgmt-resource psutil --trusted-host 192.168.100.11
+# install awscli boto3 psutil
+LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/ca/lib/ pip3 install -i http://192.168.100.11/pypirepo/py3/simple awscli boto3 psutil --trusted-host 192.168.100.11
 
 rm -f /etc/fstab
 rm -fr /home/disk1
Index: /branches/rel_apv_10_7/tools/ustack.spec
===================================================================
--- /branches/rel_apv_10_7/tools/ustack.spec	(revision 38947)
+++ /branches/rel_apv_10_7/tools/ustack.spec	(working copy)
@@ -117,6 +117,7 @@
 
 /usr/bin/cp -af %{ustack_rootdir}/usr/click/tools/prometheus_client %{buildroot}/ca/bin/
 /usr/bin/cp -af %{ustack_rootdir}/usr/click/tools/azure %{buildroot}/ca/bin/
+/usr/bin/cp -af %{ustack_rootdir}/usr/click/tools/aws %{buildroot}/ca/bin/
 
 install -Dm 0755 -t %{buildroot}/ca/bin \
 	%{ustack_rootdir}/usr/click/lib/libuinet-atcp/bin/atcp/atcp \
Index: /branches/rel_apv_10_7/usr/click/bin/backend/sys_cmd.c
===================================================================
--- /branches/rel_apv_10_7/usr/click/bin/backend/sys_cmd.c	(revision 38947)
+++ /branches/rel_apv_10_7/usr/click/bin/backend/sys_cmd.c	(working copy)
@@ -3679,6 +3679,368 @@
 
 // AZURE CLOUD FUNCTION END
 
+// AWS CLOUD FUNCTION START
+
+void cloud_aws_log_on()
+{
+	FILE *fp;
+	char path[1035];
+	char cmd[1024];
+	snprintf(cmd, 1024, "python3 /ca/bin/aws/LoggerManager.py -mode on");
+	fp = popen(cmd, "r");
+	if (fp == NULL) {
+        printf("Failed to run command\n" );
+        exit(1);
+    }
+    while (fgets(path, sizeof(path)-1, fp) != NULL) {
+        printf("%s", path);
+    }
+    pclose(fp);
+}
+
+void cloud_aws_log_off()
+{
+	FILE *fp;
+	char path[1035];
+	char cmd[1024];
+	snprintf(cmd, 1024, "python3 /ca/bin/aws/LoggerManager.py -mode off");
+	fp = popen(cmd, "r");
+	if (fp == NULL) {
+        printf("Failed to run command\n" );
+        exit(1);
+    }
+    while (fgets(path, sizeof(path)-1, fp) != NULL) {
+        printf("%s", path);
+    }
+    pclose(fp);
+}
+
+void cloud_aws_show_log_config()
+{
+	FILE *fp;
+	char path[1035];
+	char cmd[1024];
+	snprintf(cmd, 1024, "python3 /ca/bin/aws/LoggerManager.py -mode status");
+	fp = popen(cmd, "r");
+	if (fp == NULL) {
+        printf("Failed to run command\n" );
+        exit(1);
+    }
+    while (fgets(path, sizeof(path)-1, fp) != NULL) {
+        printf("%s", path);
+    }
+    pclose(fp);
+}
+
+void cloud_aws_show_log_buffer()
+{
+	FILE *fp;
+	char path[1035];
+	char cmd[1024];
+	snprintf(cmd, 1024, "python3 /ca/bin/aws/LoggerManager.py -mode show");
+	fp = popen(cmd, "r");
+	if (fp == NULL) {
+        printf("Failed to run command\n" );
+        exit(1);
+    }
+    while (fgets(path, sizeof(path)-1, fp) != NULL) {
+        printf("%s", path);
+    }
+    pclose(fp);
+}
+
+void cloud_aws_log_severity()
+{
+	FILE *fp;
+	char path[1035];
+	char cmd[1024];
+	snprintf(cmd, 1024, "python3 /ca/bin/aws/LoggerManager.py -level status");
+	fp = popen(cmd, "r");
+	if (fp == NULL) {
+        printf("Failed to run command\n" );
+        exit(1);
+    }
+    while (fgets(path, sizeof(path)-1, fp) != NULL) {
+        printf("%s", path);
+    }
+    pclose(fp);
+}
+
+void cloud_aws_loglevel_debug()
+{
+	FILE *fp;
+	char path[1035];
+	char cmd[1024];
+	snprintf(cmd, 1024, "python3 /ca/bin/aws/LoggerManager.py -level debug");
+	fp = popen(cmd, "r");
+	if (fp == NULL) {
+        printf("Failed to run command\n" );
+        exit(1);
+    }
+    while (fgets(path, sizeof(path)-1, fp) != NULL) {
+        printf("%s", path);
+    }
+    pclose(fp);
+}
+
+void cloud_aws_loglevel_info()
+{
+	FILE *fp;
+	char path[1035];
+	char cmd[1024];
+	snprintf(cmd, 1024, "python3 /ca/bin/aws/LoggerManager.py -level info");
+	fp = popen(cmd, "r");
+	if (fp == NULL) {
+        printf("Failed to run command\n" );
+        exit(1);
+    }
+    while (fgets(path, sizeof(path)-1, fp) != NULL) {
+        printf("%s", path);
+    }
+    pclose(fp);
+}
+
+void cloud_aws_loglevel_warning()
+{
+	FILE *fp;
+	char path[1035];
+	char cmd[1024];
+	snprintf(cmd, 1024, "python3 /ca/bin/aws/LoggerManager.py -level warning");
+	fp = popen(cmd, "r");
+	if (fp == NULL) {
+        printf("Failed to run command\n" );
+        exit(1);
+    }
+    while (fgets(path, sizeof(path)-1, fp) != NULL) {
+        printf("%s", path);
+    }
+    pclose(fp);
+}
+
+void cloud_aws_loglevel_error()
+{
+	FILE *fp;
+	char path[1035];
+	char cmd[1024];
+	snprintf(cmd, 1024, "python3 /ca/bin/aws/LoggerManager.py -level error");
+	fp = popen(cmd, "r");
+	if (fp == NULL) {
+        printf("Failed to run command\n" );
+        exit(1);
+    }
+    while (fgets(path, sizeof(path)-1, fp) != NULL) {
+        printf("%s", path);
+    }
+    pclose(fp);
+}
+
+
+void cloud_aws_login(char *access_key, char *secret_access_key, char *region)
+{
+	FILE *fp;
+	char path[1035];
+	char cmd[1024];
+	snprintf(cmd, 1024, "python3 /ca/bin/aws/AWSAuthManager.py -mode login -access_key %s -secret_access_key %s -region %s",
+		access_key, secret_access_key, region);
+	fp = popen(cmd, "r");
+	if (fp == NULL) {
+        printf("Failed to run command\n" );
+        exit(1);
+    }
+    while (fgets(path, sizeof(path)-1, fp) != NULL) {
+        printf("%s", path);
+    }
+    pclose(fp);
+
+}
+
+void cloud_aws_logout()
+{
+	FILE *fp;
+	char path[1035];
+	char cmd[1024];
+
+	fp = popen("python3 /ca/bin/aws/AWSAuthManager.py -mode logout", "r");
+	if (fp == NULL) {
+        printf("Failed to run command\n" );
+        exit(1);
+    }
+    while (fgets(path, sizeof(path)-1, fp) != NULL) {
+        printf("%s", path);
+    }
+    pclose(fp);
+}
+
+void cloud_aws_show_account()
+{
+	FILE *fp;
+	char path[1035];
+	char cmd[1024];
+
+	fp = popen("python3 /ca/bin/aws/AWSAuthManager.py -mode show", "r");
+	if (fp == NULL) {
+        printf("Failed to run command\n" );
+        exit(1);
+    }
+    while (fgets(path, sizeof(path)-1, fp) != NULL) {
+        printf("%s", path);
+    }
+    pclose(fp);
+}
+
+void cloud_aws_failover_trigger()
+{
+	FILE *fp;
+	char path[1035];
+	char cmd[1024];
+
+	fp = popen("python3 /ca/bin/aws/AWSENIManager.py -mode trigger", "r");
+	if (fp == NULL) {
+        printf("Failed to run command\n" );
+        exit(1);
+    }
+    while (fgets(path, sizeof(path)-1, fp) != NULL) {
+        printf("%s", path);
+    }
+    pclose(fp);
+}
+
+void cloud_aws_failover_recover()
+{
+	FILE *fp;
+	char path[1035];
+	char cmd[1024];
+
+	fp = popen("python3 /ca/bin/aws/AWSENIManager.py -mode recover", "r");
+	if (fp == NULL) {
+        printf("Failed to run command\n" );
+        exit(1);
+    }
+    while (fgets(path, sizeof(path)-1, fp) != NULL) {
+        printf("%s", path);
+    }
+    pclose(fp);
+}
+
+void cloud_aws_set_eniconfig(char *src_eni_id, char *dest_eni_id)
+{
+	FILE *fp;
+	char path[1035];
+	char cmd[1024];
+	snprintf(cmd, 1024, "python3 /ca/bin/aws/AWSConfigManager.py -ENI set -src_eni_id %s -dest_eni_id %s",
+		src_eni_id, dest_eni_id);
+	fp = popen(cmd, "r");
+	if (fp == NULL) {
+        printf("Failed to run command\n" );
+        exit(1);
+    }
+    while (fgets(path, sizeof(path)-1, fp) != NULL) {
+        printf("%s", path);
+    }
+    pclose(fp);
+}
+
+void cloud_aws_clear_eniconfig()
+{
+	FILE *fp;
+	char path[1035];
+	char cmd[1024];
+
+	fp = popen("python3 /ca/bin/aws/AWSConfigManager.py -ENI clear", "r");
+	if (fp == NULL) {
+        printf("Failed to run command\n" );
+        exit(1);
+    }
+    while (fgets(path, sizeof(path)-1, fp) != NULL) {
+        printf("%s", path);
+    }
+    pclose(fp);
+}
+
+void cloud_aws_show_eniconfig()
+{
+	FILE *fp;
+	char path[1035];
+	char cmd[1024];
+
+	fp = popen("python3 /ca/bin/aws/AWSConfigManager.py -ENI show", "r");
+	if (fp == NULL) {
+        printf("Failed to run command\n" );
+        exit(1);
+    }
+    while (fgets(path, sizeof(path)-1, fp) != NULL) {
+        printf("%s", path);
+    }
+    pclose(fp);
+}
+
+void cloud_aws_remove_eniconfig(char *index)
+{
+	FILE *fp;
+	char path[1035];
+	char cmd[1024];
+	snprintf(cmd, 1024, "python3 /ca/bin/aws/AWSConfigManager.py -ENI remove -index %s",
+		index);
+	fp = popen(cmd, "r");
+	if (fp == NULL) {
+        printf("Failed to run command\n" );
+        exit(1);
+    }
+    while (fgets(path, sizeof(path)-1, fp) != NULL) {
+        printf("%s", path);
+    }
+    pclose(fp);
+}
+
+void cloud_aws_ha_enable()
+{
+	FILE *fp;
+	char path[1035];
+	char cmd[1024];
+
+	snprintf(cmd, 1024, "python3 /ca/bin/aws/AWSFailoverPoller.py -mode enable &");
+	system(cmd);
+
+	sleep(2);
+	printf("Success\n");
+
+}
+
+void cloud_aws_ha_disable()
+{
+	FILE *fp;
+	char path[1035];
+	char cmd[1024];
+
+	fp = popen("python3 /ca/bin/aws/AWSFailoverPoller.py -mode disable", "r");
+	if (fp == NULL) {
+        printf("Failed to run command\n" );
+        exit(1);
+    }
+    while (fgets(path, sizeof(path)-1, fp) != NULL) {
+        printf("%s", path);
+    }
+    pclose(fp);
+}
+
+void cloud_aws_ha_show()
+{
+	FILE *fp;
+	char path[1035];
+	char cmd[1024];
+
+	fp = popen("python3 /ca/bin/aws/AWSFailoverPoller.py -mode status", "r");
+	if (fp == NULL) {
+        printf("Failed to run command\n" );
+        exit(1);
+    }
+    while (fgets(path, sizeof(path)-1, fp) != NULL) {
+        printf("%s", path);
+    }
+    pclose(fp);
+}
+
+// AWS CLOUD FUNCTION END
 
 int
 ui_ping_gw(uint32_t ip, uint32_t gateway, char* option)
Index: /branches/rel_apv_10_7/usr/click/lib/libparser/commands.pm
===================================================================
--- /branches/rel_apv_10_7/usr/click/lib/libparser/commands.pm	(revision 38947)
+++ /branches/rel_apv_10_7/usr/click/lib/libparser/commands.pm	(working copy)
@@ -792,7 +792,434 @@
 
 # AZURE COMMAND END
 
+# AWS COMMAND START
 
+	# cloud aws
+
+	{
+		obj_type => "MENU",
+		name => "aws",
+		parent_menu => "root_cloud",
+		uniq_name => "root_cloud_aws",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL",
+		user_level => "CLI_LEVEL_CONFIG",
+		help_string => "Display AWS Azure decision",
+	},
+
+	# cloud aws log
+
+	{
+		obj_type => "MENU",
+		name => "log",
+		parent_menu => "root_cloud_aws",
+		uniq_name => "root_cloud_aws_log",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL",
+		user_level => "CLI_LEVEL_CONFIG",
+		help_string => "Display Cloud AWS Log decision",
+	},
+
+	# cloud aws log on
+
+	{
+		obj_type => "ITEM",
+		name => "on",
+		menu => "root_cloud_aws_log",
+		help_string => "Set the log functionality on",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_KILLABLE|CMD_NON_MORE",
+		user_level => "CLI_LEVEL_CONFIG",
+		function_name => "cloud_aws_log_on",
+		function_args => [],
+	},
+
+	# cloud aws log off
+
+	{
+		obj_type => "ITEM",
+		name => "off",
+		menu => "root_cloud_aws_log",
+		help_string => "Set the log functionality off",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_KILLABLE|CMD_NON_MORE",
+		user_level => "CLI_LEVEL_CONFIG",
+		function_name => "cloud_aws_log_off",
+		function_args => [],
+	},
+
+	# cloud aws show
+
+	{
+		obj_type => "MENU",
+		name => "show",
+		parent_menu => "root_cloud_aws",
+		uniq_name => "root_cloud_aws_show",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL",
+		user_level => "CLI_LEVEL_CONFIG",
+		help_string => "Display Cloud AWS show decision",
+	},
+
+	# cloud aws show log
+
+	{
+		obj_type => "MENU",
+		name => "log",
+		parent_menu => "root_cloud_aws_show",
+		uniq_name => "root_cloud_aws_show_log",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL",
+		user_level => "CLI_LEVEL_CONFIG",
+		help_string => "Display Cloud AWS show log decision",
+	},
+
+	# cloud aws show log config
+
+	{
+		obj_type => "ITEM",
+		name => "config",
+		menu => "root_cloud_aws_show_log",
+		help_string => "Check AWS CLI log functionality status",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_KILLABLE|CMD_NON_MORE",
+		user_level => "CLI_LEVEL_CONFIG",
+		function_name => "cloud_aws_show_log_config",
+		function_args => [],
+	},
+
+	# cloud aws show log buffer
+
+	{
+		obj_type => "ITEM",
+		name => "buffer",
+		menu => "root_cloud_aws_show_log",
+		help_string => "Show the log of aws tools",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_KILLABLE|CMD_NON_MORE",
+		user_level => "CLI_LEVEL_CONFIG",
+		function_name => "cloud_aws_show_log_buffer",
+		function_args => [],
+	},
+
+	# cloud aws show log severity
+
+	{
+		obj_type => "ITEM",
+		name => "severity",
+		menu => "root_cloud_aws_show_log",
+		help_string => "Show current log severity",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_KILLABLE|CMD_NON_MORE",
+		user_level => "CLI_LEVEL_CONFIG",
+		function_name => "cloud_aws_log_severity",
+		function_args => [],
+	},
+
+	# cloud aws loglevel
+
+	{
+		obj_type => "MENU",
+		name => "loglevel",
+		parent_menu => "root_cloud_aws",
+		uniq_name => "root_cloud_aws_loglevel",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL",
+		user_level => "CLI_LEVEL_CONFIG",
+		help_string => "Display Cloud AWS loglevel decision",
+	},
+
+	# cloud aws loglevel debug
+
+	{
+		obj_type => "ITEM",
+		name => "debug",
+		menu => "root_cloud_aws_loglevel",
+		help_string => "Set the log severity to debug",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_KILLABLE|CMD_NON_MORE",
+		user_level => "CLI_LEVEL_CONFIG",
+		function_name => "cloud_aws_loglevel_debug",
+		function_args => [],
+	},
+	# cloud aws loglevel info
+
+	{
+		obj_type => "ITEM",
+		name => "info",
+		menu => "root_cloud_aws_loglevel",
+		help_string => "Set the log severity to info",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_KILLABLE|CMD_NON_MORE",
+		user_level => "CLI_LEVEL_CONFIG",
+		function_name => "cloud_aws_loglevel_info",
+		function_args => [],
+	},
+	# cloud aws loglevel warning
+
+	{
+		obj_type => "ITEM",
+		name => "warning",
+		menu => "root_cloud_aws_loglevel",
+		help_string => "Set the log severity to warning",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_KILLABLE|CMD_NON_MORE",
+		user_level => "CLI_LEVEL_CONFIG",
+		function_name => "cloud_aws_loglevel_warning",
+		function_args => [],
+	},
+	# cloud aws loglevel error
+
+	{
+		obj_type => "ITEM",
+		name => "error",
+		menu => "root_cloud_aws_loglevel",
+		help_string => "Set the log severity to error",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_KILLABLE|CMD_NON_MORE",
+		user_level => "CLI_LEVEL_CONFIG",
+		function_name => "cloud_aws_loglevel_error",
+		function_args => [],
+	},
+
+	# cloud aws login
+
+	{
+		obj_type => "ITEM",
+		name => "login",
+		menu => "root_cloud_aws",
+		help_string => "Set aws credential",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_KILLABLE|CMD_NON_MORE",
+		user_level => "CLI_LEVEL_CONFIG",
+		function_name => "cloud_aws_login",
+		function_args => [
+				{
+						type => "STRING",
+						help_string => "Enter access key: ",
+						optional => "NO",
+				},
+				{
+						type => "STRING",
+						help_string => "Enter secret acces key: ",
+						optional => "NO",
+				},
+				{
+						type => "STRING",
+						help_string => "Enter region: ",
+						optional => "NO",
+				}
+		],
+	},
+
+	# cloud aws logout
+
+	{
+		obj_type => "ITEM",
+		name => "logout",
+		menu => "root_cloud_aws",
+		help_string => "Clear aws credential",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_KILLABLE|CMD_NON_MORE",
+		user_level => "CLI_LEVEL_CONFIG",
+		function_name => "cloud_aws_logout",
+		function_args => [],
+	},
+
+	# cloud aws show account
+
+	{
+		obj_type => "ITEM",
+		name => "account",
+		menu => "root_cloud_aws_show",
+		help_string => "Check the credential details in AWS",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_KILLABLE|CMD_NON_MORE",
+		user_level => "CLI_LEVEL_CONFIG",
+		function_name => "cloud_aws_show_account",
+		function_args => [],
+	},
+
+	# cloud aws failover
+
+	{
+		obj_type => "MENU",
+		name => "failover",
+		parent_menu => "root_cloud_aws",
+		uniq_name => "root_cloud_aws_failover",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL",
+		user_level => "CLI_LEVEL_CONFIG",
+		help_string => "Display Cloud AWS failover decision",
+	},
+
+	# cloud aws failover trigger
+
+	{
+		obj_type => "ITEM",
+		name => "trigger",
+		menu => "root_cloud_aws_failover",
+		help_string => "Manually trigger IP transfer from primary APV to secondary during failover (for development use only)",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_KILLABLE|CMD_NON_MORE",
+		user_level => "CLI_LEVEL_CONFIG",
+		function_name => "cloud_aws_failover_trigger",
+		function_args => [],
+	},
+
+	# cloud aws failover recover
+
+	{
+		obj_type => "ITEM",
+		name => "recover",
+		menu => "root_cloud_aws_failover",
+		help_string => "Manually restore IP configuration to original status after primary APV recovery (for development use only)",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_KILLABLE|CMD_NON_MORE",
+		user_level => "CLI_LEVEL_CONFIG",
+		function_name => "cloud_aws_failover_recover",
+		function_args => [],
+	},
+
+	# cloud aws set
+
+	{
+		obj_type => "MENU",
+		name => "set",
+		parent_menu => "root_cloud_aws",
+		uniq_name => "root_cloud_aws_set",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL",
+		user_level => "CLI_LEVEL_CONFIG",
+		help_string => "Display Cloud AWS set decision",
+	},
+
+	# cloud aws set eniconfig
+
+	{
+		obj_type => "ITEM",
+		name => "eniconfig",
+		menu => "root_cloud_aws_set",
+		help_string => "Set IP configuration for the network interface (used during failover and recovery)",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_KILLABLE|CMD_NON_MORE",
+		user_level => "CLI_LEVEL_CONFIG",
+		function_name => "cloud_aws_set_eniconfig",
+		function_args => [
+					{
+						type => "STRING",
+						help_string => "Enter source eni id: ",
+						optional => "NO",
+
+					},
+					{
+						type => "STRING",
+						help_string => "Enter destination eni id: ",
+						optional => "NO",
+					},
+		],
+	},
+
+	# cloud aws clear
+
+	{
+		obj_type => "MENU",
+		name => "clear",
+		parent_menu => "root_cloud_aws",
+		uniq_name => "root_cloud_aws_clear",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL",
+		user_level => "CLI_LEVEL_CONFIG",
+		help_string => "Display Cloud AWS clear decision",
+	},
+
+	# cloud aws clear eniconfig
+
+	{
+		obj_type => "ITEM",
+		name => "eniconfig",
+		menu => "root_cloud_aws_clear",
+		help_string => "Clear IP configuration for the network interface (used during failover and recovery)",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_KILLABLE|CMD_NON_MORE",
+		user_level => "CLI_LEVEL_CONFIG",
+		function_name => "cloud_aws_clear_eniconfig",
+		function_args => [],
+	},
+
+
+	# cloud aws show eniconfig
+
+	{
+		obj_type => "ITEM",
+		name => "eniconfig",
+		menu => "root_cloud_aws_show",
+		help_string => "Display IP configuration for the network interface (used during failover and recovery)",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_KILLABLE|CMD_NON_MORE",
+		user_level => "CLI_LEVEL_CONFIG",
+		function_name => "cloud_aws_show_eniconfig",
+		function_args => [],
+	},
+
+	# cloud aws remove
+
+	{
+		obj_type => "MENU",
+		name => "remove",
+		parent_menu => "root_cloud_aws",
+		uniq_name => "root_cloud_aws_remove",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL",
+		user_level => "CLI_LEVEL_CONFIG",
+		help_string => "Display Cloud AWS remove decision",
+	},
+
+	# cloud aws remove eniconfig
+
+	{
+		obj_type => "ITEM",
+		name => "eniconfig",
+		menu => "root_cloud_aws_remove",
+		help_string => "Delete specific IP configuration for the network interface (used during failover and recovery) given index",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_KILLABLE|CMD_NON_MORE",
+		user_level => "CLI_LEVEL_CONFIG",
+		function_name => "cloud_aws_remove_eniconfig",
+		function_args => [
+					{
+						type => "STRING",
+						help_string => "Enter index eni index: ",
+						optional => "NO",
+					},
+		],
+	},
+
+	# cloud aws ha
+
+	{
+		obj_type => "MENU",
+		name => "ha",
+		parent_menu => "root_cloud_aws",
+		uniq_name => "root_cloud_aws_ha",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL",
+		user_level => "CLI_LEVEL_CONFIG",
+		help_string => "Display Cloud AWS ha decision",
+	},
+
+	# cloud aws ha enable
+
+	{
+		obj_type => "ITEM",
+		name => "enable",
+		menu => "root_cloud_aws_ha",
+		help_string => "Enable automatic IP transfer and recovery during HA failover",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_KILLABLE|CMD_NON_MORE",
+		user_level => "CLI_LEVEL_CONFIG",
+		function_name => "cloud_aws_ha_enable",
+		function_args => [],
+	},
+
+	# cloud aws ha disable
+
+	{
+		obj_type => "ITEM",
+		name => "disable",
+		menu => "root_cloud_aws_ha",
+		help_string => "Disable automatic IP transfer and recovery during HA failover",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_KILLABLE|CMD_NON_MORE",
+		user_level => "CLI_LEVEL_CONFIG",
+		function_name => "cloud_aws_ha_disable",
+		function_args => [],
+	},
+
+	# cloud aws ha show
+
+	{
+		obj_type => "ITEM",
+		name => "show",
+		menu => "root_cloud_aws_ha",
+		help_string => "Check if the cloud aws ha is enable or not.",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_KILLABLE|CMD_NON_MORE",
+		user_level => "CLI_LEVEL_CONFIG",
+		function_name => "cloud_aws_ha_show",
+		function_args => [],
+	},
+
+# AWS COMMAND END
 
 	{
 		#Menu objects are not that special, just a hash
Index: /branches/rel_apv_10_7/usr/click/tools/aws/AWSAuthManager.py
===================================================================
--- /branches/rel_apv_10_7/usr/click/tools/aws/AWSAuthManager.py	(revision 0)
+++ /branches/rel_apv_10_7/usr/click/tools/aws/AWSAuthManager.py	(working copy)
@@ -0,0 +1,72 @@
+import argparse
+from aws_auth.AWSAuthController import AWSAuthController
+from logger.ProxyAWSLogger import ProxyAWSLogger
+
+
+class AWSAuthManager():
+    '''
+    A class that uses AWSAuthController do the task.
+    The facade design pattern.
+
+    '''
+    def __init__():
+        pass
+
+    @classmethod
+    def login(cls, access_key: str, secret_key: str, region: str):
+        AWSAuthController.login(access_key=access_key,
+                                secret_key=secret_key,
+                                region=region)
+        log_in_info = AWSAuthController.get_login_info()
+
+        ProxyAWSLogger.info(f"log in with access key: "
+                            f"{log_in_info['aws_access_key_id']}")
+
+    @classmethod
+    def logout(cls):
+        log_in_info = AWSAuthController.get_login_info()
+        try:
+            AWSAuthController.logout()
+            ProxyAWSLogger.info(f"log out with access key: "
+                                f"{log_in_info['aws_access_key_id']}")
+        except Exception as e:
+            print(str(e))
+
+    @classmethod
+    def show(cls):
+        try:
+            log_in_info = AWSAuthController.get_login_info()
+            ProxyAWSLogger.info(f"show log in information with access key: "
+                                f"{log_in_info['aws_access_key_id']}")
+            print(log_in_info)
+        except Exception as e:
+            ProxyAWSLogger.error(str(e))
+
+
+if __name__ == "__main__":
+    choices = ["login", "logout", "show"]
+    parser = argparse.ArgumentParser(
+        description='This API is used to control AWS authentication.')
+    parser.add_argument(
+        '-mode',
+        type=str,
+        choices=choices,
+        help='Enter [login], [logout], or [show]')
+    parser.add_argument('-access_key', type=str,
+                        help='Enter your AWS access key')
+    parser.add_argument('-secret_access_key', type=str,
+                        help='EEnter your AWS secret access key')
+    parser.add_argument('-region', type=str, help='Enter your AWS region')
+
+    args = parser.parse_args()
+    if args.mode == "login":
+        AWSAuthManager.login(
+            args.access_key, args.secret_access_key, args.region)
+    elif args.mode == "logout":
+        AWSAuthManager.logout()
+    elif args.mode == "show":
+        AWSAuthManager.show()
+    else:
+        ProxyAWSLogger.error(
+            f'Error: mode must arugment must {", ".join(choices)}.'
+            f'Got mode:[{args.mode}]')
Index: /branches/rel_apv_10_7/usr/click/tools/aws/AWSConfigManager.py
===================================================================
--- /branches/rel_apv_10_7/usr/click/tools/aws/AWSConfigManager.py	(revision 0)
+++ /branches/rel_apv_10_7/usr/click/tools/aws/AWSConfigManager.py	(working copy)
@@ -0,0 +1,110 @@
+import argparse
+from logger.ProxyAWSLogger import ProxyAWSLogger
+from aws_eni.AWSENIConfigurator import AWSENIConfigurator
+
+
+class AWSConfigManger():
+    def __init__(self):
+        pass
+
+    @classmethod
+    def add_eni_config(cls, src_eni_id: str, dest_eni_id: str) -> None:
+        '''
+        This is used to add a pair of ENIs to configuration.
+
+        Args:
+            src_eni_id(str): The eni id of source eni
+            dest_eni_id(str): The eni id of destination eni
+
+        Returns:
+            None: This function does not return any value.
+        '''
+        try:
+            AWSENIConfigurator.add_eni_config(src_eni_id, dest_eni_id)
+            ProxyAWSLogger.info(f"Successfully add pair "
+                                f"ENI configuration of {src_eni_id} {dest_eni_id}")
+        except Exception as e:
+            ProxyAWSLogger.error(f"Fail to add ENI configuration {str(e)}")
+
+    @classmethod
+    def show_eni_config(cls) -> None:
+        '''
+        Print all ENI configuration with json format
+
+        Args:
+            None: This function does not take any arguments.
+
+        Returns:
+            None: This function does not return any value.
+        '''
+        try:
+            config = AWSENIConfigurator.get_config()
+            print(config)
+            ProxyAWSLogger.info(f"Successfully get ENI configuration")
+        except Exception as e:
+            ProxyAWSLogger.error(f"Fail to get ENI configuration {str(e)}")
+
+    @classmethod
+    def remove_eni_config(cls, index: str) -> None:
+        '''
+        Remove ENI configuration according to given index.
+
+        Args:
+            index(str): The index of ENI configuration needs to be removed.
+
+        Returns:
+            None: This function does not return any value.
+        '''
+        try:
+            AWSENIConfigurator.remove_eni_config(index)
+            ProxyAWSLogger.info(f"Successfully remove "
+                                f"ENI configuration with index: {index}")
+        except Exception as e:
+            ProxyAWSLogger.error(f"Fail to remove ENI configuration "
+                                 f"with index: {index} {str(e)}")
+
+    @classmethod
+    def clear_eni_config(cls) -> None:
+        '''
+        Remove all ENI configurations
+
+        Args:
+            None: This function does not take any arguments.
+
+        Returns:
+            None: This function does not return any value.
+        '''
+        try:
+            AWSENIConfigurator.clear_eni_config()
+            ProxyAWSLogger.info(f"Successfully clear "
+                                f"ENI configuration")
+        except Exception as e:
+            ProxyAWSLogger.error(f"Fail to clear ENI configuration {str(e)}")
+
+
+if __name__ == "__main__":
+    choices = ["set", "show", "remove", "clear"]
+    parser = argparse.ArgumentParser(description='Configure AWS ENI.')
+    parser.add_argument('-ENI', type=str,
+                        choices=choices,
+                        help=f"Enter one of the following {', '.join(choices)}")
+    parser.add_argument('-src_eni_id', type=str,
+                        help=f"Enter the source eni id")
+    parser.add_argument('-dest_eni_id', type=str,
+                        help=f"Enter the destination eni id")
+    parser.add_argument('-index', type=str,
+                        help=f"Enter the index of pair of ENI configuration")
+    args = parser.parse_args()
+
+    if args.ENI == "set":
+        AWSConfigManger.add_eni_config(args.src_eni_id, args.dest_eni_id)
+    elif args.ENI == "show":
+        AWSConfigManger.show_eni_config()
+    elif args.ENI == "remove":
+        AWSConfigManger.remove_eni_config(args.index)
+    elif args.ENI == "clear":
+        AWSConfigManger.clear_eni_config()
+    else:
+        ProxyAWSLogger.error(
+            f'Error: ENI must arugment must {", ".join(choices)}.'
+            f'Got ENI:[{args.ENI}]')
Index: /branches/rel_apv_10_7/usr/click/tools/aws/AWSENIManager.py
===================================================================
--- /branches/rel_apv_10_7/usr/click/tools/aws/AWSENIManager.py	(revision 0)
+++ /branches/rel_apv_10_7/usr/click/tools/aws/AWSENIManager.py	(working copy)
@@ -0,0 +1,75 @@
+import argparse
+from logger.ProxyAWSLogger import ProxyAWSLogger
+from aws_eni.AWSENIController import AWSENIController
+from aws_eni.AWSENIConfigurator import AWSENIConfigurator
+from aws_auth.AWSAuthController import AWSAuthController
+
+
+class AWSENIManager():
+    '''
+    This class is used to manually trigger the tasks when the
+    failover happens and recover back to the original state.
+    '''
+
+    def __init__(self):
+        pass
+
+    @classmethod
+    def failover_happen(cls):
+        if not AWSAuthController.is_authenticated():
+            ProxyAWSLogger.error("Invalid credential")
+            return
+        # get eni config
+        eni_config = AWSENIConfigurator.get_config()
+        # do ip swifting
+        for key in eni_config:
+            ProxyAWSLogger.info(f'transferring IPs from '
+                                f'{eni_config[key]["src_eni_id"]} to'
+                                f'{eni_config[key]["dest_eni_id"]}')
+            try:
+                AWSENIController.transfer_secondary_ip(
+                    eni_config[key]["src_eni_id"], eni_config[key]["dest_eni_id"])
+            except Exception as e:
+                ProxyAWSLogger.error(str(e))
+
+    @classmethod
+    def failover_recover(cls):
+        if not AWSAuthController.is_authenticated():
+            ProxyAWSLogger.error("Invalid credential")
+            return
+        # get eni config
+        eni_config = AWSENIConfigurator.get_config()
+        # do ip swifting
+        for key in eni_config:
+            ProxyAWSLogger.info(f'transferring IPs from '
+                                f'{eni_config[key]["dest_eni_id"]} to'
+                                f'{eni_config[key]["src_eni_id"]}')
+            try:
+                AWSENIController.transfer_secondary_ip(
+                    eni_config[key]["dest_eni_id"], eni_config[key]["src_eni_id"])
+            except Exception as e:
+                ProxyAWSLogger.error(str(e))
+
+
+if __name__ == '__main__':
+    choices = ["trigger", "recover"]
+    parser = argparse.ArgumentParser(
+        description='This API used to manual trigger failover or \
+        recover ip shifiting functionality.')
+    parser.add_argument(
+        '-mode',
+        type=str,
+        choices=choices,
+        help='Enter [trigger] or [recover]')
+
+    args = parser.parse_args()
+    if args.mode == "trigger":
+        ProxyAWSLogger.info("manually trigger failover")
+        AWSENIManager.failover_happen()
+    elif args.mode == "recover":
+        ProxyAWSLogger.info("manually trigger recover")
+        AWSENIManager.failover_recover()
+    else:
+        ProxyAWSLogger.error(
+            f'Error: mode must arugment must {", ".join(choices)}.'
+            f'Got mode:[{args.mode}]')
Index: /branches/rel_apv_10_7/usr/click/tools/aws/AWSFailoverPoller.py
===================================================================
--- /branches/rel_apv_10_7/usr/click/tools/aws/AWSFailoverPoller.py	(revision 0)
+++ /branches/rel_apv_10_7/usr/click/tools/aws/AWSFailoverPoller.py	(working copy)
@@ -0,0 +1,138 @@
+import os
+import time
+from datetime import datetime
+import psutil
+import argparse
+from logger.ProxyAWSLogger import ProxyAWSLogger
+from apv_controller.APVController import APVController
+from aws_eni.AWSENIConfigurator import AWSENIConfigurator
+from AWSENIManager import AWSENIManager
+
+
+class AWSFailoverPoller():
+    def __init__(self):
+        pass
+
+    @classmethod
+    def start(cls):
+        in_failover = False
+        polling_period = 2  # seconds
+        apv_c = APVController()
+        if apv_c.is_primary():
+            ProxyAWSLogger.debug(
+                f"This APV [{apv_c.get_apv_name()}] is primary APV in HA. Stop pooling.")
+            return
+        ProxyAWSLogger.debug(
+            f"This APV [{apv_c.get_apv_name()}] is secondary APV in HA.")
+        ProxyAWSLogger.info(f'APV [{apv_c.get_apv_name()}] start polling')
+        # pooling
+        while True:
+            time.sleep(polling_period)
+            current_time = datetime.now().strftime("%Y-%m-%d %H %M %S")
+            print("try pooling ", current_time)
+            ProxyAWSLogger.debug("try pooling")
+            # primary machine doesn't need to do pooling
+            if apv_c.is_primary():
+                break
+            if not apv_c.is_primary_alive():
+                if not in_failover:
+                    # failover happen
+                    ProxyAWSLogger.info(f"Failover happened")
+                    AWSENIManager.failover_happen()
+
+                    # todo need to verify that all setting are set, and then set is_failover=True
+                    ProxyAWSLogger.info(
+                        "Succeessfully handle failover transition")
+
+                    # set in_failover=True for condition that the primary APV is ON again.
+                    in_failover = True
+                continue
+            elif in_failover:
+                # failover happended before and now the primary APV is ON
+                current_time = datetime.now().strftime("%Y-%m-%d %H %M %S")
+                ProxyAWSLogger.info(f"Failover recover on")
+                AWSENIManager.failover_recover()
+
+                # reset
+                in_failover = False
+
+    @classmethod
+    def stop(cls):
+        '''kill poller that is another running process by its filename,
+        a.k.a. this file name.'''
+        # get this module name (filename)
+        module_name = os.path.basename(__file__)
+        cls.kill_poller(module_name)
+
+    @classmethod
+    def kill_poller(self, process_name):
+        '''This method will kill all the process with the same
+        name of process_name.'''
+        for proc in psutil.process_iter(['pid', 'cmdline']):
+            if proc.info['cmdline']:
+                for peice_of_cmd in proc.info['cmdline']:
+                    if process_name in peice_of_cmd \
+                            and (not proc.info['pid'] == os.getpid()):
+                        proc.kill()
+                        ProxyAWSLogger.info("kill process_name")
+
+    @classmethod
+    def stop(self):
+        '''kill poller that is another running process by its filename,
+        a.k.a. this file name.'''
+        # get this module name (filename)
+        module_name = os.path.basename(__file__)
+        self.kill_poller(module_name)
+
+    @classmethod
+    def is_poller_running(self, this_mode) -> bool:
+        '''This method is used to determine if the poller is running or not.
+        return True if it is running
+        return False if it isn't running
+        '''
+        module_name = os.path.basename(__file__)
+        for proc in psutil.process_iter(['pid', 'cmdline']):
+            # print(module_name, proc.info, os.getpid())
+            if proc.info['cmdline']:
+                for peice_of_cmd in proc.info['cmdline']:
+                    if module_name in peice_of_cmd \
+                            and (not proc.info['pid'] == os.getpid()):
+                        return True
+        return False
+
+
+if __name__ == "__main__":
+    choices = ["enable", "disable", "status"]
+    parser = argparse.ArgumentParser(
+        description='This API is used to turn on and off the polling \
+        functionality of HA')
+    parser.add_argument(
+        '-mode',
+        type=str,
+        choices=choices,
+        help='Enter [enable], [disable], or [status] to manipulate poller.'
+    )
+    args = parser.parse_args()
+    if args.mode == "enable":
+        AWSFailoverPoller.start()
+    elif args.mode == "disable":
+        if AWSFailoverPoller.is_poller_running(args.mode):
+            ProxyAWSLogger.info("stop polling mode")
+            AWSFailoverPoller.stop()
+        else:
+            ProxyAWSLogger.info(
+                "try to stop polling mode, but the poller isn't running")
+    elif args.mode == "status":
+        status = AWSFailoverPoller.is_poller_running(args.mode)
+        print(status)
+        if status:
+            ProxyAWSLogger.info(
+                f"check {os.path.basename(__file__)} status: running")
+        else:
+            ProxyAWSLogger.info(
+                f"check {os.path.basename(__file__)} status: not running")
+    else:
+        hint_words = ", ".join(choices)
+        ProxyAWSLogger.error(
+            f"Error: mode must arugment must {hint_words}."
+            f"Got mode:[{args.mode}]")
Index: /branches/rel_apv_10_7/usr/click/tools/aws/LoggerManager.py
===================================================================
--- /branches/rel_apv_10_7/usr/click/tools/aws/LoggerManager.py	(revision 0)
+++ /branches/rel_apv_10_7/usr/click/tools/aws/LoggerManager.py	(working copy)
@@ -0,0 +1,75 @@
+import argparse
+from logger.ProxyAWSLogger import ProxyAWSLogger
+
+
+class LoggerManager():
+    def __init__():
+        pass
+
+    @classmethod
+    def turn_on_logger(cls) -> None:
+        ProxyAWSLogger.debug("Turn on log functionality.")
+        ProxyAWSLogger.turn_on()
+
+    @classmethod
+    def turn_off_logger(cls) -> None:
+        ProxyAWSLogger.debug("Turn off log functionality.")
+        ProxyAWSLogger.turn_off()
+
+    @classmethod
+    def check_Logger_state(cls) -> bool:
+        return ProxyAWSLogger.get_is_logger_on()
+
+    @classmethod
+    def check_Logger_level_state(cls) -> str:
+        return ProxyAWSLogger.get_Logger_level_state()
+
+    @classmethod
+    def get_log(cls, number_of_line: int = None) -> str:
+        res = ProxyAWSLogger.get_log()
+        return res
+
+    @classmethod
+    def set_logger_level(cls, level: str) -> None:
+        ProxyAWSLogger.info(f"set new log severity: {level}")
+        ProxyAWSLogger.set_level(level)
+
+    @classmethod
+    def get_log_file_path(cls) -> str:
+        log_file_path = ProxyAWSLogger.get_log_file_path()
+        ProxyAWSLogger.info("get log file path: "+log_file_path)
+        return log_file_path
+
+
+if __name__ == '__main__':
+    description = '''
+    This API is used to
+    1. manipulate the mode(on or off) of the functionality.
+    2. dump the log message.
+    3. check current logger status
+    4. set the log severity and show log severity'''
+    parser = argparse.ArgumentParser(description=description)
+    parser.add_argument('-mode', type=str, choices=["on", "off", "show", "status",
+                        "getlogpath"], help='Enter [on], [off], [getlogpath], or [show]')
+    parser.add_argument('-level', type=str, choices=["debug", "info", "warning", "error",
+                        "status"], help='choose severity amond [debug], [info], [warning], or [error]')
+    args = parser.parse_args()
+
+    # set severity
+    if args.level in ["debug", "info", "warning", "error"]:
+        LoggerManager.set_logger_level(args.level)
+    elif args.level in ["status"]:
+        print(LoggerManager.check_Logger_level_state())
+
+    # set mode
+    if args.mode == "on":
+        LoggerManager.turn_on_logger()
+    elif args.mode == "off":
+        LoggerManager.turn_off_logger()
+    elif args.mode == "show":
+        log = LoggerManager.get_log()
+        print(log)
+    elif args.mode == "status":
+        print(LoggerManager.check_Logger_state())
+    elif args.mode == "getlogpath":
+        print(LoggerManager.get_log_file_path())
Index: /branches/rel_apv_10_7/usr/click/tools/aws/apv_controller/APVCommander.py
===================================================================
--- /branches/rel_apv_10_7/usr/click/tools/aws/apv_controller/APVCommander.py	(revision 0)
+++ /branches/rel_apv_10_7/usr/click/tools/aws/apv_controller/APVCommander.py	(working copy)
@@ -0,0 +1,35 @@
+import subprocess
+
+
+class APVCommander():
+    def __init__(self) -> None:
+        pass
+
+    def launch_apv_command(self, apv_command: str):
+        '''
+        /ca/bin/backend -c "show version"`echo -e "\\0374"`
+        template:
+        /ca/bin/backend -c "APV_COMMAND"`echo -e "\\0374"`
+        example:
+        /ca/bin/backend -c "show ha status domain"`echo -e "\\0374"`
+        /ca/bin/backend -c "show version"`echo -e "\\0374"`
+        '''
+        return self.exec_cli_show(apv_command)
+
+    def exec_cli_show(self, cmd):
+        '''this function is from the Tim'''
+        cmd = "/ca/bin/backend -c \"{}\"`echo -e \"\\0374\"`".format(cmd)
+        # cmd = "/ca/bin/backend -c \"show version\"`echo -e \"\\0374\"`"
+        try:
+            output = subprocess.check_output(cmd, shell=True).strip()
+            # print('output', type(output), output.decode('latin-1'))
+            result = output.decode('latin-1')
+            return result[:-1]
+        except Exception as e:
+            print(e)
+
+
+if __name__ == "__main__":
+    c = APVCommander()
+    res = c.launch_apv_command("")
+    print(res)
Index: /branches/rel_apv_10_7/usr/click/tools/aws/apv_controller/APVController.py
===================================================================
--- /branches/rel_apv_10_7/usr/click/tools/aws/apv_controller/APVController.py	(revision 0)
+++ /branches/rel_apv_10_7/usr/click/tools/aws/apv_controller/APVController.py	(working copy)
@@ -0,0 +1,120 @@
+import re
+from collections import deque
+import argparse
+from apv_controller.APVCommander import APVCommander
+
+
+class APVController():
+    def __init__(self) -> None:
+        self.name = self.get_apv_name()
+        peer_state_q_max_len = 3  # workaround
+        self.peer_state_q: deque = deque(maxlen=peer_state_q_max_len)
+
+    def get_apv_version():
+        commander = APVCommander()
+        res = commander.launch_apv_command("show version")
+        return res
+
+    def get_apv_name(self) -> str:
+        ''' get APV name in HA.
+        Algo:
+        step1. Use 'show ha status domain' Array CLI to get the context.
+        step2. The local unit is the name of this APV.
+        '''
+        if hasattr(self, 'name'):
+            return self.name
+        commander = APVCommander()
+        context = commander.launch_apv_command("show ha status domain")
+        pattern = 'Local[\s]+unit:[\s]+(.+)\s(UP|DOWN)\s*'
+
+        name_list = re.findall(pattern, context)
+        if not name_list:
+            error_msg = "Error: cannot find APV name in "+context
+            raise Exception(error_msg)
+        return name_list[0][0].strip()
+
+    def is_primary(self) -> bool:
+        '''Check if this APV is primary.
+        Algo:
+        The highiest proirity is primary. Check if this APV name is the same with the name of APV that is highiest priority.
+        step1. Use "show ha config" APV command.
+        step2. Parse it by regrex to get ha group prioirty
+        step3. Sort it by prioirty
+        step4. Check if this APV name is same with the name of APV that is highiest priority.
+        '''
+        self.name = self.get_apv_name()
+        commander = APVCommander()
+        context = commander.launch_apv_command("show ha config")
+        # need to be checked
+        pattern = 'ha group priority \"(.+)\" [\d]+ (\d+)'
+        group_priority_list = re.findall(pattern, context)
+        if not group_priority_list:
+            error_msg = "Error: cannot find APV group priority in "+context
+            raise Exception(error_msg)
+
+        # make priority of string to integer
+        group_priority_list = [(item[0], int(item[1]))
+                               for item in group_priority_list]
+
+        # from low priority to heigh priority
+        sorted_group_priority_list = sorted(
+            group_priority_list, key=lambda x: x[1])
+
+        return self.name == sorted_group_priority_list[-1][0]
+
+    def is_primary_alive(self) -> bool:
+        '''This function is to check if the primary APV is alive or not.
+        return True: primary APV is alive, do nothing
+        return False: Primary APV is not alive.
+        This must be called in secondary APV.
+        Algo:
+        step1. Use APV CLI "show ha status domain to check if peer(primary APV) is UP or DOWN".
+        step2. if peer(primary APV) is "DOWN", it means primary is dead, aka not alive.
+        '''
+        commander = APVCommander()
+        context = commander.launch_apv_command("show ha status domain")
+        print(context)
+        pattern = 'Peer[\s]+unit:[\s]+(.+)\s(UP|DOWN)\s*'
+        peer_up_or_down_list = re.findall(pattern, context)
+        print(peer_up_or_down_list)
+
+        if not peer_up_or_down_list:
+            error_msg = "Error: cannot parse peer status in " + context
+            raise Exception(error_msg)
+
+        import sys
+        from datetime import datetime
+        file = open('/tmp/heartbeat_workaround.txt', 'a')
+
+        # Redirect sys.stdout to the file
+        sys.stdout = file
+
+        # Current time formatted as YYYY-MM-DD HH:MM:SS
+        timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
+        print(f"[{timestamp}] {peer_up_or_down_list[0]}")
+        sys.stdout = sys.__stdout__
+        # to solve ha flapping issue, we use container to store the recent five heartbeat results
+        # true failure happen <=> in the last five heartbeat check, all state is DOWN
+        self.peer_state_q.append(peer_up_or_down_list[0][1])
+        if self.peer_state_q.count("DOWN") == self.peer_state_q.maxlen:
+            # after checking recent five heartbeat results, the peer is truely DOWN
+            return False
+        elif self.peer_state_q.count("-") == self.peer_state_q.maxlen:
+            # user doesn't turn on ha functionality
+            return True
+        elif self.peer_state_q.count("UP") == self.peer_state_q.maxlen:
+            # after checking recent five heartbeat results, the peer is truely up
+            return True
+        return True  # the machine just booted, do nothing
+
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser(
+        description='Process optional name argument.')
+    parser.add_argument(
+        '-c', type=str, help='Enter 1 or 2: mode 1: start polling; mode 2: stop polling')
+    args = parser.parse_args()
+
+    apv_c = APVController()
+    print(apv_c.is_primary_alive())
+    # print(f"run command {args.c}")
Index: /branches/rel_apv_10_7/usr/click/tools/aws/aws_auth/AWSAuthController.py
===================================================================
--- /branches/rel_apv_10_7/usr/click/tools/aws/aws_auth/AWSAuthController.py	(revision 0)
+++ /branches/rel_apv_10_7/usr/click/tools/aws/aws_auth/AWSAuthController.py	(working copy)
@@ -0,0 +1,140 @@
+import subprocess
+import boto3
+from botocore.exceptions import NoCredentialsError
+from logger.ProxyAWSLogger import ProxyAWSLogger
+
+
+class AWSAuthController():
+    '''
+    A class to handle aws authentication for vAPV
+
+    Attributes:
+        output_format(str): The output format is default to json.
+    '''
+    output_format = 'json'
+
+    def __init__() -> None:
+        pass
+
+    @classmethod
+    def login(cls, access_key: str, secret_key: str, region: str) -> None:
+        '''
+        Authenticate using aws configure AWS CLI
+
+        Args:
+            access_key (str): AWS access key.
+            secret_key (str): AWS secret access key.
+            region (str): AWS resource region.
+
+        Returns:
+            None:
+        '''
+        command = ["aws", "configure"]
+        try:
+            subprocess.run(
+                command,
+                input=f"{access_key}\n{secret_key}\n"
+                f"{region}\n{cls.output_format}\n",
+                text=True,
+                capture_output=True,
+                check=True,
+            )
+            print("AWS CLI configured successfully!")
+        except Exception as e:
+            ProxyAWSLogger.error(str(e))
+
+    @classmethod
+    def logout(cls) -> None:
+        '''
+        Clear credential by setting all configuration to none.
+
+        Args:
+            None: This function does not take any arguments.
+
+        Returns:
+            None: This function does not return any value.
+        '''
+        print("logout")
+        try:
+            subprocess.run(
+                ["aws", "configure", "set", "aws_access_key_id", ""],
+                check=True
+            )
+            subprocess.run(
+                ["aws", "configure", "set", "aws_secret_access_key", ""],
+                check=True
+            )
+            subprocess.run(
+                ["aws", "configure", "set", "default.region", ""],
+                check=True
+            )
+            print("AWS credentials have been cleared.")
+        except subprocess.CalledProcessError as e:
+            print(f"Error clearing AWS credentials: {e}")
+
+    @classmethod
+    def get_login_info(cls) -> dict:
+        '''
+        Get the current log in information.
+
+        Args:
+            None: This function does not take any arguments.
+        Returns:
+            str: The dictionary of current log in information.
+        '''
+        res = {
+            "aws_access_key_id": None,
+            "aws_secret_access_key": None,
+            "region": None,
+        }
+        for key in res.keys():
+            try:
+                process = subprocess.run(
+                    ["aws", "configure", "get", key],
+                    text=True,
+                    capture_output=True,
+                    check=True,
+                )
+                res[key] = process.stdout.replace("\n", "")
+            except Exception as e:
+                print(str(e))
+
+        if res["aws_access_key_id"] or res["aws_access_key_id"]:
+            res["aws_access_key_id"] = cls._mask_credential(
+                res["aws_access_key_id"])
+            res["aws_secret_access_key"] = cls._mask_credential(
+                res["aws_secret_access_key"])
+
+        return res
+
+    @classmethod
+    def _mask_credential(cls, text: str) -> str:
+        '''
+        For security issue, mask the input text.
+
+        Returns:
+            str: a masked string of input text.
+        '''
+        number_show_char = 4
+        starts = "*"*7
+        return starts+text[-number_show_char:]
+
+    @classmethod
+    def is_authenticated(cls) -> bool:
+        '''
+        Try a simple ec2 API call (describe instances) to test if the credentials are working
+
+        Returns:
+            bool: is authenticated
+        '''
+        try:
+            ec2 = boto3.client('ec2')
+            ec2.describe_instances()
+            return True
+        except Exception as e:
+            print(str(e))
+            return False
+
+
+if __name__ == "__main__":
+    pass
Index: /branches/rel_apv_10_7/usr/click/tools/aws/aws_auth/__init__.py	(added)
===================================================================
--- /branches/rel_apv_10_7/usr/click/tools/aws/aws_auth/__init__.py	(revision 0)
+++ /branches/rel_apv_10_7/usr/click/tools/aws/aws_auth/__init__.py	(revision 0)
Index: /branches/rel_apv_10_7/usr/click/tools/aws/aws_eni/AWSENIConfigurator.py
===================================================================
--- /branches/rel_apv_10_7/usr/click/tools/aws/aws_eni/AWSENIConfigurator.py	(revision 0)
+++ /branches/rel_apv_10_7/usr/click/tools/aws/aws_eni/AWSENIConfigurator.py	(working copy)
@@ -0,0 +1,118 @@
+import json
+import os
+
+
+class AWSENIConfigurator():
+    '''
+    This is a class to handle the configuration of shifting.
+    Basically, configuration should include source eni id and
+    destination eni id.
+    '''
+    config_file_path = "/ca/conf/aws_eni_config.json"
+    max_number_of_conifg = 200
+
+    def __init__(self):
+        pass
+
+    @classmethod
+    def get_config(cls) -> dict:
+        '''
+        Read the config file based on config_file_path and return it
+        '''
+        config_dict = {}
+        if os.path.exists(cls.config_file_path):
+            with open(cls.config_file_path, 'r') as f:
+                data = f.read()
+            try:
+                config_dict = json.loads(data)
+            except Exception:
+                print(f"load data to json error.")
+        return config_dict
+
+    @classmethod
+    def _save_config(cls, ip_config_dict: dict) -> None:
+        ip_config_dict = dict(sorted(ip_config_dict.items()))
+        with open(cls.config_file_path, 'w') as json_file:
+            json.dump(ip_config_dict, json_file, indent=4)
+
+    @classmethod
+    def add_eni_config(cls, src_eni_id: str, dest_eni_id: str) -> None:
+        '''
+        Add a pair of eni configuration.
+
+        Args:
+            src_eni_id(str): The eni id of source eni
+            dest_eni_id(str): The eni id of destination eni
+
+        '''
+        ip_config_dict = cls.get_config()
+        for i in range(1, cls.max_number_of_conifg+1):
+            if str(i) not in ip_config_dict:
+                ip_config_dict[str(i)] = {
+                    "src_eni_id": src_eni_id,
+                    "dest_eni_id": dest_eni_id
+                }
+                break
+        cls._save_config(ip_config_dict)
+
+    @classmethod
+    def remove_eni_config(cls, index: str) -> None:
+        '''
+        Remove ENI configuration according to given index.
+
+        Args:
+            index(str): The index of ENI configuration needs to be removed.
+
+        Returns:
+            None: This function does not return any value.
+        '''
+
+        config = cls.get_config()
+        del config[index]
+        cls._save_config(config)
+
+    @classmethod
+    def clear_eni_config(cls) -> None:
+        '''
+        Remove ENI configuration according to given index.
+
+        Args:
+            index(str): The index of ENI configuration needs to be removed.
+
+        Returns:
+            None: This function does not return any value.
+        '''
+
+        cls._save_config({})
+
+    @classmethod
+    def get_config_file_path(cls) -> str:
+        return cls.config_file_path
+
+    @classmethod
+    def set_config_file_path(cls, config_file_path) -> None:
+        file_path = config_file_path
+        directory = os.path.dirname(file_path)
+
+        if not os.path.exists(directory):
+            # Create the directory if it does not exist
+            os.makedirs(directory, exist_ok=True)
+            print(f"Directory '{directory}' created.")
+
+        if not os.path.isfile(file_path):
+            # Create the file and write an empty dictionary
+            with open(file_path, "w") as file:
+                json.dump({}, file, indent=4)
+                print(f"File '{file_path}' created with an empty dictionary.")
+        else:
+            print(f"File '{file_path}' already exists.")
+
+        cls.config_file_path = config_file_path
+
+
+if __name__ == "__main__":
+    AWSENIConfigurator.set_config_file_path("/ca/conf/aws_eni_config.json")
+    AWSENIConfigurator.add_eni_config("src_eni_id", "dest_eni_id")
+
+    config = AWSENIConfigurator.get_config()
+    print(config)
Index: /branches/rel_apv_10_7/usr/click/tools/aws/aws_eni/AWSENIController.py
===================================================================
--- /branches/rel_apv_10_7/usr/click/tools/aws/aws_eni/AWSENIController.py	(revision 0)
+++ /branches/rel_apv_10_7/usr/click/tools/aws/aws_eni/AWSENIController.py	(working copy)
@@ -0,0 +1,118 @@
+import boto3
+from botocore.exceptions import ClientError
+from logger.ProxyAWSLogger import ProxyAWSLogger
+
+
+class AWSENIController():
+    '''
+    AWSENIController is used to manipulate the network interface.
+    '''
+    def __init__():
+        pass
+
+    @classmethod
+    def transfer_secondary_ip(cls, src_eni_id: str, dest_eni_id: str) -> None:
+        '''
+        Transfer all secondary ip from source ENI to target ENI given their IDs.
+
+        Args:
+            src_eni_id(str): The ENI id of source ENI.
+            dest_eni_id(str): The ENI id of destination ENI.
+        '''
+        ec2 = boto3.client(
+            "ec2",
+        )
+        response = ec2.describe_network_interfaces(
+            NetworkInterfaceIds=[src_eni_id])
+        eni = response["NetworkInterfaces"][0]
+        for ip_pair in eni["PrivateIpAddresses"]:
+            if not ip_pair["Primary"]:
+                public_ip = ip_pair.get(
+                    "Association", {}).get("PublicIp", None)
+                private_ip = ip_pair["PrivateIpAddress"]
+                allocation_id = ip_pair.get(
+                    "Association", {}).get("AllocationId", None)
+                # transfer the pair of public ip and private ip
+                ProxyAWSLogger.info(
+                    f'try to transfer ip pair with private {private_ip}')
+
+                if public_ip:
+                    # transfer public ip
+                    try:
+                        cls._transfer_secondary_private_ip(
+                            src_eni_id, dest_eni_id, private_ip)
+                        ec2.associate_address(
+                            NetworkInterfaceId=dest_eni_id,
+                            AllocationId=allocation_id,
+                            PrivateIpAddress=private_ip,
+                        )
+                        ProxyAWSLogger.info(
+                            f'Succeed to transfer ip pair with private {private_ip}')
+                    except ClientError as e:
+                        if e.response["Error"]["Code"] == "PrivateIpAddressLimitExceeded":
+                            ProxyAWSLogger.error(
+                                f"Fail to tranfer ip pair with "
+                                f"{private_ip}: {str(e)}"
+                            )
+                            # recover
+                            ec2.assign_private_ip_addresses(
+                                NetworkInterfaceId=src_eni_id,
+                                PrivateIpAddresses=[private_ip],
+                            )
+                            print(src_eni_id, allocation_id, private_ip)
+                            ec2.associate_address(
+                                NetworkInterfaceId=src_eni_id,
+                                AllocationId=allocation_id,
+                                PrivateIpAddress=private_ip,
+                            )
+                        else:
+                            ProxyAWSLogger.error(f"{e}")
+                    except Exception as e:
+                        ProxyAWSLogger.error(f"Fail to tranfer ip pair with "
+                                            "{private_ip}: {str(e)}")
+                else:
+                    # transfer the private ip
+                    try:
+                        cls._transfer_secondary_private_ip(
+                            src_eni_id, dest_eni_id, private_ip)
+                        ProxyAWSLogger.info(
+                            f'Succeed to transfer ip pair with private {private_ip}')
+
+                    except ClientError as e:
+                        if e.response["Error"]["Code"] == "PrivateIpAddressLimitExceeded":
+                            ProxyAWSLogger.error(
+                                f"Fail to tranfer ip pair with "
+                                f"{private_ip}: {str(e)}"
+                            )
+                            # recover
+                            ec2.assign_private_ip_addresses(
+                                NetworkInterfaceId=src_eni_id,
+                                PrivateIpAddresses=[private_ip],
+                            )
+                            print(src_eni_id, allocation_id, private_ip)
+                        else:
+                            ProxyAWSLogger.error(f"{e}")
+                    except Exception as e:
+                        ProxyAWSLogger.error(f"Fail to tranfer ip pair with "
+                                            "{ private_ip}: {str(e)}")
+
+    @classmethod
+    def _transfer_secondary_private_ip(cls, src_eni_id: str, dest_eni_id: str, private_ip: str):
+        ec2 = boto3.client(
+            "ec2",
+        )
+        ec2.unassign_private_ip_addresses(
+            NetworkInterfaceId=src_eni_id,
+            PrivateIpAddresses=[private_ip],
+        )
+        ec2.assign_private_ip_addresses(
+            NetworkInterfaceId=dest_eni_id,
+            PrivateIpAddresses=[private_ip],
+        )
+
+
+if __name__ == "__main__":
+    source_eni = "eni-06dca0e528c346e5b"  # Replace with your source ENI ID
+    target_eni = "eni-0cf2efac34b3b81cd"  # Replace with your target ENI ID
+    AWSENIController.transfer_secondary_ip(target_eni, source_eni)
+    # AWSENIController.transfer_secondary_ip(source_eni, target_eni)
Index: /branches/rel_apv_10_7/usr/click/tools/aws/aws_eni/__init__.py	(added)
===================================================================
--- /branches/rel_apv_10_7/usr/click/tools/aws/aws_eni/__init__.py	(revision 0)
+++ /branches/rel_apv_10_7/usr/click/tools/aws/aws_eni/__init__.py	(revision 0)
Index: /branches/rel_apv_10_7/usr/click/tools/aws/logger/AWSLogger.py
===================================================================
--- /branches/rel_apv_10_7/usr/click/tools/aws/logger/AWSLogger.py	(revision 0)
+++ /branches/rel_apv_10_7/usr/click/tools/aws/logger/AWSLogger.py	(working copy)
@@ -0,0 +1,168 @@
+import logging
+from logging.handlers import RotatingFileHandler
+import json
+from abc import ABC, abstractmethod
+import os
+
+
+class AbstractAWSLogger(ABC):
+    @classmethod
+    @abstractmethod
+    def set_log_path(cls, log_path: str) -> None:
+        cls.log_path = log_path
+
+    @classmethod
+    @abstractmethod
+    def debug(cls, message: str) -> None:
+        pass
+
+    @classmethod
+    @abstractmethod
+    def info(cls, message: str) -> None:
+        pass
+
+    @classmethod
+    @abstractmethod
+    def warning(cls, message: str) -> None:
+        pass
+
+    @classmethod
+    @abstractmethod
+    def error(cls, message: str) -> None:
+        pass
+
+    @classmethod
+    @abstractmethod
+    def _load_config(file_path):
+        pass
+
+
+log_levels = {
+    "debug": logging.DEBUG,
+    "info": logging.INFO,
+    "warning": logging.WARNING,
+    "error": logging.ERROR,
+}
+
+
+class AWSLogger(AbstractAWSLogger):
+    '''
+    This class is used to log the AWS event.
+    We use the python build-in logging under the hood to implement this class.
+    This class have several class method to log the message.
+    There is no interface to configure this class, that is,
+    all the configurations are set inside the class.
+    The AWSLogger have four levels of severity, debug, info,
+    warning and error which have the same name of class method.
+    '''
+    # is there a way to make the initilization clean?
+    def _load_config(file_path):
+        try:
+            with open(file_path, 'r') as config_file:
+                config = json.load(config_file)
+                return config
+        except FileNotFoundError:
+            print(f"Error: The file {file_path} was not found.")
+        except json.JSONDecodeError:
+            print(f"Error: The file {file_path} is not a valid JSON file.")
+
+    current_module_directory = os.path.dirname(os.path.abspath(__file__))
+    config_file_path = os.path.join(current_module_directory, "config.json")
+    config = _load_config(config_file_path)
+    log_path = config["log_path"]
+    # log_path = "./azure_ha.log" # for developing purpose
+    log_format = config["log_format"]
+    max_size_log_file = config["max_size_log_file"]  # MB
+
+    # logger
+    logger = logging.getLogger("AWSLogger")
+    log_levels.get(config["level_of_severity"].lower(), logging.DEBUG)
+    logger.setLevel(log_levels.get(
+        config["level_of_severity"].lower(), logging.DEBUG))
+
+    # log handler
+    file_handler = RotatingFileHandler(
+        log_path, maxBytes=max_size_log_file*1024*1024, backupCount=1)
+    logger.addHandler(file_handler)
+
+    # log formatter
+    file_formatter = logging.Formatter(log_format, datefmt=config["datefmt"])
+    file_handler.setFormatter(file_formatter)
+
+    def __init__():
+        pass
+
+    @classmethod
+    def set_log_path(cls, log_path: str) -> None:
+        cls.log_path = log_path
+
+    @classmethod
+    def debug(cls, message: str) -> None:
+        cls.logger.debug(message)
+
+    @classmethod
+    def info(cls, message: str) -> None:
+        cls.logger.info(message)
+
+    @classmethod
+    def warning(cls, message: str) -> None:
+        cls.logger.warning(message)
+
+    @classmethod
+    def error(cls, message: str) -> None:
+        cls.logger.error(message)
+
+    @classmethod
+    def reload_config(cls) -> None:
+
+        try:
+            with open(cls.config_file_path, 'r') as config_file:
+                config = json.load(config_file)
+        except FileNotFoundError:
+            print(f"Error: The file {config_file} was not found.")
+        except json.JSONDecodeError:
+            print(f"Error: The file {config_file} is not a valid JSON file.")
+
+        log_path = config["log_path"]
+        # log_path = "./azure_ha.log" # for developing purpose
+        log_format = config["log_format"]
+        max_size_log_file = config["max_size_log_file"]  # MB
+
+        # logger
+        logger = logging.getLogger("AWSLogger")
+        log_levels.get(config["level_of_severity"].lower(), logging.DEBUG)
+        logger.setLevel(log_levels.get(
+            config["level_of_severity"].lower(), logging.DEBUG))
+
+        # log handler
+        # Remove all existing handlers
+        # Create a copy of the list for safe iteration
+        for handler in logger.handlers[:]:
+            logger.removeHandler(handler)
+        file_handler = RotatingFileHandler(
+            log_path, maxBytes=max_size_log_file*1024*1024, backupCount=1)
+
+        # log formatter
+        file_formatter = logging.Formatter(
+            log_format, datefmt=config["datefmt"])
+        file_handler.setFormatter(file_formatter)
+
+        logger.addHandler(file_handler)
+
+
+if __name__ == "__main__":
+    # test code
+
+    AWSLogger.debug("This is a debug message")
+    AWSLogger.info("This is an info message")
+    AWSLogger.warning("This is a warning message")
+    AWSLogger.error("This is a error message")
+    mb = 1
+    for i in range(mb*5000):
+        AWSLogger.reload_config()
+        AWSLogger.debug(f"This is a debug message {i}")
+        AWSLogger.info(f"This is an info message {i}")
+        AWSLogger.warning(f"This is a warning message {i}")
+        AWSLogger.error(f"This is a error message {i}")
+        import time
+        time.sleep(1)
Index: /branches/rel_apv_10_7/usr/click/tools/aws/logger/ProxyAWSLogger.py
===================================================================
--- /branches/rel_apv_10_7/usr/click/tools/aws/logger/ProxyAWSLogger.py	(revision 0)
+++ /branches/rel_apv_10_7/usr/click/tools/aws/logger/ProxyAWSLogger.py	(working copy)
@@ -0,0 +1,191 @@
+
+import os
+import json
+from logger.AWSLogger import AbstractAWSLogger
+from logger.AWSLogger import AWSLogger
+
+
+class ProxyAWSLogger(AbstractAWSLogger):
+    '''
+    This class is designed using the proxy pattern,
+    a structural design pattern.
+    Because there is a requirement of dynamically changing
+    the level of severity,
+    we use a proxy to determine if the configuration file is changed or not in
+    order to keep the AWSLogger class pure.
+    '''
+    config_modified_indicator_file = os.path.join(
+        AWSLogger.current_module_directory, 'config_modified.txt')
+    with open(AWSLogger.config_file_path, 'r') as config_file:
+        config = json.load(config_file)
+    is_logger_on = config["is_logger_on"]
+
+    @classmethod
+    def get_config(cls) -> dict:
+        '''THe usage of this method refers to the set_config()'''
+        try:
+            with open(AWSLogger.config_file_path, 'r') as config_file:
+                config = json.load(config_file)
+                return config
+        except FileNotFoundError:
+            AWSLogger.error(f"Error: The file {config_file} was not found.")
+        except json.JSONDecodeError:
+            AWSLogger.error(f"Error: The file {config_file} \
+                            is not a valid JSON file.")
+
+    @classmethod
+    def set_config(cls, config: dict) -> None:
+        '''The suggested method to modify configuration file is to use
+        get_config() method
+        to get the original configuration dictionary, modify
+        the dictionary objecct, and invoke set_config() with
+        arugment of modified dictionary object
+        algo:
+        1. take input to override the original config dictionary.
+        2. write the file.
+        3. set config file modified indictor
+        '''
+        # AWSLogger.info(f"setting new config: {config}")
+        ori_config = cls.get_config()
+        for key in ori_config.keys():
+            ori_config[key] = config[key]
+        with open(AWSLogger.config_file_path, "w") as json_file:
+            json.dump(ori_config, json_file, indent=4)
+        with open(cls.config_modified_indicator_file, 'w'):
+            pass
+
+    @classmethod
+    def is_config_modified(cls) -> bool:
+        '''This method is used to check if the configuration file
+        is modified or not.
+        The alogrithem to do that is check if there is the modified
+        file existed.
+        If the file existed, the configuration file is modified;
+        otherwise, the configuration is unchaged.
+        '''
+        return os.path.exists(cls.config_modified_indicator_file)
+
+    @classmethod
+    def _refresh_config(cls) -> None:
+        if cls.is_config_modified():
+            AWSLogger.reload_config()
+            with open(AWSLogger.config_file_path, 'r') as config_file:
+                config = json.load(config_file)
+            cls.is_logger_on = config["is_logger_on"]
+            # delete config file changed indicator
+            os.remove(cls.config_modified_indicator_file)
+
+    @classmethod
+    def set_level(cls, level: str) -> None:
+        config = cls.get_config()
+        config["level_of_severity"] = level
+        cls.set_config(config)
+
+    @classmethod
+    def turn_on(cls) -> None:
+        '''This on off functionality is on off all the invoking debug, info,
+        warning, and error method using ProxyAWSLogger class.
+        That is, if the client directly use AWSLogger, the message is still be
+        logger. However, it's not recommanded'''
+        config = cls.get_config()
+        config["is_logger_on"] = True
+        cls.set_config(config)
+        cls._refresh_config()
+        # cls.is_logger_on = True
+
+    @classmethod
+    def turn_off(cls) -> None:
+        '''This on off functionality is on off all the invoking debug, info,
+        warning, and error method using ProxyAWSLogger class.
+        That is, if the client directly use AWSLogger, the message is still
+        be logger. However, it's not recommanded'''
+        config = cls.get_config()
+        config["is_logger_on"] = False
+        cls.set_config(config)
+        cls._refresh_config()
+        # cls.is_logger_on = False
+
+    @classmethod
+    def get_log(cls) -> str:
+        '''return a string of content of log file'''
+        config = cls.get_config()
+        with open(config["log_path"], 'r', encoding='utf-8') as file:
+            content = file.read()
+        return content
+
+    @classmethod
+    def get_is_logger_on(cls) -> bool:
+        '''This is used to check if logger is on or not
+        return True if logger is on
+        return False if logger is off
+        '''
+        config = cls.get_config()
+        return config["is_logger_on"]
+
+    @classmethod
+    def get_Logger_level_state(cls) -> str:
+        '''This is used to check if logger level is debug, info,
+        warning, and error
+        return a string of log severity
+        '''
+        config = cls.get_config()
+        return config["level_of_severity"]
+
+    @classmethod
+    def get_log_file_path(cls) -> str:
+        config = cls.get_config()
+        return config["log_path"]
+
+    @classmethod
+    def debug(cls, message: str) -> None:
+        cls._refresh_config()
+        if cls.is_logger_on:
+            AWSLogger.debug(message)
+
+    @classmethod
+    def info(cls, message: str) -> None:
+        cls._refresh_config()
+        if cls.is_logger_on:
+            AWSLogger.info(message)
+
+    @classmethod
+    def warning(cls, message: str) -> None:
+        cls._refresh_config()
+        if cls.is_logger_on:
+            AWSLogger.warning(message)
+
+    @classmethod
+    def error(cls, message: str) -> None:
+        cls._refresh_config()
+        if cls.is_logger_on:
+            AWSLogger.error(message)
+
+
+if __name__ == "__main__":
+    # test code
+
+    import os
+    # Get the location of the current module
+    current_module_directory = os.path.dirname(os.path.abspath(__file__))
+
+    ProxyAWSLogger.debug("This is a debug message")
+    ProxyAWSLogger.info("This is an info message")
+    ProxyAWSLogger.warning("This is a warning message")
+    ProxyAWSLogger.error("This is a error message")
+    mb = 5
+    for i in range(mb*5000):
+        ProxyAWSLogger.debug(f"This is a debug message {i}")
+        ProxyAWSLogger.info(f"This is an info message {i}")
+        ProxyAWSLogger.warning(f"This is a warning message {i}")
+        ProxyAWSLogger.error(f"This is a error message {i}")
+        import time
+        if i % 3 == 0:
+            # test config file changing
+            cur_config = ProxyAWSLogger.get_config()
+            cur_config["level_of_severity"] = (
+                "info"
+                if cur_config["level_of_severity"] == "debug" else "debug"
+            )
+            ProxyAWSLogger.set_config(cur_config)
+            print("change level")
+        time.sleep(2)
Index: /branches/rel_apv_10_7/usr/click/tools/aws/logger/__init__.py	(added)
===================================================================
--- /branches/rel_apv_10_7/usr/click/tools/aws/logger/__init__.py	(revision 0)
+++ /branches/rel_apv_10_7/usr/click/tools/aws/logger/__init__.py	(revision 0)
Index: /branches/rel_apv_10_7/usr/click/tools/aws/logger/config.json
===================================================================
--- /branches/rel_apv_10_7/usr/click/tools/aws/logger/config.json	(revision 0)
+++ /branches/rel_apv_10_7/usr/click/tools/aws/logger/config.json	(working copy)
@@ -0,0 +1,8 @@
+{
+    "log_path": "/var/crash/aws_ha.log",
+    "log_format": "[%(asctime)s] - [%(levelname)s] %(message)s",
+    "max_size_log_file": 0,
+    "level_of_severity": "info",
+    "datefmt": "%Y-%m-%dT%H:%M:%S",
+    "is_logger_on": true
+}
\ No newline at end of file
