github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/cmd/roachprod/install/cassandra.go (about) 1 // Copyright 2018 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package install 12 13 import ( 14 "bufio" 15 "fmt" 16 "html/template" 17 "io/ioutil" 18 "log" 19 "os" 20 "time" 21 22 "github.com/cockroachdb/cockroach/pkg/cmd/roachprod/ssh" 23 ) 24 25 // Cassandra TODO(peter): document 26 type Cassandra struct{} 27 28 // Start implements the ClusterImpl.NodeDir interface. 29 func (Cassandra) Start(c *SyncedCluster, extraArgs []string) { 30 yamlPath, err := makeCassandraYAML(c) 31 if err != nil { 32 log.Fatal(err) 33 } 34 c.Put(yamlPath, "./cassandra.yaml") 35 _ = os.Remove(yamlPath) 36 37 display := fmt.Sprintf("%s: starting cassandra (be patient)", c.Name) 38 nodes := c.ServerNodes() 39 c.Parallel(display, len(nodes), 1, func(i int) ([]byte, error) { 40 host := c.host(nodes[i]) 41 user := c.user(nodes[i]) 42 43 if err := func() error { 44 session, err := ssh.NewSSHSession(user, host) 45 if err != nil { 46 return err 47 } 48 defer session.Close() 49 50 cmd := c.Env + `env ROACHPROD=true cassandra` + 51 ` -Dcassandra.config=file://${PWD}/cassandra.yaml` + 52 ` -Dcassandra.ring_delay_ms=3000` + 53 ` > cassandra.stdout 2> cassandra.stderr` 54 _, err = session.CombinedOutput(cmd) 55 return err 56 }(); err != nil { 57 return nil, err 58 } 59 60 for { 61 up, err := func() (bool, error) { 62 session, err := ssh.NewSSHSession(user, host) 63 if err != nil { 64 return false, err 65 } 66 defer session.Close() 67 68 cmd := `nc -z $(hostname) 9042` 69 if _, err := session.CombinedOutput(cmd); err != nil { 70 // The common case here is going to be "exit status 1" until the 71 // cassandra process starts listening on the port. Logging would 72 // just generate noise. 73 return false, nil //nolint:returnerrcheck 74 } 75 return true, nil 76 }() 77 if err != nil { 78 return nil, err 79 } 80 if up { 81 break 82 } 83 time.Sleep(time.Second) 84 } 85 return nil, nil 86 }) 87 } 88 89 // NodeDir implements the ClusterImpl.NodeDir interface. 90 func (Cassandra) NodeDir(c *SyncedCluster, index int) string { 91 if c.IsLocal() { 92 // TODO(peter): This will require a bit of work to adjust paths in 93 // cassandra.yaml. 94 panic("Cassandra.NodeDir unimplemented") 95 } 96 return "/mnt/data1/cassandra" 97 } 98 99 // LogDir implements the ClusterImpl.NodeDir interface. 100 func (Cassandra) LogDir(c *SyncedCluster, index int) string { 101 panic("Cassandra.LogDir unimplemented") 102 } 103 104 // CertsDir implements the ClusterImpl.NodeDir interface. 105 func (Cassandra) CertsDir(c *SyncedCluster, index int) string { 106 panic("Cassandra.CertsDir unimplemented") 107 } 108 109 // NodeURL implements the ClusterImpl.NodeDir interface. 110 func (Cassandra) NodeURL(_ *SyncedCluster, host string, port int) string { 111 return fmt.Sprintf("'cassandra://%s:%d'", host, port) 112 } 113 114 // NodePort implements the ClusterImpl.NodeDir interface. 115 func (Cassandra) NodePort(c *SyncedCluster, index int) int { 116 // TODO(peter): This will require a bit of work to adjust ports in 117 // cassandra.yaml. 118 // if c.IsLocal() { 119 // } 120 return 9042 121 } 122 123 // NodeUIPort implements the ClusterImpl.NodeDir interface. 124 func (Cassandra) NodeUIPort(c *SyncedCluster, index int) int { 125 return 0 // unimplemented 126 } 127 128 func makeCassandraYAML(c *SyncedCluster) (string, error) { 129 ip, err := c.GetInternalIP(c.ServerNodes()[0]) 130 if err != nil { 131 return "", err 132 } 133 134 f, err := ioutil.TempFile("", "cassandra.yaml") 135 if err != nil { 136 return "", err 137 } 138 defer f.Close() 139 140 w := bufio.NewWriter(f) 141 if _, err := w.WriteString(cassandraDefaultYAML); err != nil { 142 return "", err 143 } 144 defer w.Flush() 145 146 t, err := template.New("cassandra.yaml").Parse(cassandraDiffYAML) 147 if err != nil { 148 log.Fatal(err) 149 } 150 m := map[string]interface{}{ 151 "Seeds": ip, 152 } 153 if err := t.Execute(w, m); err != nil { 154 log.Fatal(err) 155 } 156 return f.Name(), nil 157 }