bUpgrade=FALSE by default
[public/netxms.git] / src / server / tools / nxupload / nxupload.cpp
CommitLineData
d24fdaf4
VK
1/*
2** nxupload - command line tool used to upload files to NetXMS agent
3** Copyright (C) 2004 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** $module: nxupload.cpp
20**
21**/
22
23#include <nms_common.h>
24#include <nms_agent.h>
25#include <nms_util.h>
26#include <nxclapi.h>
27#include <nxsrvapi.h>
28
29#ifndef _WIN32
30#include <netdb.h>
31#endif
32
33
e925a5fc
VK
34//
35// Do agent upgrade
36//
37
38static int UpgradeAgent(AgentConnection &conn, TCHAR *pszPkgName, BOOL bVerbose)
39{
40 DWORD dwError;
41 int i;
42 BOOL bConnected = FALSE;
43
44 dwError = conn.StartUpgrade(pszPkgName);
45 if (dwError == ERR_SUCCESS)
46 {
47 conn.Disconnect();
48
49 if (bVerbose)
50 {
51 printf("Agent upgrade started, waiting for completion...\n"
52 "[............................................................]\r[");
53 fflush(stdout);
54 for(i = 0; i < 120; i += 2)
55 {
56 ThreadSleep(2);
57 putc('*', stdout);
58 fflush(stdout);
59 if ((i % 20 == 0) && (i > 30))
60 {
61 if (conn.Connect(FALSE))
62 {
63 bConnected = TRUE;
64 break; // Connected successfully
65 }
66 }
67 }
68 putc('\n', stdout);
69 }
70 else
71 {
72 ThreadSleep(20);
73 for(i = 20; i < 120; i += 20)
74 {
75 ThreadSleep(20);
76 if (conn.Connect(FALSE))
77 {
78 bConnected = TRUE;
79 break; // Connected successfully
80 }
81 }
82 }
83
84 // Last attempt to reconnect
85 if (!bConnected)
86 bConnected = conn.Connect(bVerbose);
87
88 if (bConnected && bVerbose)
89 {
90 printf("Successfully established connection to agent after upgrade\n");
91 }
92 else
93 {
94 fprintf(stderr, "Failed to establish connection to the agent after upgrade\n");
95 }
96 }
97 else
98 {
99 if (bVerbose)
100 fprintf(stderr, "%d: %s\n", dwError, AgentErrorCodeToText(dwError));
101 }
102
103 return bConnected ? 0 : 1;
104}
105
106
d24fdaf4
VK
107//
108// Startup
109//
110
111int main(int argc, char *argv[])
112{
113 char *eptr;
76cf47d9 114 BOOL bStart = TRUE, bVerbose = TRUE, bUpgrade = FALSE;
d24fdaf4
VK
115 int i, ch, iExitCode = 3;
116 int iAuthMethod = AUTH_NONE;
117 WORD wPort = AGENT_LISTEN_PORT;
118 DWORD dwAddr, dwTimeout = 3000;
119 char szSecret[MAX_SECRET_LENGTH] = "";
ddce77b0 120 INT64 nElapsedTime;
d24fdaf4
VK
121
122 // Parse command line
123 opterr = 1;
e925a5fc 124 while((ch = getopt(argc, argv, "a:hp:qs:uvw:")) != -1)
d24fdaf4
VK
125 {
126 switch(ch)
127 {
128 case 'h': // Display help and exit
129 printf("Usage: nxupload [<options>] <host> <file>\n"
130 "Valid options are:\n"
131 " -a <auth> : Authentication method. Valid methods are \"none\",\n"
132 " \"plain\", \"md5\" and \"sha1\". Default is \"none\".\n"
133 " -h : Display help and exit.\n"
134 " -p <port> : Specify agent's port number. Default is %d.\n"
135 " -q : Quiet mode.\n"
136 " -s <secret> : Specify shared secret for authentication.\n"
e925a5fc 137 " -u : Start agent upgrade from uploaded package.\n"
d24fdaf4
VK
138 " -v : Display version and exit.\n"
139 " -w <seconds> : Specify command timeout (default is 3 seconds)\n"
140 "\n", wPort);
141 bStart = FALSE;
142 break;
143 case 'a': // Auth method
144 if (!strcmp(optarg, "none"))
145 iAuthMethod = AUTH_NONE;
146 else if (!strcmp(optarg, "plain"))
147 iAuthMethod = AUTH_PLAINTEXT;
148 else if (!strcmp(optarg, "md5"))
149 iAuthMethod = AUTH_MD5_HASH;
150 else if (!strcmp(optarg, "sha1"))
151 iAuthMethod = AUTH_SHA1_HASH;
152 else
153 {
154 printf("Invalid authentication method \"%s\"\n", optarg);
155 bStart = FALSE;
156 }
157 break;
158 case 'p': // Port number
159 i = strtol(optarg, &eptr, 0);
160 if ((*eptr != 0) || (i < 0) || (i > 65535))
161 {
162 printf("Invalid port number \"%s\"\n", optarg);
163 bStart = FALSE;
164 }
165 else
166 {
167 wPort = (WORD)i;
168 }
169 break;
170 case 'q': // Quiet mode
171 bVerbose = FALSE;
172 break;
173 case 's': // Shared secret
174 strncpy(szSecret, optarg, MAX_SECRET_LENGTH - 1);
175 break;
e925a5fc
VK
176 case 'u': // Upgrade agent
177 bUpgrade = TRUE;
178 break;
d24fdaf4
VK
179 case 'v': // Print version and exit
180 printf("NetXMS UPLOAD command-line utility Version " NETXMS_VERSION_STRING "\n");
181 bStart = FALSE;
182 break;
183 case 'w': // Command timeout
184 i = strtol(optarg, &eptr, 0);
185 if ((*eptr != 0) || (i < 1) || (i > 120))
186 {
187 printf("Invalid timeout \"%s\"\n", optarg);
188 bStart = FALSE;
189 }
190 else
191 {
192 dwTimeout = (DWORD)i * 1000; // Convert to milliseconds
193 }
194 break;
195 case '?':
196 bStart = FALSE;
197 break;
198 default:
199 break;
200 }
201 }
202
203 // Check parameter correctness
204 if (bStart)
205 {
206 if (argc - optind < 2)
207 {
e925a5fc
VK
208 if (bVerbose)
209 printf("Required argument(s) missing.\nUse nxupload -h to get complete command line syntax.\n");
d24fdaf4
VK
210 bStart = FALSE;
211 }
212 else if ((iAuthMethod != AUTH_NONE) && (szSecret[0] == 0))
213 {
e925a5fc
VK
214 if (bVerbose)
215 fprintf(stderr, "Shared secret not specified or empty\n");
d24fdaf4
VK
216 bStart = FALSE;
217 }
218
219 // If everything is ok, start communications
220 if (bStart)
221 {
222 struct hostent *hs;
223
224 // Initialize WinSock
225#ifdef _WIN32
226 WSADATA wsaData;
227 WSAStartup(2, &wsaData);
228#endif
229
230 // Resolve hostname
231 hs = gethostbyname(argv[optind]);
232 if (hs != NULL)
233 {
234 memcpy(&dwAddr, hs->h_addr, sizeof(DWORD));
235 }
236 else
237 {
238 dwAddr = inet_addr(argv[optind]);
239 }
240 if ((dwAddr == 0) || (dwAddr == INADDR_NONE))
241 {
e925a5fc
VK
242 if (bVerbose)
243 fprintf(stderr, "Invalid host name or address specified\n");
d24fdaf4
VK
244 }
245 else
246 {
247 AgentConnection conn(dwAddr, wPort, iAuthMethod, szSecret);
248
249 conn.SetCommandTimeout(dwTimeout);
250 if (conn.Connect(bVerbose))
251 {
252 DWORD dwError;
253
ddce77b0 254 nElapsedTime = GetCurrentTimeMs();
d24fdaf4 255 dwError = conn.UploadFile(argv[optind + 1]);
ddce77b0 256 nElapsedTime = GetCurrentTimeMs() - nElapsedTime;
d24fdaf4
VK
257 if (bVerbose)
258 {
259 if (dwError == ERR_SUCCESS)
ddce77b0
VK
260 {
261 QWORD qwBytes;
262
263 qwBytes = FileSize(argv[optind + 1]);
264 printf("File transferred successfully\n"
265#ifdef _WIN32
266 "%I64u"
267#else
268 "%llu"
269#endif
270 " bytes in %d.%03d seconds (%.2f KB/sec)\n",
271 qwBytes, (long)(nElapsedTime / 1000),
272 (long)(nElapsedTime % 1000),
273 ((double)((INT64)qwBytes / 1024) / (double)nElapsedTime) * 1000);
274 }
d24fdaf4 275 else
ddce77b0 276 {
e925a5fc 277 fprintf(stderr, "%d: %s\n", dwError, AgentErrorCodeToText(dwError));
ddce77b0 278 }
d24fdaf4 279 }
e925a5fc
VK
280
281 if (bUpgrade && (dwError == RCC_SUCCESS))
282 {
283 iExitCode = UpgradeAgent(conn, argv[optind + 1], bVerbose);
284 }
285 else
286 {
287 iExitCode = (dwError == ERR_SUCCESS) ? 0 : 1;
288 }
d24fdaf4
VK
289 conn.Disconnect();
290 }
291 else
292 {
293 iExitCode = 2;
294 }
295 }
296 }
297 }
298
299 return iExitCode;
300}