Index: /branches/amp_3_7
===================================================================
--- /branches/amp_3_7	(revision 2461)
+++ /branches/amp_3_7	(working copy)

Property changes on: .
___________________________________________________________________
Added: svn:ignore
## -0,0 +1 ##
+Makefile amp.spec scripts/buildenv.ks
Index: /branches/amp_3_7/amp.spec
===================================================================
--- /branches/amp_3_7/amp.spec	(revision 2461)
+++ /branches/amp_3_7/amp.spec	(working copy)
@@ -201,6 +201,7 @@
 install -Dm 0755 scripts/check_crontab_add.py %{buildroot}/ca/bin/check_crontab_add.py
 install -Dm 0755 scripts/clean_oper_log.py %{buildroot}/ca/bin/clean_oper_log.py
 cp lib/composer/composer-2.5.0.2.tgz %{buildroot}/ca/etc/
+mkdir -p /ca/webui/htdocs/new/src/hive/media/docs
 
 %files
 %defattr(-,root,root,-)
Index: /branches/amp_3_7/src/webui/webui/htdocs/new/src/djproject/urls.py
===================================================================
--- /branches/amp_3_7/src/webui/webui/htdocs/new/src/djproject/urls.py	(revision 2469)
+++ /branches/amp_3_7/src/webui/webui/htdocs/new/src/djproject/urls.py	(working copy)
@@ -13,6 +13,7 @@
 from hive.storage import storage_mangement
 from hive.log_location import handle_log_location_app
 from hive.llb_stats import handle_llb_stats_req
+from hive.report.generate_report import handle_report_generation
 
 js_info_dict = {
     #'packages': ('your.app.package',),
@@ -60,6 +61,7 @@
     url(r'^composer_status/(?P<app>\w+)', composer_status),
     url(r'^composer_query$', composer_query),
     url(r'^llb/(?P<path>.*)$', handle_llb_stats_req),
+     url(r'^report/(?P<app>\w+)/(?P<path>.*)$', handle_report_generation),
     url(r'^log/(?P<app>\w+)$', handle_log_location_app),
     url(r'^real_service$', real_service),
     url(r'^rs_block$', rs_block),
Index: /branches/amp_3_7/src/webui/webui/htdocs/new/src/hive/db/llb_stats_queries.py
===================================================================
--- /branches/amp_3_7/src/webui/webui/htdocs/new/src/hive/db/llb_stats_queries.py	(revision 2469)
+++ /branches/amp_3_7/src/webui/webui/htdocs/new/src/hive/db/llb_stats_queries.py	(working copy)
@@ -74,8 +74,8 @@
                 http_client.close()
 
     @staticmethod
-    def get_llb_stats_query_str(request):
-        """Constructs the query for LLB stats"""
+    def get_llb_stats_data(agent_host):
+        """Returns the LLB stats data"""
         req_dict = {
             "url": LLBStatsDB.BASE_URL,
             "path": "db=composer&epoch=ms",
@@ -90,29 +90,23 @@
             'last(linkConn) AS linkConn, last(linkHits) AS linkHits FROM llbStats WHERE time > now()-20s '
             'GROUP BY agent_host, linkName, linkStatus FILL(0);')
 
-        if 'query' in request:
-            query_params = request.get('query', {})
-            agent_host = query_params.get('agent_host')
-            if agent_host:
-                query_string = (
-                    'SELECT LAST(linkGateway) AS linkGateway, last(linkThresh) AS linkThresh, last(linkUsage) AS linkUsage, '
-                    'last(linkBandwidIn) * 8 AS received, last(linkBandwidOut) * 8 AS sent, last(linkConn) AS linkConn, '
-                    'last(linkHits) AS linkHits FROM llbStats WHERE agent_host =~ \'{}\' '
-                    'AND time > now()-20s GROUP BY agent_host, linkName, linkStatus FILL(0);'
-                ).format(agent_host)
-            else:
-                oper_log('error', 'system',
-                         "Query must contain only agent_host details. Please specify agent_host in the query.")
-                raise ge.GenericError(400,
-                                      "Query must contain only agent_host details. Please specify agent_host in the query.")
+        if agent_host:
+            query_string = (
+                'SELECT LAST(linkGateway) AS linkGateway, last(linkThresh) AS linkThresh, last(linkUsage) AS linkUsage, '
+                'last(linkBandwidIn) * 8 AS received, last(linkBandwidOut) * 8 AS sent, last(linkConn) AS linkConn, '
+                'last(linkHits) AS linkHits FROM llbStats WHERE agent_host =~ \'{}\' '
+                'AND time > now()-20s GROUP BY agent_host, linkName, linkStatus FILL(0);'
+            ).format(agent_host)
 
         query_string = LLBStatsDB.format_query_string(query_string)
         req_dict["body"] = 'q=' + query_string
-        return req_dict
+        response = LLBStatsDB.execute_db_query(req_dict)
+
+        return response
 
     @staticmethod
-    def get_llb_monitoring_query_str(request):
-        """Constructs the query for LLB monitoring data"""
+    def get_llb_monitoring_data(agent_host):
+        """Returns the LLB monitoring data"""
         req_dict = {
             "url": LLBStatsDB.BASE_URL,
             "path": "db=composer&epoch=ms",
@@ -130,7 +124,7 @@
                         'received, last(linkBandwidOut) * 8 as  sent from llbStats group by linkName, agent_host) '
                         'where time > now()-20s FILL(0);')
 
-        if 'query' in request and 'agent_host' in request['query']:
+        if agent_host:
             query_string = ('SELECT TOP(hits, 5) as top_hits, linkName, agent_host FROM (SELECT MAX(linkHits)-MIN('
                             'linkHits) AS hits FROM llbStats GROUP BY linkName, agent_host) WHERE agent_host =~ {} '
                             'and time >now()-20s;'
@@ -140,16 +134,17 @@
                             'select last(linkBandwidIn) * 8 + last(linkBandwidOut) * 8 as total, '
                             'last(linkBandwidIn) * 8 as received, last(linkBandwidOut) * 8 as  sent from llbStats GROUP'
                             'BY linkName, agent_host) WHERE agent_host =~ {} and time > now()-20s FILL(0);'
-                            ).format(request['query']['agent_host'], request['query']['agent_host'],
-                                     request['query']['agent_host'])
+                            ).format(agent_host, agent_host, agent_host)
 
         query_string = LLBStatsDB.format_query_string(query_string)
         req_dict["body"] = 'q=' + query_string
-        return req_dict
+        response = LLBStatsDB.execute_db_query(req_dict)
+
+        return response
 
     @staticmethod
-    def get_llb_historical_data_str(request):
-        """Constructs the query for LLB monitoring data"""
+    def get_llb_historical_data(from_time, to_time, link_name):
+        """Returns the LLB monitoring data"""
         req_dict = {
             "url": LLBStatsDB.BASE_URL,
             "path": "db=composer&epoch=ms",
@@ -157,16 +152,6 @@
             "body": {},
             "config": LLBStatsDB.CONTENT_TYPE
         }
-        if 'query' in request and 'from_time' in request['query'] and 'to_time' in request['query'] and 'link_name' in \
-                request['query']:
-            from_time = request['query'].get('from_time', '')
-            to_time = request['query'].get('to_time', '')
-            link_name = request['query'].get('link_name', '')
-        else:
-            oper_log('error', 'system',
-                     "Query cannot be empty. Please specify from_time and to_time and link_name in the query.")
-            raise ge.GenericError(400, "Query cannot be empty. Please specify from_time and to_time and link_name in "
-                                       "the query.")
 
         # time_interval specifies the frequency at which data points should be generated.
         time_interval = LLBStatsDB.get_time_interval(from_time, to_time)
@@ -177,35 +162,96 @@
 
         # Ensure the to_time is properly stripped and lowercased for comparison.
         to_time = to_time.strip().lower()
-        if isinstance(to_time, int):
 
-            query_string = (
-                "SELECT mean(linkBandwidIn) AS avgBandwidIn, mean(linkBandwidOut) AS avgBandwidOut, "
-                "mean(linkUsage) AS avgLinkUsage, mean(linkConn) AS avgLinkConn, mean(linkHits) AS avgLinkHits FROM "
-                "llbStats WHERE time > {} and time < {} and linkName = '{}' GROUP BY time({}), agent_host, linkName, linkStatus FILL(0);"
-            ).format(from_time, to_time, link_name, time_interval)
+        if link_name:
+            if isinstance(to_time, int):
+                query_string = (
+                    "SELECT mean(linkBandwidIn) AS avgBandwidIn, mean(linkBandwidOut) AS avgBandwidOut, "
+                    "mean(linkUsage) AS avgLinkUsage, mean(linkConn) AS avgLinkConn, mean(linkHits) AS avgLinkHits FROM "
+                    "llbStats WHERE time > {} and time < {} and linkName = '{}' GROUP BY time({}), agent_host, linkName, linkStatus FILL(0);"
+                ).format(from_time, to_time, link_name, time_interval)
+            else:
+                from_time = LLBStatsDB.get_time_in_influx_format(from_time)
+                query_string = (
+                    "SELECT mean(linkBandwidIn) AS avgBandwidIn, mean(linkBandwidOut) AS avgBandwidOut, "
+                    "mean(linkUsage) AS avgLinkUsage, mean(linkConn) AS avgLinkConn, mean(linkHits) AS avgLinkHits FROM "
+                    "llbStats WHERE time > {} and linkName = '{}' GROUP BY time({}), agent_host, linkName, linkStatus FILL(0);"
+                ).format(from_time, link_name, time_interval)
+        else:
+            if isinstance(to_time, int):
+                query_string = (
+                    "SELECT mean(linkBandwidIn) AS avgBandwidIn, mean(linkBandwidOut) AS avgBandwidOut, "
+                    "mean(linkUsage) AS avgLinkUsage, mean(linkConn) AS avgLinkConn, mean(linkHits) AS avgLinkHits FROM "
+                    "llbStats WHERE time > {} and time < {} GROUP BY time({}), agent_host, linkName, linkStatus FILL(0);"
+                ).format(from_time, to_time, time_interval)
+            else:
+                from_time = LLBStatsDB.get_time_in_influx_format(from_time)
+                query_string = (
+                    "SELECT mean(linkBandwidIn) AS avgBandwidIn, mean(linkBandwidOut) AS avgBandwidOut, "
+                    "mean(linkUsage) AS avgLinkUsage, mean(linkConn) AS avgLinkConn, mean(linkHits) AS avgLinkHits FROM "
+                    "llbStats WHERE time > {} GROUP BY time({}), agent_host, linkName, linkStatus FILL(0);"
+                ).format(from_time, time_interval)
+
+        query_string = LLBStatsDB.format_query_string(query_string)
+        req_dict["body"] = 'q=' + query_string
+        response = LLBStatsDB.execute_db_query(req_dict)
+
+        return response
 
+    @staticmethod
+    def get_llb_summary_data(from_time, to_time):
+        """Constructs the query for LLB monitoring data"""
+        req_dict = {
+            "url": LLBStatsDB.BASE_URL,
+            "path": "db=composer&epoch=ms",
+            "method": "POST",
+            "body": {},
+            "config": LLBStatsDB.CONTENT_TYPE
+        }
 
+        if isinstance(to_time, int):
+            query_string = ('select mean(linkHits) AS avgLinkHits, mean(conn) AS avgLinkConn, mean(received) AS '
+                            'avgBandwidIn, mean(sent) AS avgBandwidOut, mean(linkUsage) AS avgLinkUsage '
+                            'FROM llbStats WHERE time > {} and time < {} GROUP BY linkName FILL(0);').format(from_time,
+                                                                                                             to_time)
         else:
             from_time = LLBStatsDB.get_time_in_influx_format(from_time)
-            query_string = (
-                "SELECT mean(linkBandwidIn) AS avgBandwidIn, mean(linkBandwidOut) AS avgBandwidOut, "
-                "mean(linkUsage) AS avgLinkUsage, mean(linkConn) AS avgLinkConn, mean(linkHits) AS avgLinkHits FROM "
-                "llbStats WHERE time > {} and linkName = '{}' GROUP BY time({}), agent_host, linkName, linkStatus FILL(0);"
-            ).format(from_time, link_name, time_interval)
+            query_string = ('select mean(linkHits) AS avgLinkHits, mean(conn) AS avgLinkConn, mean(received) AS '
+                            'avgBandwidIn, mean(sent) AS avgBandwidOut, mean(linkUsage) AS avgLinkUsage '
+                            'FROM llbStats WHERE time > {} GROUP BY linkName FILL(0);').format(from_time)
 
         query_string = LLBStatsDB.format_query_string(query_string)
         req_dict["body"] = 'q=' + query_string
+        response = LLBStatsDB.execute_db_query(req_dict)
 
-        return req_dict
+        return response
 
     @staticmethod
     def get_time_interval(from_time, to_time):
-        curr_time_in_ms = LLBStatsDB.get_curr_sys_time()
+        from_time_in_int, to_time_in_int = LLBStatsDB.get_time_range(from_time, to_time)
+
+        # Calculate the absolute difference in time
+        diff_time = abs(to_time_in_int - from_time_in_int)
 
+        # If there's a positive time difference, calculate the interval
+        if diff_time > 0:
+            diff_hours = diff_time / (1000 * 60 * 60)  # Convert ms to hours
+
+            if diff_hours > 24:
+                # More than 24 hours, divide by 96 for 15 minute intervals
+                return LLBStatsDB.convert_ms_to_influxdb_time(abs(diff_time / 96))
+            else:
+                # Less than 24 hours, divide by 24 for hourly intervals
+                return LLBStatsDB.convert_ms_to_influxdb_time(abs(diff_time / 24))
+        else:
+            # Return -1 for invalid or zero time difference
+            return -1
+
+    @staticmethod
+    def get_time_range(from_time, to_time):
+        curr_time_in_ms = LLBStatsDB.get_curr_sys_time()
         # Handle from_time (same logic as before)
         from_time_in_int = LLBStatsDB.get_time_in_ms_for_str(from_time)
-
         if from_time_in_int == -1:
             try:
                 from_time_in_int = int(from_time)  # Try to convert to integer if it's in epoch ms format
@@ -214,7 +260,6 @@
                 raise ge.GenericError(400, "From time is not specified in correct format.")
         else:
             from_time_in_int = curr_time_in_ms - from_time_in_int
-
         if to_time == "now":
             to_time_in_int = curr_time_in_ms  # If "now", use current time
         else:
@@ -226,24 +271,8 @@
                     oper_log('error', 'system', "To time is not specified in correct format.")
                     raise ge.GenericError(400, "To time is not specified in correct format.")
             else:
-                from_time_in_int = curr_time_in_ms - from_time_in_int
-
-        # Calculate the absolute difference in time
-        diff_time = abs(to_time_in_int - from_time_in_int)
-
-        # If there's a positive time difference, calculate the interval
-        if diff_time > 0:
-            diff_hours = diff_time / (1000 * 60 * 60)  # Convert ms to hours
-
-            if diff_hours > 24:
-                # More than 24 hours, divide by 96 for 15 minute intervals
-                return LLBStatsDB.convert_ms_to_influxdb_time(abs(diff_time / 96))
-            else:
-                # Less than 24 hours, divide by 24 for hourly intervals
-                return LLBStatsDB.convert_ms_to_influxdb_time(abs(diff_time / 24))
-        else:
-            # Return -1 for invalid or zero time difference
-            return -1
+                to_time_in_int = curr_time_in_ms - from_time_in_int
+        return from_time_in_int, to_time_in_int
 
     @staticmethod
     def get_time_in_ms_for_str(from_time):
Index: /branches/amp_3_7/src/webui/webui/htdocs/new/src/hive/llb_stats.py
===================================================================
--- /branches/amp_3_7/src/webui/webui/htdocs/new/src/hive/llb_stats.py	(revision 2469)
+++ /branches/amp_3_7/src/webui/webui/htdocs/new/src/hive/llb_stats.py	(working copy)
@@ -1,3 +1,5 @@
+import os
+
 from django.http import HttpResponse
 import json
 from hive.db.llb_stats_queries import LLBStatsDB
@@ -30,55 +32,68 @@
 
 
 def get_llb_stats(request):
+    """ Fetch data for LLB stats data """
+    agent_host = None
     req = json.loads(request.body)
-    req_dict = LLBStatsDB.get_llb_stats_query_str(req)
-    response = LLBStatsDB.execute_db_query(req_dict)
-
-    if not response:
-        return []
-
-    if isinstance(response, str):
-        response = json.loads(response)
+    if 'query' in req:
+        if 'agent_host' in req['query']:
+            agent_host = req['query']['agent_host']
 
-    response_data = reformat_data_from_db(response, 'stats')
+        else:
+            oper_log('error', 'system', "Query must contain only agent_host details. Please specify agent_host in the "
+                                        "query.")
+            raise ge.GenericError(400, "Query must contain only agent_host details. Please specify agent_host in the "
+                                       "query.")
 
-    if response_data:
-        return HttpResponse(json.dumps(response_data), content_type='application/json')
-    else:
-        return HttpResponse(json.dumps(response), content_type='application/json')
+    response = LLBStatsDB.get_llb_stats_data(agent_host)
+    return get_formatted_response(response, 'stats')
 
 
 def get_monitoring_data(request):
+    """ Fetch data for LLB data for monitoring page """
     req = json.loads(request.body)
-    req_dict = LLBStatsDB.get_llb_monitoring_query_str(req)
-    response = LLBStatsDB.execute_db_query(req_dict)
-    if not response:
-        return []
-
-    if isinstance(response, str):
-        response = json.loads(response)
+    agent_host = None
+    if 'query' in req:
+        if 'agent_host' in req['query']:
+            agent_host = req['query']['agent_host']
 
-    response_data = reformat_data_from_db(response, 'monitoring_data')
+        else:
+            oper_log('error', 'system', "Query must contain only agent_host details. Please specify agent_host in the "
+                                        "query.")
+            raise ge.GenericError(400, "Query must contain only agent_host details. Please specify agent_host in the "
+                                       "query.")
 
-    if response_data:
-        return HttpResponse(json.dumps(response_data), content_type='application/json')
-    else:
-        return HttpResponse(json.dumps(response), content_type='application/json')
+    response = LLBStatsDB.get_llb_monitoring_data(agent_host)
+    return get_formatted_response(response, 'monitoring_data')
 
 
 def get_llb_historical_data(request):
+    """ Fetch data for LLB graphs for a particular time period"""
     req = json.loads(request.body)
-    req_dict = LLBStatsDB.get_llb_historical_data_str(req)
-    response = LLBStatsDB.execute_db_query(req_dict)
 
-    # Handle cases where response is None or not JSON
+    if 'query' in req and 'from_time' in req['query'] and 'to_time' in req['query'] and 'link_name' in \
+            req['query']:
+        from_time = req['query'].get('from_time', '')
+        to_time = req['query'].get('to_time', '')
+        link_name = req['query'].get('link_name', '')
+    else:
+        oper_log('error', 'system',
+                 "Query cannot be empty. Please specify from_time and to_time and link_name in the query.")
+        raise ge.GenericError(400, "Query cannot be empty. Please specify from_time and to_time and link_name in "
+                                   "the query.")
+
+    response = LLBStatsDB.get_llb_historical_data(from_time, to_time, link_name)
+    return get_formatted_response(response, 'historical')
+
+
+def get_formatted_response(response, type):
     if not response:
         return []
 
     if isinstance(response, str):
         response = json.loads(response)
 
-    response_data = reformat_data_from_db(response, 'historical')
+    response_data = reformat_data_from_db(response, type)
 
     if response_data:
         return HttpResponse(json.dumps(response_data), content_type='application/json')
@@ -128,10 +143,11 @@
                 series_obj['values'] = units
                 response_data.append(series_obj)
 
-                return response_data
+    return response_data
 
 
 def get_llb_historical_col_values(col_indices, value):
+    """ Get Column values LLB Historical """
     return [value[col_indices["time"]] if "time" in col_indices else 0,
             round(value[col_indices["avgBandwidIn"]],
                   2) if "avgBandwidIn" in col_indices else 0,
@@ -144,6 +160,7 @@
 
 
 def get_llb_monitoring_col_values(col_indices, value):
+    """ Get Column values LLB Monitoring """
     return [value[col_indices["time"]] if "time" in col_indices else 0] + [
         value[col_indices[key]] for key in [
             "top_hits", "top_conn", "total_throughput", "received", "sent", "linkName", "agent_host"
@@ -152,6 +169,7 @@
 
 
 def get_llb_stats_col_values(col_indices, value):
+    """ Get Column values LLB Stats """
     return [value[col_indices["time"]] if "time" in col_indices else 0,
             value[col_indices["linkGateway"]] if "linkGateway" in col_indices else 0,
             round(value[col_indices["linkThresh"]],
@@ -163,4 +181,4 @@
             round(value[col_indices["sent"]],
                   2) if "sent" in col_indices else 0,
             int(value[col_indices["linkConn"]]) if "linkConn" in col_indices else 0,
-            int(value[col_indices["linkHits"]]) if "linkHits" in col_indices else 0]
+            int(value[col_indices["linkHits"]]) if "linkHits" in col_indices else 0]
\ No newline at end of file
Index: /branches/amp_3_7/src/webui/webui/htdocs/new/src/hive/media/static/Array-Logo-en-2024.jpg
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = image/jpeg
Index: /branches/amp_3_7/src/webui/webui/htdocs/new/src/hive/media/static/Array-Logo-en-2024.jpg
===================================================================
--- /branches/amp_3_7/src/webui/webui/htdocs/new/src/hive/media/static/Array-Logo-en-2024.jpg	(revision 2461)
+++ /branches/amp_3_7/src/webui/webui/htdocs/new/src/hive/media/static/Array-Logo-en-2024.jpg	(working copy)

Property changes on: src/webui/webui/htdocs/new/src/hive/media/static/Array-Logo-en-2024.jpg
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+image/jpeg
\ No newline at end of property
Index: /branches/amp_3_7/src/webui/webui/htdocs/new/src/hive/report/__init__.py	(added)
===================================================================
--- /branches/amp_3_7/src/webui/webui/htdocs/new/src/hive/report/__init__.py	(revision 0)
+++ /branches/amp_3_7/src/webui/webui/htdocs/new/src/hive/report/__init__.py	(revision 0)
Index: /branches/amp_3_7/src/webui/webui/htdocs/new/src/hive/report/generate_pdf_report.py
===================================================================
--- /branches/amp_3_7/src/webui/webui/htdocs/new/src/hive/report/generate_pdf_report.py	(revision 0)
+++ /branches/amp_3_7/src/webui/webui/htdocs/new/src/hive/report/generate_pdf_report.py	(working copy)
@@ -0,0 +1,127 @@
+from reportlab.lib.pagesizes import letter
+from reportlab.lib.units import inch
+from reportlab.pdfgen import canvas
+from reportlab.lib import colors
+from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer, Image
+from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
+from django.utils.translation import ugettext_lazy as _
+import random, time, csv, codecs
+from hive.utils import andebug
+from cm.lib.libbasic_operation import oper_log
+
+report_file_path = "/ca/webui/htdocs/new/src/hive/media/docs/"
+logo_path = "/ca/webui/htdocs/new/src/hive/media/static/Array-Logo-en-2024.jpg"
+
+
+class Report:
+
+    def __init__(self):
+        pass
+
+    def get_table_data(self, headers, llb_data):
+        # Add Table Data
+        data = [tuple(headers)] + llb_data
+        table = Table(data, colWidths=int(480 / len(headers)), rowHeights=20)
+        data_len = len(data)
+
+        for each in range(data_len):
+            if each == 0:
+                bg_color = colors.lightgrey
+            else:
+                bg_color = colors.white
+
+            table.setStyle(TableStyle([('BACKGROUND', (0, each), (-1, each), bg_color),
+                                       ('FONT', (0, 0), (-1, -1), 'Helvetica'), ]))
+        return table
+
+    def generate_pdf_report(self, filename, category, llb_data_dict, link_data_summary_dict, start_time, end_time):
+        try:
+            """
+                Generate a PDF report with a table and an optional chart.
+            """
+            pdf = SimpleDocTemplate(report_file_path + filename, pagesize=letter)
+            elements = []
+            styles = getSampleStyleSheet()
+            styles.add(ParagraphStyle(
+                name="LLBHeading3",
+                parent=styles["Heading3"],
+                leftPadding=0  # Add spacing before the paragraph
+            ))
+
+            im = Image(logo_path, 2 * inch, 0.8 * inch)
+            im.hAlign = 'CENTER'
+            elements.append(im)
+            elements.append(Spacer(1, 20))
+
+            # Add Title & Subtitle
+            category_name = str(category).upper()
+            title = category_name + " Report"
+            elements.append(Paragraph('<b>{}</b>'.format(title), styles["Title"]))
+            elements.append(Spacer(1, 20))
+
+            elements.append(Paragraph("Statistics From" + " : " + str(start_time), styles["Heading4"]))
+            elements.append(Paragraph("Statistics To" + " : " + str(end_time), styles["Heading4"]))
+            elements.append(Spacer(1, 10))
+
+            # Summary report
+            if link_data_summary_dict:
+                elements.append(Paragraph("Summary Report (Average values)" + " :", styles["LLBHeading3"]))
+                for link in link_data_summary_dict:
+                    data = link_data_summary_dict.get(link)
+                    elements.append(Spacer(1, 20))
+                    headers = ["Link Name", "Hits", "Connections", "Inbound (bps)", "Outbound (bps)", "Bandwidth Usage"]
+                    link_data = [str(link), data["avg_link_hits"], data["avg_link_conn"], data["avg_bandwidth_in"],
+                                 data["avg_bandwidth_out"], data["avg_link_usage"]]
+                    table = self.get_table_data(headers, [link_data])
+                    elements.append(table)
+                    elements.append(Spacer(1, 30))
+
+            # Detailed Report
+            if llb_data_dict:
+                elements.append(Paragraph("Detailed Report" + " :", styles["LLBHeading3"]))
+                for each_link in llb_data_dict:
+                    elements.append(Paragraph("Link: " + each_link, styles["Heading3"]))
+                    elements.append(Spacer(1, 20))
+
+                    llb_link_data = llb_data_dict.get(each_link)
+
+                    elements.append(Paragraph("Link Throughput(bps)", styles["Heading4"]))
+                    elements.append(Spacer(1, 20))
+                    headers = ["Time", "Inbound (bps)", "Outbound (bps)"]
+                    llb_data = list(
+                        zip(llb_link_data["time"], llb_link_data["inbound_list"], llb_link_data["outbound_list"]))
+                    table = self.get_table_data(headers, llb_data)
+                    elements.append(table)
+                    elements.append(Spacer(1, 30))
+
+                    elements.append(Paragraph("Bandwidth Usage", styles["Heading4"]))
+                    elements.append(Spacer(1, 20))
+                    headers = ["Time", "Bandwidth Usage"]
+                    llb_data = list(
+                        zip(llb_link_data["time"], llb_link_data["bandwidth_usage_list"]))
+                    table = self.get_table_data(headers, llb_data)
+                    elements.append(table)
+                    elements.append(Spacer(1, 30))
+
+                    elements.append(Paragraph("Concurrent Connections", styles["Heading4"]))
+                    elements.append(Spacer(1, 20))
+                    headers = ["Time", "Concurrent Connections"]
+                    llb_data = list(
+                        zip(llb_link_data["time"], llb_link_data["cc_list"]))
+                    table = self.get_table_data(headers, llb_data)
+                    elements.append(table)
+                    elements.append(Spacer(1, 30))
+
+                    elements.append(Paragraph("Hits", styles["Heading4"]))
+                    elements.append(Spacer(1, 20))
+                    headers = ["Time", "Hits"]
+                    llb_data = list(
+                        zip(llb_link_data["time"], llb_link_data["hit_list"]))
+                    table = self.get_table_data(headers, llb_data)
+                    elements.append(table)
+                    elements.append(Spacer(1, 30))
+
+            pdf.build(elements)
+        except Exception as e:
+            oper_log('error', 'system', e.message)
+            raise e  # Raise to crash and see error
\ No newline at end of file
Index: /branches/amp_3_7/src/webui/webui/htdocs/new/src/hive/report/generate_report.py
===================================================================
--- /branches/amp_3_7/src/webui/webui/htdocs/new/src/hive/report/generate_report.py	(revision 0)
+++ /branches/amp_3_7/src/webui/webui/htdocs/new/src/hive/report/generate_report.py	(working copy)
@@ -0,0 +1,174 @@
+import os
+
+from django.http import HttpResponse
+import json
+import time
+from hive.custom_exceptions import generic_exception as ge
+from cm.lib.libbasic_operation import oper_log
+from hive.db.llb_stats_queries import LLBStatsDB
+from hive.report.generate_pdf_report import Report
+from hive.llb_stats import reformat_data_from_db
+from hive.utils import andebug
+
+report_file_path = "/ca/webui/htdocs/new/src/hive/media/docs/"
+
+
+def handle_report_generation(request, path=None):
+    try:
+        if path == 'pdf' and request.method == 'POST':
+            return generate_pdf_report(request)
+        else:
+            return HttpResponse(json.dumps({
+                'error': 405,
+                'message': "Invalid HTTP method"
+            }), content_type='application/json')
+
+    except ge.GenericError as e:
+        oper_log('error', 'system', e.message)
+        return ge.handle_exception(e)
+    except Exception as e:
+        oper_log('error', 'system', 'An Unexpected error occurred,  details: {}'.format(e))
+        e.message = 'An Unexpected error occurred,  details: {}'.format(e)
+        return ge.handle_exception(e)
+
+
+def generate_pdf_report(request):
+    try:
+        req = json.loads(request.body)
+
+        if 'query' in req and 'from_time' in req['query'] and 'to_time' in req['query']:
+            from_time = req['query'].get('from_time', '')
+            to_time = req['query'].get('to_time', '')
+            category = req['query'].get('category')
+            link_name = req['query'].get('link_name', '')
+        else:
+            oper_log('error', 'system',
+                     "Query cannot be empty. Please specify from_time and to_time and link_name in the query.")
+            raise ge.GenericError(400, "Query cannot be empty. Please specify from_time and to_time and link_name in "
+                                       "the query.")
+
+        if category and str(category).upper() == 'LLB':
+            data_dict = get_llb_detailed_data_for_report(from_time, to_time, link_name)
+            data_summary_dict = get_link_summary_data_for_report(from_time, to_time)
+        else:
+            oper_log('error', 'system',
+                     "category cannot be empty. Please specify category in the query.")
+            raise ge.GenericError(400, "category cannot be empty. Please specify category in the query.")
+
+        report_generator = Report()
+        intervalStart, intervalEnd = LLBStatsDB.get_time_range(from_time, to_time)
+        start_time = time.strftime("%Y_%m_%d_%H_%M_%S", time.localtime(intervalEnd / 1000))
+        end_time = time.strftime("%Y_%m_%d_%H_%M_%S",
+                      time.localtime(intervalStart / 1000))
+        report_name = str(category).upper() + "_" + "Statistics_Report_from_%s_to_%s.pdf" % (
+        start_time, end_time)
+
+        report_generator.generate_pdf_report(report_name, category, data_dict, data_summary_dict, intervalStart, intervalEnd)
+        if os.path.exists(report_file_path + report_name):
+            return HttpResponse(json.dumps({"result": True, "filename": report_name}), content_type='application/json')
+        else:
+            return HttpResponse(json.dumps({"result": False}), content_type='application/json')
+
+    except ge.GenericError as e:
+        oper_log('error', 'system', e.message)
+        return ge.handle_exception(e)
+    except Exception as e:
+        oper_log('error', 'system', e.message)
+        return HttpResponse(json.dumps({"error": "Error while generating PDF",
+                                        }), content_type='application/json')
+
+
+def get_link_summary_data_for_report(from_time, to_time):
+    """ Returns data for LLB Summary report """
+    try:
+        response = LLBStatsDB.get_llb_summary_data(from_time, to_time)
+
+        # Handle cases where response is None or not JSON
+        if not response:
+            return []
+
+        if isinstance(response, str):
+            response = json.loads(response)
+
+        response_data = reformat_data_from_db(response, 'historical')
+
+        llb_dict = {}
+        if response_data:
+            for res_data in response_data:
+                data = res_data.get("values")
+                link_name = res_data.get("linkName")
+                for llb_point in data:
+                    llb_dict[link_name] = {
+                        'time': llb_point[0],
+                        'avg_link_hits': llb_point[1],
+                        'avg_link_conn': llb_point[2],
+                        'avg_bandwidth_in': llb_point[3],
+                        'avg_bandwidth_out': llb_point[4],
+                        'avg_link_usage': llb_point[5],
+                    }
+        else:
+            if 'results' in response and all(len(res) == 1 and 'statement_id' in res for res in response['results']):
+                return HttpResponse(json.dumps({
+                    "error": "No valid data found"
+                }), content_type='application/json')
+            else:
+                return HttpResponse(json.dumps(response), content_type='application/json')
+        return llb_dict
+
+    except Exception as e:
+        return HttpResponse(json.dumps({"error": "Error while fetching LLB Summary data",
+                                        }), content_type='application/json')
+
+
+def get_llb_detailed_data_for_report(from_time, to_time, link_name):
+    """ Returns data for LLB Detailed report """
+    try:
+        time_list = []
+        cc_list = []
+        bandwidth_usage_list = []
+        inbound_list = []
+        outbound_list = []
+        hit_list = []
+        response = LLBStatsDB.get_llb_historical_data(from_time, to_time, link_name)
+
+        # Handle cases where response is None or not JSON
+        if not response:
+            return []
+
+        if isinstance(response, str):
+            response = json.loads(response)
+
+        response_data = reformat_data_from_db(response, 'historical')
+
+        llb_dict = {}
+        if response_data:
+            for res_data in response_data:
+                data = res_data.get("values")
+                link_name = res_data.get("linkName")
+                for llb_point in data:
+                    time_list.append(llb_point[0])
+                    inbound_list.append(llb_point[1])
+                    outbound_list.append(llb_point[2])
+                    bandwidth_usage_list.append(llb_point[3])
+                    cc_list.append(llb_point[4])
+                    hit_list.append(llb_point[5])
+
+                    llb_dict[link_name] = {
+                        'time': time_list,
+                        'inbound_list': inbound_list,
+                        'outbound_list': outbound_list,
+                        'bandwidth_usage_list': bandwidth_usage_list,
+                        'cc_list': cc_list,
+                        'hit_list': hit_list,
+                    }
+        else:
+            if 'results' in response and all(len(res) == 1 and 'statement_id' in res for res in response['results']):
+                return HttpResponse(json.dumps({
+                    "error": "No valid data found"
+                }), content_type='application/json')
+            else:
+                return HttpResponse(json.dumps(response), content_type='application/json')
+        return llb_dict
+    except Exception as e:
+        return HttpResponse(json.dumps({"error": "Error while fetching LLB data",
+                                        }), content_type='application/json')
