agent restart issues restart command to all connected external subagents
[public/netxms.git] / src / agent / core / master.cpp
1 /*
2 ** NetXMS multiplatform core agent
3 ** Copyright (C) 2003-2017 Victor Kirhenshtein
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
25 /**
26 * Restart agent
27 */
28 LONG RestartAgent();
29
30 /**
31 * Handler for CMD_GET_PARAMETER command
32 */
33 static void H_GetParameter(NXCPMessage *pRequest, NXCPMessage *pMsg)
34 {
35 TCHAR name[MAX_PARAM_NAME];
36 pRequest->getFieldAsString(VID_PARAMETER, name, MAX_PARAM_NAME);
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)
43 pMsg->setField(VID_VALUE, value);
44 }
45
46 /**
47 * Handler for CMD_GET_TABLE command
48 */
49 static void H_GetTable(NXCPMessage *pRequest, NXCPMessage *pMsg)
50 {
51 TCHAR name[MAX_PARAM_NAME];
52 pRequest->getFieldAsString(VID_PARAMETER, name, MAX_PARAM_NAME);
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)
59 value.fillMessage(*pMsg, 0, -1);
60 }
61
62 /**
63 * Handler for CMD_GET_LIST command
64 */
65 static void H_GetList(NXCPMessage *pRequest, NXCPMessage *pMsg)
66 {
67 TCHAR name[MAX_PARAM_NAME];
68 pRequest->getFieldAsString(VID_PARAMETER, name, MAX_PARAM_NAME);
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)
75 {
76 pMsg->setField(VID_NUM_STRINGS, (UINT32)value.size());
77 for(int i = 0; i < value.size(); i++)
78 pMsg->setField(VID_ENUM_VALUE_BASE + i, value.get(i));
79 }
80 }
81
82 /**
83 * Pipe to master agent
84 */
85 #ifdef _WIN32
86 static HANDLE s_pipe = INVALID_HANDLE_VALUE;
87 #else
88 static int s_pipe = -1;
89 #endif
90 static MUTEX s_mutexPipeWrite = MutexCreate();
91
92 /**
93 * Listener thread for master agent commands
94 */
95 THREAD_RESULT THREAD_CALL MasterAgentListener(void *arg)
96 {
97 while(!(g_dwFlags & AF_SHUTDOWN))
98 {
99 #ifdef _WIN32
100 TCHAR pipeName[MAX_PATH];
101 _sntprintf(pipeName, MAX_PATH, _T("\\\\.\\pipe\\nxagentd.subagent.%s"), g_masterAgent);
102
103 s_pipe = CreateFile(pipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
104 if (s_pipe != INVALID_HANDLE_VALUE)
105 {
106 DWORD pipeMode = PIPE_READMODE_MESSAGE;
107 SetNamedPipeHandleState(s_pipe, &pipeMode, NULL, NULL);
108 #else
109 s_pipe = socket(AF_UNIX, SOCK_STREAM, 0);
110 if (s_pipe != INVALID_SOCKET)
111 {
112 struct sockaddr_un remote;
113 remote.sun_family = AF_UNIX;
114 #ifdef UNICODE
115 sprintf(remote.sun_path, "/tmp/.nxagentd.subagent.%S", g_masterAgent);
116 #else
117 sprintf(remote.sun_path, "/tmp/.nxagentd.subagent.%s", g_masterAgent);
118 #endif
119 if (connect(s_pipe, (struct sockaddr *)&remote, SUN_LEN(&remote)) == -1)
120 {
121 close(s_pipe);
122 s_pipe = -1;
123 }
124 }
125
126 if (s_pipe != -1)
127 {
128 #endif
129 AgentWriteDebugLog(1, _T("Connected to master agent"));
130
131 PipeMessageReceiver receiver(s_pipe, 8192, 1048576); // 8K initial, 1M max
132 while(!(g_dwFlags & AF_SHUTDOWN))
133 {
134 MessageReceiverResult result;
135 NXCPMessage *msg = receiver.readMessage(INFINITE, &result);
136 if ((msg == NULL) || (g_dwFlags & AF_SHUTDOWN))
137 {
138 AgentWriteDebugLog(6, _T("MasterAgentListener: receiver failure (%s)"), AbstractMessageReceiver::resultToText(result));
139 break;
140 }
141
142 TCHAR buffer[256];
143 AgentWriteDebugLog(6, _T("Received message %s from master agent"), NXCPMessageCodeName(msg->getCode(), buffer));
144
145 NXCPMessage response;
146 response.setCode(CMD_REQUEST_COMPLETED);
147 response.setId(msg->getId());
148 switch(msg->getCode())
149 {
150 case CMD_GET_PARAMETER:
151 H_GetParameter(msg, &response);
152 break;
153 case CMD_GET_TABLE:
154 H_GetTable(msg, &response);
155 break;
156 case CMD_GET_LIST:
157 H_GetList(msg, &response);
158 break;
159 case CMD_GET_PARAMETER_LIST:
160 response.setField(VID_RCC, ERR_SUCCESS);
161 GetParameterList(&response);
162 break;
163 case CMD_GET_ENUM_LIST:
164 response.setField(VID_RCC, ERR_SUCCESS);
165 GetEnumList(&response);
166 break;
167 case CMD_GET_TABLE_LIST:
168 response.setField(VID_RCC, ERR_SUCCESS);
169 GetTableList(&response);
170 break;
171 case CMD_SHUTDOWN:
172 Shutdown();
173 ThreadSleep(10);
174 exit(0);
175 break;
176 case CMD_RESTART:
177 RestartAgent();
178 ThreadSleep(10);
179 exit(0);
180 break;
181 default:
182 response.setField(VID_RCC, ERR_UNKNOWN_COMMAND);
183 break;
184 }
185 delete msg;
186
187 // Send response to pipe
188 NXCP_MESSAGE *rawMsg = response.createMessage();
189 bool sendSuccess = SendMessageToPipe(s_pipe, rawMsg);
190 free(rawMsg);
191 if (!sendSuccess)
192 break;
193 }
194 #ifdef _WIN32
195 CloseHandle(s_pipe);
196 #else
197 close(s_pipe);
198 #endif
199 AgentWriteDebugLog(1, _T("Disconnected from master agent"));
200 }
201 else
202 {
203 #ifdef _WIN32
204 if (GetLastError() == ERROR_PIPE_BUSY)
205 {
206 WaitNamedPipe(pipeName, 5000);
207 }
208 else
209 #endif
210 {
211 AgentWriteDebugLog(1, _T("Cannot connect to master agent, will retry in 5 seconds"));
212 ThreadSleep(5);
213 }
214 }
215 }
216 AgentWriteDebugLog(1, _T("Master agent listener stopped"));
217 return THREAD_OK;
218 }
219
220 /**
221 * Send message to master agent
222 */
223 bool SendMessageToMasterAgent(NXCPMessage *msg)
224 {
225 NXCP_MESSAGE *rawMsg = msg->createMessage();
226 bool success = SendRawMessageToMasterAgent(rawMsg);
227 free(rawMsg);
228 return success;
229 }
230
231 /**
232 * Send raw message to master agent
233 */
234 bool SendRawMessageToMasterAgent(NXCP_MESSAGE *msg)
235 {
236 MutexLock(s_mutexPipeWrite);
237 bool success = SendMessageToPipe(s_pipe, msg);
238 MutexUnlock(s_mutexPipeWrite);
239 return success;
240 }