vitess.io/vitess@v0.16.2/go/vt/zkctl/zkconf.go (about) 1 //go:build !codeanalysis 2 // +build !codeanalysis 3 4 /* 5 Copyright 2019 The Vitess Authors. 6 7 Licensed under the Apache License, Version 2.0 (the "License"); 8 you may not use this file except in compliance with the License. 9 You may obtain a copy of the License at 10 11 http://www.apache.org/licenses/LICENSE-2.0 12 13 Unless required by applicable law or agreed to in writing, software 14 distributed under the License is distributed on an "AS IS" BASIS, 15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 See the License for the specific language governing permissions and 17 limitations under the License. 18 */ 19 20 /* 21 Generate zoo.conf files from templates. 22 */ 23 24 package zkctl 25 26 import ( 27 "bytes" 28 "fmt" 29 "os" 30 "path" 31 "strconv" 32 "strings" 33 "text/template" 34 35 "vitess.io/vitess/go/netutil" 36 "vitess.io/vitess/go/vt/env" 37 "vitess.io/vitess/go/vt/log" 38 ) 39 40 type zkServerAddr struct { 41 ServerId uint32 // nolint:revive 42 Hostname string 43 LeaderPort int 44 ElectionPort int 45 ClientPort int 46 } 47 48 type ZkConfig struct { 49 ServerId uint32 // nolint:revive 50 ClientPort int 51 Servers []zkServerAddr 52 Global bool 53 } 54 55 /* ServerId is a unique id for a server - must be 1-255 56 */ 57 func NewZkConfig() *ZkConfig { 58 return &ZkConfig{ 59 ClientPort: 2181, 60 Servers: make([]zkServerAddr, 0, 16), 61 } 62 } 63 64 func (cnf *ZkConfig) DataDir() string { 65 baseDir := env.VtDataRoot() 66 if cnf.Global { 67 return fmt.Sprintf("%v/zk_global_%03d", baseDir, cnf.ServerId) 68 } 69 return fmt.Sprintf("%v/zk_%03d", baseDir, cnf.ServerId) 70 } 71 72 func (cnf *ZkConfig) DirectoryList() []string { 73 return []string{ 74 cnf.DataDir(), 75 cnf.LogDir(), 76 } 77 } 78 79 func (cnf *ZkConfig) LogDir() string { 80 return path.Join(cnf.DataDir(), "logs") 81 } 82 83 func (cnf *ZkConfig) ConfigFile() string { 84 return path.Join(cnf.DataDir(), "zoo.cfg") 85 } 86 87 func (cnf *ZkConfig) PidFile() string { 88 return path.Join(cnf.DataDir(), "zk.pid") 89 } 90 91 func (cnf *ZkConfig) MyidFile() string { 92 return path.Join(cnf.DataDir(), "myid") 93 } 94 95 func (cnf *ZkConfig) WriteMyid() error { 96 return os.WriteFile(cnf.MyidFile(), []byte(fmt.Sprintf("%v", cnf.ServerId)), 0664) 97 } 98 99 /* 100 Search for first existing file in cnfFiles and subsitute in the right values. 101 */ 102 func MakeZooCfg(cnfFiles []string, cnf *ZkConfig, header string) (string, error) { 103 myTemplateSource := new(bytes.Buffer) 104 for _, line := range strings.Split(header, "\n") { 105 fmt.Fprintf(myTemplateSource, "## %v\n", strings.TrimSpace(line)) 106 } 107 var dataErr error 108 for _, path := range cnfFiles { 109 data, dataErr := os.ReadFile(path) 110 if dataErr != nil { 111 continue 112 } 113 myTemplateSource.WriteString("## " + path + "\n") 114 myTemplateSource.Write(data) 115 } 116 if dataErr != nil { 117 return "", dataErr 118 } 119 120 myTemplate, err := template.New("foo").Parse(myTemplateSource.String()) 121 if err != nil { 122 return "", err 123 } 124 cnfData := new(bytes.Buffer) 125 err = myTemplate.Execute(cnfData, cnf) 126 if err != nil { 127 return "", err 128 } 129 return cnfData.String(), nil 130 } 131 132 const GuessMyID = 0 133 134 /* 135 Create a config for this instance. 136 137 <server_id>@<hostname>:<leader_port>:<election_port>:<client_port> 138 139 If server_id > 1000, then we assume this is a global quorum. 140 server_id's must be 1-255, global id's are 1001-1255 mod 1000. 141 */ 142 func MakeZkConfigFromString(cmdLine string, myID uint32) *ZkConfig { 143 zkConfig := NewZkConfig() 144 for _, zki := range strings.Split(cmdLine, ",") { 145 zkiParts := strings.SplitN(zki, "@", 2) 146 if len(zkiParts) != 2 { 147 panic("bad command line format for zk config") 148 } 149 zkID := zkiParts[0] 150 zkAddrParts := strings.Split(zkiParts[1], ":") 151 serverId, _ := strconv.ParseUint(zkID, 10, 0) // nolint:revive 152 if serverId > 1000 { 153 serverId = serverId % 1000 154 zkConfig.Global = true 155 } 156 myID = myID % 1000 157 158 zkServer := zkServerAddr{ServerId: uint32(serverId), ClientPort: 2181, 159 LeaderPort: 2888, ElectionPort: 3888} 160 switch len(zkAddrParts) { 161 case 4: 162 zkServer.ClientPort, _ = strconv.Atoi(zkAddrParts[3]) 163 fallthrough 164 case 3: 165 zkServer.ElectionPort, _ = strconv.Atoi(zkAddrParts[2]) 166 fallthrough 167 case 2: 168 zkServer.LeaderPort, _ = strconv.Atoi(zkAddrParts[1]) 169 fallthrough 170 case 1: 171 zkServer.Hostname = zkAddrParts[0] 172 // if !strings.Contains(zkServer.Hostname, ".") { 173 // panic(fmt.Errorf("expected fully qualified hostname: %v", zkServer.Hostname)) 174 // } 175 default: 176 panic(fmt.Errorf("bad command line format for zk config")) 177 } 178 zkConfig.Servers = append(zkConfig.Servers, zkServer) 179 } 180 hostname := netutil.FullyQualifiedHostnameOrPanic() 181 log.Infof("Fully qualified machine hostname was detected as: %v", hostname) 182 for _, zkServer := range zkConfig.Servers { 183 if (myID > 0 && myID == zkServer.ServerId) || (myID == 0 && zkServer.Hostname == hostname) { 184 zkConfig.ServerId = zkServer.ServerId 185 zkConfig.ClientPort = zkServer.ClientPort 186 break 187 } 188 } 189 if zkConfig.ServerId == 0 { 190 panic(fmt.Errorf("no zk server found for host %v in config %v", hostname, cmdLine)) 191 } 192 return zkConfig 193 }