Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(79)

Side by Side Diff: pkg/dartino_agent/bin/agent.dart

Issue 1659163007: Rename fletch -> dartino (Closed) Base URL: https://github.com/dartino/sdk.git@master
Patch Set: address comments Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/dartino/pubspec.yaml ('k') | pkg/dartino_agent/lib/agent_connection.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE.md file. 3 // BSD-style license that can be found in the LICENSE.md file.
4 4
5 library fletch_agent.agent; 5 library dartino_agent.agent;
6 6
7 import 'dart:convert' show UTF8; 7 import 'dart:convert' show UTF8;
8 import 'dart:fletch'; 8 import 'dart:dartino';
9 import 'dart:fletch.ffi'; 9 import 'dart:dartino.ffi';
10 import 'dart:fletch.os' as os; 10 import 'dart:dartino.os' as os;
11 import 'dart:typed_data'; 11 import 'dart:typed_data';
12 12
13 import 'package:ffi/ffi.dart'; 13 import 'package:ffi/ffi.dart';
14 import 'package:file/file.dart'; 14 import 'package:file/file.dart';
15 import 'package:fletch/fletch.dart' as fletch; 15 import 'package:dartino/dartino.dart' as dartino;
16 import 'package:os/os.dart' show sys; 16 import 'package:os/os.dart' show sys;
17 import 'package:socket/socket.dart'; 17 import 'package:socket/socket.dart';
18 18
19 import '../lib/messages.dart'; 19 import '../lib/messages.dart';
20 20
21 class Logger { 21 class Logger {
22 final String _prefix; 22 final String _prefix;
23 final String _path; 23 final String _path;
24 final bool _logToStdout; 24 final bool _logToStdout;
25 25
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 return cStringToString(ptr); 66 return cStringToString(ptr);
67 } 67 }
68 68
69 // Agent specific info. 69 // Agent specific info.
70 final String ip; 70 final String ip;
71 final int port; 71 final int port;
72 final String pidFile; 72 final String pidFile;
73 final Logger logger; 73 final Logger logger;
74 final bool applyUpgrade; 74 final bool applyUpgrade;
75 75
76 // Fletch-vm path and args. 76 // Dartino-vm path and args.
77 final String vmBinPath; 77 final String vmBinPath;
78 final String vmLogDir; 78 final String vmLogDir;
79 final String tmpDir; 79 final String tmpDir;
80 80
81 factory AgentContext() { 81 factory AgentContext() {
82 String ip = _getEnv('AGENT_IP'); 82 String ip = _getEnv('AGENT_IP');
83 if (ip == null) { 83 if (ip == null) {
84 ip = '0.0.0.0'; 84 ip = '0.0.0.0';
85 } 85 }
86 int port; 86 int port;
87 try { 87 try {
88 String portStr = _getEnv('AGENT_PORT'); 88 String portStr = _getEnv('AGENT_PORT');
89 port = int.parse(portStr); 89 port = int.parse(portStr);
90 } catch (_) { 90 } catch (_) {
91 port = AGENT_DEFAULT_PORT; // default 91 port = AGENT_DEFAULT_PORT; // default
92 } 92 }
93 String logFile = _getEnv('AGENT_LOG_FILE'); 93 String logFile = _getEnv('AGENT_LOG_FILE');
94 if (logFile == null) { 94 if (logFile == null) {
95 print('Agent requires a valid log file. Please specify file path in ' 95 print('Agent requires a valid log file. Please specify file path in '
96 'the AGENT_LOG_FILE environment variable.'); 96 'the AGENT_LOG_FILE environment variable.');
97 Process.exit(); 97 Process.exit();
98 } 98 }
99 var logger = new Logger('Agent', logFile); 99 var logger = new Logger('Agent', logFile);
100 String pidFile = _getEnv('AGENT_PID_FILE'); 100 String pidFile = _getEnv('AGENT_PID_FILE');
101 if (pidFile == null) { 101 if (pidFile == null) {
102 logger.error('Agent requires a valid pid file. Please specify file path ' 102 logger.error('Agent requires a valid pid file. Please specify file path '
103 'in the AGENT_PID_FILE environment variable.'); 103 'in the AGENT_PID_FILE environment variable.');
104 Process.exit(); 104 Process.exit();
105 } 105 }
106 String vmBinPath = _getEnv('FLETCH_VM'); 106 String vmBinPath = _getEnv('DARTINO_VM');
107 String vmLogDir = _getEnv('VM_LOG_DIR'); 107 String vmLogDir = _getEnv('VM_LOG_DIR');
108 String tmpDir = _getEnv('TMPDIR'); 108 String tmpDir = _getEnv('TMPDIR');
109 if (tmpDir == null) tmpDir = '/tmp'; 109 if (tmpDir == null) tmpDir = '/tmp';
110 110
111 // If the below ENV variable is set the agent will just store the agent 111 // If the below ENV variable is set the agent will just store the agent
112 // debian package but not apply it. 112 // debian package but not apply it.
113 bool applyUpgrade = _getEnv('AGENT_UPGRADE_DRY_RUN') == null; 113 bool applyUpgrade = _getEnv('AGENT_UPGRADE_DRY_RUN') == null;
114 114
115 logger.info('Agent log file: $logFile'); 115 logger.info('Agent log file: $logFile');
116 logger.info('Agent pid file: $pidFile'); 116 logger.info('Agent pid file: $pidFile');
117 logger.info('Vm path: $vmBinPath'); 117 logger.info('Vm path: $vmBinPath');
118 logger.info('Log path: $vmLogDir'); 118 logger.info('Log path: $vmLogDir');
119 119
120 // Make sure we have a fletch-vm binary we can use for launching a vm. 120 // Make sure we have a dartino-vm binary we can use for launching a vm.
121 if (!File.existsAsFile(vmBinPath)) { 121 if (!File.existsAsFile(vmBinPath)) {
122 logger.error('Cannot find fletch vm at path: $vmBinPath'); 122 logger.error('Cannot find dartino vm at path: $vmBinPath');
123 Process.exit(); 123 Process.exit();
124 } 124 }
125 // Make sure we have a valid log directory. 125 // Make sure we have a valid log directory.
126 if (!File.existsAsFile(vmLogDir)) { 126 if (!File.existsAsFile(vmLogDir)) {
127 logger.error('Cannot find log directory: $vmLogDir'); 127 logger.error('Cannot find log directory: $vmLogDir');
128 Process.exit(); 128 Process.exit();
129 } 129 }
130 return new AgentContext._( 130 return new AgentContext._(
131 ip, port, pidFile, logger, vmBinPath, vmLogDir, tmpDir, applyUpgrade); 131 ip, port, pidFile, logger, vmBinPath, vmLogDir, tmpDir, applyUpgrade);
132 } 132 }
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 break; 205 break;
206 case RequestHeader.STOP_VM: 206 case RequestHeader.STOP_VM:
207 _stopVm(); 207 _stopVm();
208 break; 208 break;
209 case RequestHeader.LIST_VMS: 209 case RequestHeader.LIST_VMS:
210 _listVms(); 210 _listVms();
211 break; 211 break;
212 case RequestHeader.UPGRADE_AGENT: 212 case RequestHeader.UPGRADE_AGENT:
213 _upgradeAgent(); 213 _upgradeAgent();
214 break; 214 break;
215 case RequestHeader.FLETCH_VERSION: 215 case RequestHeader.DARTINO_VERSION:
216 _fletchVersion(); 216 _dartinoVersion();
217 break; 217 break;
218 case RequestHeader.SIGNAL_VM: 218 case RequestHeader.SIGNAL_VM:
219 _signalVm(); 219 _signalVm();
220 break; 220 break;
221 default: 221 default:
222 _context.logger.warn('Unknown command: ${_requestHeader.command}.'); 222 _context.logger.warn('Unknown command: ${_requestHeader.command}.');
223 _sendReply( 223 _sendReply(
224 new ReplyHeader(_requestHeader.id, ReplyHeader.UNKNOWN_COMMAND)); 224 new ReplyHeader(_requestHeader.id, ReplyHeader.UNKNOWN_COMMAND));
225 break; 225 break;
226 } 226 }
(...skipping 11 matching lines...) Expand all
238 File portFile = new File.temporary("${_context.tmpDir}/vm-port-"); 238 File portFile = new File.temporary("${_context.tmpDir}/vm-port-");
239 try { 239 try {
240 List<String> args = ['--log-dir=${_context.vmLogDir}', 240 List<String> args = ['--log-dir=${_context.vmLogDir}',
241 '--port-file=${portFile.path}', '--host=0.0.0.0']; 241 '--port-file=${portFile.path}', '--host=0.0.0.0'];
242 vmPid = os.NativeProcess.startDetached(_context.vmBinPath, args); 242 vmPid = os.NativeProcess.startDetached(_context.vmBinPath, args);
243 // Find out what port the vm is listening on. 243 // Find out what port the vm is listening on.
244 _context.logger.info('Reading port from ${portFile.path} for vm $vmPid'); 244 _context.logger.info('Reading port from ${portFile.path} for vm $vmPid');
245 int port = _retrieveVmPort(portFile.path); 245 int port = _retrieveVmPort(portFile.path);
246 reply = new StartVmReply( 246 reply = new StartVmReply(
247 _requestHeader.id, ReplyHeader.SUCCESS, vmId: vmPid, vmPort: port); 247 _requestHeader.id, ReplyHeader.SUCCESS, vmId: vmPid, vmPort: port);
248 _context.logger.info('Started fletch vm with pid $vmPid on port $port'); 248 _context.logger.info('Started dartino vm with pid $vmPid on port $port');
249 } catch (e) { 249 } catch (e) {
250 reply = new StartVmReply(_requestHeader.id, ReplyHeader.START_VM_FAILED); 250 reply = new StartVmReply(_requestHeader.id, ReplyHeader.START_VM_FAILED);
251 // TODO(wibling): could extend the result with caught error string. 251 // TODO(wibling): could extend the result with caught error string.
252 _context.logger.warn('Failed to start vm with error: $e'); 252 _context.logger.warn('Failed to start vm with error: $e');
253 if (vmPid > 0) { 253 if (vmPid > 0) {
254 // Kill the vm. 254 // Kill the vm.
255 _kill.icall$2(vmPid, SIGTERM); 255 _kill.icall$2(vmPid, SIGTERM);
256 } 256 }
257 } finally { 257 } finally {
258 File.delete(portFile.path); 258 File.delete(portFile.path);
259 } 259 }
260 _sendReply(reply); 260 _sendReply(reply);
261 } 261 }
262 262
263 int _retrieveVmPort(String portPath) { 263 int _retrieveVmPort(String portPath) {
264 // The fletch-vm will write the port it is listening on into the file 264 // The dartino-vm will write the port it is listening on into the file
265 // specified by 'portPath' above. The agent waits for the file to be 265 // specified by 'portPath' above. The agent waits for the file to be
266 // created (retries the File.open until it succeeds) and then reads the 266 // created (retries the File.open until it succeeds) and then reads the
267 // port from the file. 267 // port from the file.
268 // To make sure we are reading a consistent value from the file, ie. the 268 // To make sure we are reading a consistent value from the file, ie. the
269 // vm could have written a partial value at the time we read it, we continue 269 // vm could have written a partial value at the time we read it, we continue
270 // reading the value from the file until we have read the same value from 270 // reading the value from the file until we have read the same value from
271 // file in two consecutive reads. 271 // file in two consecutive reads.
272 // An alternative to the consecutive reading would be to use cooperative 272 // An alternative to the consecutive reading would be to use cooperative
273 // locking, but consecutive reading is not relying on the fletch-vm to 273 // locking, but consecutive reading is not relying on the dartino-vm to
274 // behave. 274 // behave.
275 // TODO(wibling): Look into passing a socket port to the fletch-vm and 275 // TODO(wibling): Look into passing a socket port to the dartino-vm and
276 // have it write the port to the socket. This allows the agent to just 276 // have it write the port to the socket. This allows the agent to just
277 // wait on the socket and wake up when it is ready. 277 // wait on the socket and wake up when it is ready.
278 int previousPort = -1; 278 int previousPort = -1;
279 for (int retries = 500; retries >= 0; --retries) { 279 for (int retries = 500; retries >= 0; --retries) {
280 int port = _tryReadPort(portPath, retries == 0); 280 int port = _tryReadPort(portPath, retries == 0);
281 // Check if we read the same port value twice in a row. 281 // Check if we read the same port value twice in a row.
282 if (previousPort != -1 && previousPort == port) return port; 282 if (previousPort != -1 && previousPort == port) return port;
283 previousPort = port; 283 previousPort = port;
284 os.sleep(10); 284 os.sleep(10);
285 } 285 }
(...skipping 28 matching lines...) Expand all
314 if (_requestHeader.payloadLength != 4) { 314 if (_requestHeader.payloadLength != 4) {
315 _sendReply( 315 _sendReply(
316 new StopVmReply(_requestHeader.id, ReplyHeader.INVALID_PAYLOAD)); 316 new StopVmReply(_requestHeader.id, ReplyHeader.INVALID_PAYLOAD));
317 return; 317 return;
318 } 318 }
319 var reply; 319 var reply;
320 // Read in the vm id. 320 // Read in the vm id.
321 var pidBytes = _socket.read(4); 321 var pidBytes = _socket.read(4);
322 if (pidBytes == null) { 322 if (pidBytes == null) {
323 reply = new StopVmReply(_requestHeader.id, ReplyHeader.INVALID_PAYLOAD); 323 reply = new StopVmReply(_requestHeader.id, ReplyHeader.INVALID_PAYLOAD);
324 _context.logger.warn('Missing pid of the fletch vm to stop.'); 324 _context.logger.warn('Missing pid of the dartino vm to stop.');
325 } else { 325 } else {
326 int pid = readUint32(pidBytes, 0); 326 int pid = readUint32(pidBytes, 0);
327 int err = _kill.icall$2(pid, SIGTERM); 327 int err = _kill.icall$2(pid, SIGTERM);
328 if (err != 0) { 328 if (err != 0) {
329 reply = new StopVmReply(_requestHeader.id, ReplyHeader.UNKNOWN_VM_ID); 329 reply = new StopVmReply(_requestHeader.id, ReplyHeader.UNKNOWN_VM_ID);
330 _context.logger.warn( 330 _context.logger.warn(
331 'Failed to stop pid $pid with error: ${Foreign.errno}'); 331 'Failed to stop pid $pid with error: ${Foreign.errno}');
332 } else { 332 } else {
333 reply = new StopVmReply(_requestHeader.id, ReplyHeader.SUCCESS); 333 reply = new StopVmReply(_requestHeader.id, ReplyHeader.SUCCESS);
334 _context.logger.info('Stopped pid: $pid'); 334 _context.logger.info('Stopped pid: $pid');
335 } 335 }
336 } 336 }
337 _sendReply(reply); 337 _sendReply(reply);
338 } 338 }
339 339
340 void _signalVm() { 340 void _signalVm() {
341 if (_requestHeader.payloadLength != 8) { 341 if (_requestHeader.payloadLength != 8) {
342 _sendReply( 342 _sendReply(
343 new SignalVmReply(_requestHeader.id, ReplyHeader.INVALID_PAYLOAD)); 343 new SignalVmReply(_requestHeader.id, ReplyHeader.INVALID_PAYLOAD));
344 return; 344 return;
345 } 345 }
346 var reply; 346 var reply;
347 // Read in the vm id and the signal to send. 347 // Read in the vm id and the signal to send.
348 var pidBytes = _socket.read(8); 348 var pidBytes = _socket.read(8);
349 if (pidBytes == null) { 349 if (pidBytes == null) {
350 reply = new SignalVmReply(_requestHeader.id, ReplyHeader.INVALID_PAYLOAD); 350 reply = new SignalVmReply(_requestHeader.id, ReplyHeader.INVALID_PAYLOAD);
351 _context.logger.warn('Missing pid of the fletch vm to signal.'); 351 _context.logger.warn('Missing pid of the dartino vm to signal.');
352 } else { 352 } else {
353 int pid = readUint32(pidBytes, 0); 353 int pid = readUint32(pidBytes, 0);
354 int signal = readUint32(pidBytes, 4); 354 int signal = readUint32(pidBytes, 4);
355 // Hack to make ctrl-c work for stopping spawned vms work on Raspbian 355 // Hack to make ctrl-c work for stopping spawned vms work on Raspbian
356 // wheezy. For some reason SIGINT doesn't work so we map it to SIGTERM as 356 // wheezy. For some reason SIGINT doesn't work so we map it to SIGTERM as
357 // a workaround. 357 // a workaround.
358 if (signal == SIGINT && sys.info().release.startsWith('3.18')) { 358 if (signal == SIGINT && sys.info().release.startsWith('3.18')) {
359 _context.logger.info('Remapping SIGINT to SIGTERM on Raspbian wheezy'); 359 _context.logger.info('Remapping SIGINT to SIGTERM on Raspbian wheezy');
360 signal = SIGTERM; 360 signal = SIGTERM;
361 } 361 }
(...skipping 13 matching lines...) Expand all
375 void _listVms() { 375 void _listVms() {
376 // TODO(wibling): implement this method. For now just hardcode some values. 376 // TODO(wibling): implement this method. For now just hardcode some values.
377 _sendReply( 377 _sendReply(
378 new ListVmsReply(_requestHeader.id, ReplyHeader.UNKNOWN_COMMAND)); 378 new ListVmsReply(_requestHeader.id, ReplyHeader.UNKNOWN_COMMAND));
379 } 379 }
380 380
381 void _upgradeAgent() { 381 void _upgradeAgent() {
382 int result; 382 int result;
383 ByteBuffer binary = _socket.read(_requestHeader.payloadLength); 383 ByteBuffer binary = _socket.read(_requestHeader.payloadLength);
384 if (binary == null) { 384 if (binary == null) {
385 _context.logger.warn('Could not read fletch-agent package binary' 385 _context.logger.warn('Could not read dartino-agent package binary'
386 ' of length ${_requestHeader.payloadLength} bytes'); 386 ' of length ${_requestHeader.payloadLength} bytes');
387 result = ReplyHeader.INVALID_PAYLOAD; 387 result = ReplyHeader.INVALID_PAYLOAD;
388 } else { 388 } else {
389 _context.logger.info('Read fletch-agent package binary' 389 _context.logger.info('Read dartino-agent package binary'
390 ' of length ${binary.lengthInBytes} bytes.'); 390 ' of length ${binary.lengthInBytes} bytes.');
391 File file = new File.open(PACKAGE_FILE_NAME, mode: File.WRITE); 391 File file = new File.open(PACKAGE_FILE_NAME, mode: File.WRITE);
392 try { 392 try {
393 file.write(binary); 393 file.write(binary);
394 } catch (e) { 394 } catch (e) {
395 _context.logger.warn('UpgradeAgent failed: $e'); 395 _context.logger.warn('UpgradeAgent failed: $e');
396 _sendReply(new UpgradeAgentReply(_requestHeader.id, 396 _sendReply(new UpgradeAgentReply(_requestHeader.id,
397 ReplyHeader.UPGRADE_FAILED)); 397 ReplyHeader.UPGRADE_FAILED));
398 } finally { 398 } finally {
399 file.close(); 399 file.close();
400 } 400 }
401 _context.logger.info('Package file written successfully.'); 401 _context.logger.info('Package file written successfully.');
402 if (_context.applyUpgrade) { 402 if (_context.applyUpgrade) {
403 int pid = os.NativeProcess.startDetached('/usr/bin/dpkg', 403 int pid = os.NativeProcess.startDetached('/usr/bin/dpkg',
404 [// Force dpkg to overwrite configuration files installed by 404 [// Force dpkg to overwrite configuration files installed by
405 // the agent. 405 // the agent.
406 '--force-confnew', 406 '--force-confnew',
407 '--install', 407 '--install',
408 PACKAGE_FILE_NAME]); 408 PACKAGE_FILE_NAME]);
409 _context.logger.info('started package update (PID $pid)'); 409 _context.logger.info('started package update (PID $pid)');
410 } 410 }
411 result = ReplyHeader.SUCCESS; 411 result = ReplyHeader.SUCCESS;
412 } 412 }
413 _context.logger.info('sending reply'); 413 _context.logger.info('sending reply');
414 _sendReply(new UpgradeAgentReply(_requestHeader.id, result)); 414 _sendReply(new UpgradeAgentReply(_requestHeader.id, result));
415 } 415 }
416 416
417 void _fletchVersion() { 417 void _dartinoVersion() {
418 String version = fletch.version(); 418 String version = dartino.version();
419 _context.logger.info('Returning fletch version $version'); 419 _context.logger.info('Returning dartino version $version');
420 _sendReply(new FletchVersionReply( 420 _sendReply(new DartinoVersionReply(
421 _requestHeader.id, ReplyHeader.SUCCESS, version: version)); 421 _requestHeader.id, ReplyHeader.SUCCESS, version: version));
422 } 422 }
423 } 423 }
424 424
425 void main(List<String> arguments) { 425 void main(List<String> arguments) {
426 // The agent context will initialize itself from the runtime environment. 426 // The agent context will initialize itself from the runtime environment.
427 var context = new AgentContext(); 427 var context = new AgentContext();
428 428
429 // Write the program's pid to the pid file if set. 429 // Write the program's pid to the pid file if set.
430 _writePid(context.pidFile); 430 _writePid(context.pidFile);
431 431
432 // Run fletch agent on given ip address and port. 432 // Run dartino agent on given ip address and port.
433 var agent = new Agent(context); 433 var agent = new Agent(context);
434 agent.start(); 434 agent.start();
435 } 435 }
436 436
437 void _writePid(String pidFilePath) { 437 void _writePid(String pidFilePath) {
438 final ForeignFunction _getpid = ForeignLibrary.main.lookup('getpid'); 438 final ForeignFunction _getpid = ForeignLibrary.main.lookup('getpid');
439 439
440 int pid = _getpid.icall$0(); 440 int pid = _getpid.icall$0();
441 List<int> encodedPid = UTF8.encode('$pid'); 441 List<int> encodedPid = UTF8.encode('$pid');
442 ByteBuffer buffer = new Uint8List.fromList(encodedPid).buffer; 442 ByteBuffer buffer = new Uint8List.fromList(encodedPid).buffer;
443 var pidFile = new File.open(pidFilePath, mode: File.WRITE); 443 var pidFile = new File.open(pidFilePath, mode: File.WRITE);
444 try { 444 try {
445 pidFile.write(buffer); 445 pidFile.write(buffer);
446 } finally { 446 } finally {
447 pidFile.close(); 447 pidFile.close();
448 } 448 }
449 } 449 }
450 450
451 void printUsage() { 451 void printUsage() {
452 print('Usage:'); 452 print('Usage:');
453 print('The Fletch agent supports the following flags'); 453 print('The Dartino agent supports the following flags');
454 print(''); 454 print('');
455 print(' --port: specify the port on which to listen, default: ' 455 print(' --port: specify the port on which to listen, default: '
456 '$AGENT_DEFAULT_PORT'); 456 '$AGENT_DEFAULT_PORT');
457 print(' --ip: specify the ip address on which to listen, default: 0.0.0.0'); 457 print(' --ip: specify the ip address on which to listen, default: 0.0.0.0');
458 print(' --vm: specify the path to the vm binary, default: ' 458 print(' --vm: specify the path to the vm binary, default: '
459 '/opt/fletch/bin/fletch-vm.'); 459 '/opt/dartino/bin/dartino-vm.');
460 print(''); 460 print('');
461 Process.exit(); 461 Process.exit();
462 } 462 }
OLDNEW
« no previous file with comments | « pkg/dartino/pubspec.yaml ('k') | pkg/dartino_agent/lib/agent_connection.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698