 about the request.  If an instance-id is available, the instance-info-map data
 will be merged in."
   [ids]
-  (let [descs  (describe-spot-instance-requests :spot-instance-request-ids ids)
-        sirs   (:spot-instance-requests descs)
-        sirs   (map (fn [rm] (m-section rm [[:request-id :spot-instance-request-id] :state :instance-id])) sirs)
-        is     (filter string? (map :instance-id sirs))
-        ims    (instance-info-map is)
-        sirs   (map #(merge % (ims (:instance-id %))) sirs)]
-    (mseq->m sirs :request-id)))
-
-
-(defn request-instances [rs]
-  (let [d (describe-spot-instance-requests :spot-instance-request-ids rs)]
-    (map :instance-id (:spot-instance-requests d))))
+  (if-not (seq ids)
+    {}
+    (let [ids    (vec ids)
+          descs  (describe-spot-instance-requests :spot-instance-request-ids ids)
+          sirs   (:spot-instance-requests descs)
+          sirs   (map (fn [rm] (m-section rm [[:request-id :spot-instance-request-id] :state :instance-id])) sirs)
+          is     (filter string? (map :instance-id sirs))
+          ims    (instance-info-map is)
+          sirs   (map #(merge % (ims (:instance-id %))) sirs)]
+      (mseq->m sirs :request-id))))
+
 
 (defn request-spots [req & opts]
   (let [req    (apply ph-assoc req paths opts)
         args   (apply concat (seq req))
         _      (debug "Spot request" (pr-str args))
-        rs     (apply request-spot-instances args)]
-    (map :spot-instance-request-id  (:spot-instance-requests rs))))
+        rs     (apply request-spot-instances args)
+        rs     (map :spot-instance-request-id  (:spot-instance-requests rs))]
+    (debug "Requests:" (pr-str (vec rs)))
+    (swap! all-requests #(apply conj % rs))
+    rs))
 
 (defn terminate [is]
-  (let [t (terminate-instances :instance-ids is)]
-    (debug t)
-    t))
+  (when (seq is)
+    (let [is (vec is)
+          t (terminate-instances :instance-ids is)]
+      (debug t)
+      t)))
 
 (defn stop [is]
-  (let [t (stop-instances :instance-ids is)]
-    (debug t)
-    t))
+  (when (seq is)
+    (let [is (vec is)
+          t  (stop-instances :instance-ids is)]
+      (swap! all-normal-instances #(apply disj % is))
+      (debug t)
+      t)))
 
 (defn start [is]
-  (let [t (start-instances :instance-ids is)]
-    (debug t)
-    t))
+  (when (seq is)
+    (let [is (vec is)
+          t (start-instances :instance-ids is)]
+      (swap! all-normal-instances #(apply conj % is))
+      (debug t)
+      t)))
 
 
 (defn cancel-requests
   "Cancel the specified requests; if instance-id information is available, also stops the instances."
   [rs]
-  (let [ds (:spot-instance-requests (describe-spot-instance-requests :spot-instance-request-ids rs))
-        is (filter (complement nil?) (map :instance-id ds))
-        cr (:cancelled-spot-instance-requests (cancel-spot-instance-requests :spot-instance-request-ids rs))
-        ci (and (seq is) (terminate is))]
-    [cr ci]))
-
-
-(def ids->chs (atom {}))
+  (when (seq rs)
+    (let [rs (vec rs)
+          cr (:cancelled-spot-instance-requests (cancel-spot-instance-requests :spot-instance-request-ids rs))
+          ds (:spot-instance-requests (describe-spot-instance-requests :spot-instance-request-ids rs))
+          is (filter (complement nil?) (map :instance-id ds))
+          ci (and (seq is) (terminate is))]
+      (swap! all-requests #(apply disj % rs))
+      [cr ci])))
+
+(defonce ids->chs (atom {}))
 
 (defn- notify-chan
   "Return a channel that will receive status information extracted from send-up messages

(timbre/refer-timbre)


(def cred (read-string (slurp "AWS.clj")))
(apply defcredential (map cred [:access-key :secret-key :endpoint]))


     (string? (:ip info))
     (pos? (count (:ip info))))))


(defn bring-up-spots
  "Bring up at least nmin instances as specified by reqmap.  The sequence
of cmds will be excecuted at startup.  Any other request-spot-instance arguments
can be specified optionally."
  [reqmap nmin cmds & opts]
  (let [[opts [tot no-cancel?]] (extract-opts opts [:minutes :no-cancel])
        _  (debug opts tot no-cancel?)
        tot (or tot 5)
        id  (.toString (UUID/randomUUID))
        cmd (str (send-up id) (clojure.string/join "\n" cmds) "\n")
        req (apply ph-assoc reqmap paths opts)
        req (ph-assoc req paths :udata cmd)
        n   (ph-get reqmap paths :n)
        req (if (<= nmin n) req (ph-assoc req paths :n nmin))
        _   (debug "Requesting:" id (pr-str req))
        cl  (notify-chan id)
        rs  (request-spots req)
        to  (timeout (* tot 60 1000))]
    (async/go-loop [i 0]
      (if (>= i nmin)
        (let [_ (debug 1)
              rs->info (request-info-map rs)
              _ (debug rs->info)
              pred     (partial really-up? rs->info)
              rs-up    (filter pred rs)
              _ (debug rs-up)
              rs-dn    (filter (complement pred) rs)]
          (debug "Brought up" i "spots: "(pr-str [rs-up rs-dn rs->info]))
          (close-notify-chan! id)
          (cancel-requests rs-dn)
          (m-section rs->info rs-up))
        (let [[v c] (async/alts! [cl to])]
          (cond
           (= c to) (when (not  no-cancel?)
                      (info "Timeout on spot request:" req)
                      (close-notify-chan! id)
                      (cancel-requests rs)
                      nil)
           (= c cl) (recur (inc i))))))))

(defn bring-up-instances [is & opts]
  (let [[_ [tot no-cancel?]] (extract-opts opts [:minutes :no-cancel])
        tot (or tot 5)
        n  (count is)
        id (.toString (UUID/randomUUID))
        cl (notify-chan id)
        to (timeout (* tot 5 60 1000))]
    (doseq [i is]
            (modify-instance-attribute :instance-id i :user-data (s->b64 (send-up id))))
    (start is)
