updated to add persistence to provisioning and roll that through the rest of the services

Change-Id: Ia0d5a49dc0d88dbe6780c76483fd2247ad631bdf
diff --git a/automation/provisioner_api.go b/automation/provisioner_api.go
new file mode 100644
index 0000000..899cde5
--- /dev/null
+++ b/automation/provisioner_api.go
@@ -0,0 +1,121 @@
+package main
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"net/http"
+)
+
+type ProvisionStatus int
+
+const (
+	Pending ProvisionStatus = iota
+	Running
+	Complete
+	Failed
+)
+
+func (s ProvisionStatus) String() string {
+	switch s {
+	case Pending:
+		return "PENDING"
+	case Running:
+		return "RUNNING"
+	case Complete:
+		return "COMPLETE"
+	case Failed:
+		return "FAILED"
+	}
+	return "INVALID TASK STATUS"
+}
+
+type ProvisionRecord struct {
+	Status    ProvisionStatus `json:"status"`
+	Timestamp int64
+}
+
+type ProvisionRequest struct {
+	Id   string `json:"id"`
+	Name string `json:"name"`
+	Ip   string `json:"ip"`
+	Mac  string `json:"mac"`
+}
+
+type Provisioner interface {
+	Get(id string) (*ProvisionRecord, error)
+	Provision(prov *ProvisionRequest) error
+	Clear(id string) error
+}
+
+type ProvisionerConfig struct {
+	Url string
+}
+
+func NewProvisioner(config *ProvisionerConfig) Provisioner {
+	return config
+}
+
+func (p *ProvisionerConfig) Get(id string) (*ProvisionRecord, error) {
+	resp, err := http.Get(p.Url + "/" + id)
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+	decoder := json.NewDecoder(resp.Body)
+
+	var record ProvisionRecord
+
+	switch resp.StatusCode {
+	case http.StatusOK, http.StatusAccepted:
+		err = decoder.Decode(&record)
+		if err != nil {
+			return nil, err
+		}
+		return &record, nil
+	case http.StatusNotFound:
+		return nil, nil
+	default:
+		return nil, fmt.Errorf(resp.Status)
+	}
+}
+
+func (p *ProvisionerConfig) Provision(prov *ProvisionRequest) error {
+	hc := http.Client{}
+	data, err := json.Marshal(prov)
+	if err != nil {
+		return err
+	}
+	req, err := http.NewRequest("POST", p.Url, bytes.NewReader(data))
+	if err != nil {
+		return err
+	}
+	req.Header.Add("Content-Type", "application/json")
+	resp, err := hc.Do(req)
+	if err != nil {
+		return err
+	}
+	defer resp.Body.Close()
+	if resp.StatusCode != http.StatusAccepted {
+		return fmt.Errorf("Unexpected response : %s", resp.Status)
+	}
+	return nil
+}
+
+func (p *ProvisionerConfig) Clear(id string) error {
+	hc := http.Client{}
+	req, err := http.NewRequest("DELETE", p.Url+"/"+id, nil)
+	if err != nil {
+		return err
+	}
+
+	resp, err := hc.Do(req)
+	if err != nil {
+		return err
+	}
+	defer resp.Body.Close()
+	if resp.StatusCode != http.StatusOK {
+		return fmt.Errorf("Unexpected response : %s", resp.Status)
+	}
+	return nil
+}