1 (in-package #:candle-aws)
3 (defvar *aws-mutex* (sb-thread:make-mutex))
4 (defvar *aws-waitq* (sb-thread:make-waitqueue))
5 (defvar *aws-state* :initial)
7 (defvar *aws-instance-id*)
8 (defvar *aws-username*)
12 (defvar *remote-work-dir*)
13 (defvar *remote-candle-location*)
15 (defmethod candle:process-job-in-system ((job-system (eql :aws)) job)
16 (sb-thread:with-mutex (*aws-mutex*)
17 ; Don't start it up until we process the first job
18 (when (eql :initial *aws-state*)
19 (setf *aws-state* :down)
20 (start-shutdown-thread))
21 (when (eql :down *aws-state*) (start-aws-box))
23 ((retn (multiple-value-list (run-job job))))
24 (setf *aws-state* :up)
25 (sb-thread:condition-broadcast *aws-waitq*)
28 (defun start-shutdown-thread ()
29 (log:info "Starting AWS shutdown thread")
30 (sb-thread:make-thread
33 (sb-thread:with-mutex (*aws-mutex*)
34 (when (eql :down *aws-state*)
35 (sb-thread:condition-wait *aws-waitq* *aws-mutex*))
36 (when (eql :shutting-down-soon *aws-state*)
38 (setf *aws-state* :down))
39 (when (eql :up *aws-state*)
40 (setf *aws-state* :shutting-down-soon)))
42 :name "AWS Shutdown Thread"))
44 (defmethod candle:shutdown-system ((job-system (eql :aws)))
45 (log:info "Shutting down AWS box for exit")
46 ; If there's a job going, we need to wait for it to finish
47 (sb-thread:with-mutex (*aws-mutex*))
50 (defun aws-command (cmd &rest args)
51 (with-output-to-string (out)
58 :error *error-output*)))
60 (defun describe-property (property)
67 (format nil "Reservations[0].Instances[0].~A" property))))
69 (defun get-remote-state ()
70 (intern (string-upcase (describe-property "State.Name")) :keyword))
72 (defun start-aws-box ()
73 (aws-command "start-instances" "--instance-ids" *aws-instance-id*)
76 :until (eql :running (get-remote-state))
78 ; Make sure ssh and services are started up
80 (when (not (eql :running (get-remote-state)))
81 (error "Waited two minutes and still not running...?")))
83 (defun stop-aws-box ()
84 (aws-command "stop-instances" "--instance-ids" *aws-instance-id*)
87 :until (eql :stopped (get-remote-state))
89 (when (not (eql :stopped (get-remote-state)))
90 (error "Waited two minutes and still not stopped...?")))
99 (format nil "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~A" *aws-keyfile*)
102 (candle:project-dir (candle:job-project job))
103 (format nil "~A@~A:~A" *aws-username* (describe-property "PublicIpAddress") *remote-work-dir*)))
108 (with-output-to-string (out-str)
110 (sb-ext:process-exit-code
115 "StrictHostKeyChecking=no"
117 "UserKnownHostsFile=/dev/null"
120 (describe-property "PublicIpAddress")
121 (format nil "cd ~A ; ~A run --env aws" *remote-work-dir* *remote-candle-location*))
125 (values (zerop code) out)))