agent restart issues restart command to all connected external subagents
[public/netxms.git] / src / agent / core / master.cpp
CommitLineData
060c5a11 1/*
94cbb70f 2** NetXMS multiplatform core agent
eb17778f 3** Copyright (C) 2003-2017 Victor Kirhenshtein
94cbb70f
VK
4**
5** This program is free software; you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation; either version 2 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program; if not, write to the Free Software
17** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18**
19** File: master.cpp
20**
21**/
22
23#include "nxagentd.h"
24
eb17778f
VK
25/**
26 * Restart agent
27 */
28LONG RestartAgent();
29
94cbb70f
VK
30/**
31 * Handler for CMD_GET_PARAMETER command
32 */
b368969c 33static void H_GetParameter(NXCPMessage *pRequest, NXCPMessage *pMsg)
94cbb70f 34{
da8453a5 35 TCHAR name[MAX_PARAM_NAME];
b368969c 36 pRequest->getFieldAsString(VID_PARAMETER, name, MAX_PARAM_NAME);
da8453a5
VK
37
38 TCHAR value[MAX_RESULT_LENGTH];
39 VirtualSession session(0);
40 UINT32 rcc = GetParameterValue(name, value, &session);
41 pMsg->setField(VID_RCC, rcc);
42 if (rcc == ERR_SUCCESS)
b368969c 43 pMsg->setField(VID_VALUE, value);
0f506caa
VK
44}
45
46/**
47 * Handler for CMD_GET_TABLE command
48 */
b368969c 49static void H_GetTable(NXCPMessage *pRequest, NXCPMessage *pMsg)
0f506caa
VK
50{
51 TCHAR name[MAX_PARAM_NAME];
b368969c 52 pRequest->getFieldAsString(VID_PARAMETER, name, MAX_PARAM_NAME);
da8453a5
VK
53
54 Table value;
55 VirtualSession session(0);
56 UINT32 rcc = GetTableValue(name, &value, &session);
57 pMsg->setField(VID_RCC, rcc);
58 if (rcc == ERR_SUCCESS)
0f506caa
VK
59 value.fillMessage(*pMsg, 0, -1);
60}
61
62/**
63 * Handler for CMD_GET_LIST command
64 */
b368969c 65static void H_GetList(NXCPMessage *pRequest, NXCPMessage *pMsg)
0f506caa
VK
66{
67 TCHAR name[MAX_PARAM_NAME];
b368969c 68 pRequest->getFieldAsString(VID_PARAMETER, name, MAX_PARAM_NAME);
da8453a5
VK
69
70 StringList value;
71 VirtualSession session(0);
72 UINT32 rcc = GetListValue(name, &value, &session);
73 pMsg->setField(VID_RCC, rcc);
74 if (rcc == ERR_SUCCESS)
0f506caa 75 {
b368969c 76 pMsg->setField(VID_NUM_STRINGS, (UINT32)value.size());
a6312bd6 77 for(int i = 0; i < value.size(); i++)
b368969c 78 pMsg->setField(VID_ENUM_VALUE_BASE + i, value.get(i));
0f506caa 79 }
94cbb70f
VK
80}
81
0137b9f7
VK
82/**
83 * Pipe to master agent
84 */
85#ifdef _WIN32
86static HANDLE s_pipe = INVALID_HANDLE_VALUE;
87#else
88static int s_pipe = -1;
89#endif
90static MUTEX s_mutexPipeWrite = MutexCreate();
91
94cbb70f
VK
92/**
93 * Listener thread for master agent commands
94 */
94cbb70f
VK
95THREAD_RESULT THREAD_CALL MasterAgentListener(void *arg)
96{
94cbb70f
VK
97 while(!(g_dwFlags & AF_SHUTDOWN))
98 {
e41fc6fc 99#ifdef _WIN32
4ff5a802
VK
100 TCHAR pipeName[MAX_PATH];
101 _sntprintf(pipeName, MAX_PATH, _T("\\\\.\\pipe\\nxagentd.subagent.%s"), g_masterAgent);
102
0137b9f7
VK
103 s_pipe = CreateFile(pipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
104 if (s_pipe != INVALID_HANDLE_VALUE)
94cbb70f
VK
105 {
106 DWORD pipeMode = PIPE_READMODE_MESSAGE;
0137b9f7 107 SetNamedPipeHandleState(s_pipe, &pipeMode, NULL, NULL);
e41fc6fc 108#else
0137b9f7
VK
109 s_pipe = socket(AF_UNIX, SOCK_STREAM, 0);
110 if (s_pipe != INVALID_SOCKET)
e41fc6fc
VK
111 {
112 struct sockaddr_un remote;
113 remote.sun_family = AF_UNIX;
114#ifdef UNICODE
4ff5a802 115 sprintf(remote.sun_path, "/tmp/.nxagentd.subagent.%S", g_masterAgent);
e41fc6fc 116#else
4ff5a802 117 sprintf(remote.sun_path, "/tmp/.nxagentd.subagent.%s", g_masterAgent);
e41fc6fc 118#endif
0137b9f7 119 if (connect(s_pipe, (struct sockaddr *)&remote, SUN_LEN(&remote)) == -1)
e41fc6fc 120 {
0137b9f7
VK
121 close(s_pipe);
122 s_pipe = -1;
e41fc6fc
VK
123 }
124 }
125
0137b9f7 126 if (s_pipe != -1)
e41fc6fc
VK
127 {
128#endif
94cbb70f
VK
129 AgentWriteDebugLog(1, _T("Connected to master agent"));
130
6be0a20b 131 PipeMessageReceiver receiver(s_pipe, 8192, 1048576); // 8K initial, 1M max
94cbb70f
VK
132 while(!(g_dwFlags & AF_SHUTDOWN))
133 {
6be0a20b 134 MessageReceiverResult result;
b368969c 135 NXCPMessage *msg = receiver.readMessage(INFINITE, &result);
639088d4 136 if ((msg == NULL) || (g_dwFlags & AF_SHUTDOWN))
b368969c
VK
137 {
138 AgentWriteDebugLog(6, _T("MasterAgentListener: receiver failure (%s)"), AbstractMessageReceiver::resultToText(result));
94cbb70f 139 break;
b368969c 140 }
4ff5a802
VK
141
142 TCHAR buffer[256];
b368969c 143 AgentWriteDebugLog(6, _T("Received message %s from master agent"), NXCPMessageCodeName(msg->getCode(), buffer));
060c5a11 144
b368969c
VK
145 NXCPMessage response;
146 response.setCode(CMD_REQUEST_COMPLETED);
147 response.setId(msg->getId());
148 switch(msg->getCode())
94cbb70f
VK
149 {
150 case CMD_GET_PARAMETER:
151 H_GetParameter(msg, &response);
152 break;
0f506caa
VK
153 case CMD_GET_TABLE:
154 H_GetTable(msg, &response);
155 break;
156 case CMD_GET_LIST:
157 H_GetList(msg, &response);
158 break;
94cbb70f 159 case CMD_GET_PARAMETER_LIST:
b368969c 160 response.setField(VID_RCC, ERR_SUCCESS);
94cbb70f
VK
161 GetParameterList(&response);
162 break;
0f506caa 163 case CMD_GET_ENUM_LIST:
b368969c 164 response.setField(VID_RCC, ERR_SUCCESS);
0f506caa
VK
165 GetEnumList(&response);
166 break;
167 case CMD_GET_TABLE_LIST:
b368969c 168 response.setField(VID_RCC, ERR_SUCCESS);
0f506caa
VK
169 GetTableList(&response);
170 break;
f918b160
VK
171 case CMD_SHUTDOWN:
172 Shutdown();
173 ThreadSleep(10);
174 exit(0);
eb17778f
VK
175 break;
176 case CMD_RESTART:
177 RestartAgent();
178 ThreadSleep(10);
179 exit(0);
f918b160 180 break;
94cbb70f 181 default:
b368969c 182 response.setField(VID_RCC, ERR_UNKNOWN_COMMAND);
94cbb70f
VK
183 break;
184 }
185 delete msg;
186
187 // Send response to pipe
b368969c 188 NXCP_MESSAGE *rawMsg = response.createMessage();
0137b9f7 189 bool sendSuccess = SendMessageToPipe(s_pipe, rawMsg);
e41fc6fc
VK
190 free(rawMsg);
191 if (!sendSuccess)
192 break;
94cbb70f 193 }
e41fc6fc 194#ifdef _WIN32
0137b9f7 195 CloseHandle(s_pipe);
e41fc6fc 196#else
0137b9f7 197 close(s_pipe);
e41fc6fc 198#endif
94cbb70f
VK
199 AgentWriteDebugLog(1, _T("Disconnected from master agent"));
200 }
201 else
202 {
e41fc6fc 203#ifdef _WIN32
605fc935
VK
204 if (GetLastError() == ERROR_PIPE_BUSY)
205 {
206 WaitNamedPipe(pipeName, 5000);
207 }
208 else
e41fc6fc 209#endif
605fc935
VK
210 {
211 AgentWriteDebugLog(1, _T("Cannot connect to master agent, will retry in 5 seconds"));
212 ThreadSleep(5);
213 }
94cbb70f
VK
214 }
215 }
216 AgentWriteDebugLog(1, _T("Master agent listener stopped"));
217 return THREAD_OK;
218}
0137b9f7
VK
219
220/**
221 * Send message to master agent
222 */
b368969c 223bool SendMessageToMasterAgent(NXCPMessage *msg)
0137b9f7 224{
b368969c 225 NXCP_MESSAGE *rawMsg = msg->createMessage();
0137b9f7
VK
226 bool success = SendRawMessageToMasterAgent(rawMsg);
227 free(rawMsg);
228 return success;
229}
230
231/**
232 * Send raw message to master agent
233 */
b368969c 234bool SendRawMessageToMasterAgent(NXCP_MESSAGE *msg)
0137b9f7
VK
235{
236 MutexLock(s_mutexPipeWrite);
237 bool success = SendMessageToPipe(s_pipe, msg);
238 MutexUnlock(s_mutexPipeWrite);
239 return success;
240}