Clusters: Support persistent storage on remote clusters.

With this merged users can request persistent volumes and PostgreSQL
instances on remote clusters.

This is achieved by Cluster manager installing open-iscsi on all
remote servers and running longhorn on top of them.

Change-Id: Ic1b24ede12fa32bb99f38e560207230437b45fd6
diff --git a/core/installer/cluster/kube.go b/core/installer/cluster/kube.go
index ee123fa..11fe746 100644
--- a/core/installer/cluster/kube.go
+++ b/core/installer/cluster/kube.go
@@ -25,6 +25,7 @@
 	serverToken      string
 	controllers      []Server
 	workers          []Server
+	storageEnabled   bool
 }
 
 func NewKubeManager() *KubeManager {
@@ -42,6 +43,7 @@
 		serverToken:      st.ServerToken,
 		controllers:      st.Controllers,
 		workers:          st.Workers,
+		storageEnabled:   st.StorageEnabled,
 	}, nil
 }
 
@@ -57,10 +59,15 @@
 		m.kubeCfg,
 		m.controllers,
 		m.workers,
+		m.storageEnabled,
 	}
 }
 
-func (m *KubeManager) Init(s Server, setupFn ClusterSetupFunc) (net.IP, error) {
+func (m *KubeManager) EnableStorage() {
+	m.storageEnabled = true
+}
+
+func (m *KubeManager) Init(s Server, setupFn ClusterIngressSetupFunc) (net.IP, error) {
 	m.l.Lock()
 	defer m.l.Unlock()
 	if m.kubeCfg != "" {
diff --git a/core/installer/cluster/manager.go b/core/installer/cluster/manager.go
index c8e62d1..c422535 100644
--- a/core/installer/cluster/manager.go
+++ b/core/installer/cluster/manager.go
@@ -30,14 +30,17 @@
 	Kubeconfig       string   `json:"kubeconfig"`
 	Controllers      []Server `json:"controllers"`
 	Workers          []Server `json:"workers"`
+	StorageEnabled   bool     `json:"storageEnabled"`
 }
 
-type ClusterSetupFunc func(name, kubeconfig, ingressClassName string) (net.IP, error)
+type ClusterIngressSetupFunc func(name, kubeconfig, ingressClassName string) (net.IP, error)
+type ClusterSetupFunc func(m Manager) error
 
 type Manager interface {
-	Init(s Server, setupFn ClusterSetupFunc) (net.IP, error)
+	Init(s Server, setupFn ClusterIngressSetupFunc) (net.IP, error)
 	JoinController(s Server) error
 	JoinWorker(s Server) error
 	RemoveServer(name string) error
 	State() State
+	EnableStorage()
 }
diff --git a/core/installer/cluster/ssh.go b/core/installer/cluster/ssh.go
index 751a797..21562a3 100644
--- a/core/installer/cluster/ssh.go
+++ b/core/installer/cluster/ssh.go
@@ -109,7 +109,8 @@
 
 func GetTailscaleIP(c *SSHClient) (string, error) {
 	fmt.Println("Getting Tailscale IP")
-	if _, err := c.Exec("sudo apt-get install net-tools -y"); err != nil {
+	// TODO(gio): install all necessary packages beforehand
+	if _, err := c.Exec("sudo apt-get install net-tools open-iscsi -y"); err != nil {
 		return "", err
 	}
 	ip, err := c.Exec("sudo ifconfig | grep 10.42")