-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclient_handlers.py
138 lines (116 loc) · 5.62 KB
/
client_handlers.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import json
import logging
from auth_handlers import BaseHandler
logger = logging.getLogger(__name__)
import json
import logging
from auth_handlers import BaseHandler
logger = logging.getLogger(__name__)
class ClientConfigHandler(BaseHandler):
async def get(self):
client_id = self.get_argument('client_id', None)
if not client_id:
self.set_status(400)
self.write({"error": "Client ID is required"})
return
try:
with self.db.get_cursor() as cursor:
cursor.execute("SELECT config, last_updated FROM client_configs WHERE client_id = %s", (client_id,))
result = cursor.fetchone()
if result:
config, last_updated = result['config'], result['last_updated']
client_last_update = self.get_argument('last_update', '0')
logger.info(f"Client last update: {client_last_update}, Server last updated: {last_updated}")
if str(last_updated.timestamp()) > client_last_update:
self.write({
"status": "update_available",
"config": config
})
else:
self.write({"status": "no_update"})
else:
self.set_status(404)
self.write({"status": "unknown_client"})
except Exception as e:
logger.error(f"Error in ClientConfigHandler GET: {str(e)}")
self.set_status(500)
self.write({"error": "Internal server error"})
async def post(self):
data = json.loads(self.request.body)
client_id = data.get('client_id')
hostname = data.get('hostname')
new_config = data.get('config')
new_tags = data.get('tags', {})
if not client_id or not hostname or not new_config:
self.set_status(400)
self.write({"error": "client_id, hostname, and config are required"})
return
try:
with self.db.get_cursor() as cursor:
# First, get the current config
cursor.execute("SELECT config FROM client_configs WHERE client_id = %s", (client_id,))
result = cursor.fetchone()
if result:
current_config = json.loads(result['config'])
# Merge new config with current config
self.merge_configs(current_config, new_config)
# Merge new tags with current tags
current_tags = current_config.get('tags', {})
current_tags.update(new_tags)
current_config['tags'] = current_tags
updated_config_json = json.dumps(current_config)
if updated_config_json == result['config']:
self.write({"status": "success", "message": "No changes to config"})
else:
cursor.execute("""
UPDATE client_configs
SET hostname = %s, config = %s, last_updated = NOW()
WHERE client_id = %s
""", (hostname, updated_config_json, client_id))
self.write({"status": "success", "message": "Client config updated successfully"})
else:
# New client, insert the config as is
cursor.execute("""
INSERT INTO client_configs (client_id, hostname, config, last_updated)
VALUES (%s, %s, %s, NOW())
""", (client_id, hostname, json.dumps(new_config)))
self.write({"status": "success", "message": "New client config created successfully"})
except Exception as e:
logger.error(f"Error in ClientConfigHandler POST: {str(e)}")
self.set_status(500)
self.write({"error": "Internal server error"})
def merge_configs(self, current_config, new_config):
for key, value in new_config.items():
if isinstance(value, dict) and key in current_config and isinstance(current_config[key], dict):
self.merge_configs(current_config[key], value)
else:
current_config[key] = value
class FetchMetricsHandler(BaseHandler):
async def get(self):
client_id = self.get_argument('client_id', None)
if not client_id:
self.set_status(400)
self.write({"error": "Client ID is required"})
return
try:
with self.db.get_cursor() as cursor:
cursor.execute("SELECT tags FROM client_configs WHERE client_id = %s", (client_id,))
result = cursor.fetchone()
if not result:
self.set_status(404)
self.write({"error": "Client not found"})
return
client_tags = result['tags'] or {}
cursor.execute("""
SELECT name, code
FROM metric_scripts
WHERE tags @> %s OR tags IS NULL OR tags = '{}' OR %s = '{}'
""", (json.dumps(client_tags), json.dumps(client_tags)))
metrics = {row['name']: row['code'] for row in cursor.fetchall()}
self.set_header("Content-Type", "application/json")
self.write(json.dumps(metrics))
except Exception as e:
logger.error(f"Error in FetchMetricsHandler: {str(e)}")
self.set_status(500)
self.set_header("Content-Type", "application/json")
self.write({"error": "Internal server error"})