vitess.io/vitess@v0.16.2/go/vt/mysqlctl/mycnf.go (about) 1 /* 2 Copyright 2019 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 /* 18 Generate my.cnf files from templates. 19 */ 20 21 package mysqlctl 22 23 import ( 24 "bufio" 25 "bytes" 26 "fmt" 27 "io" 28 "os" 29 "path" 30 "strconv" 31 ) 32 33 // Mycnf is a memory structure that contains a bunch of interesting 34 // parameters to start mysqld. It can be used to generate standard 35 // my.cnf files from a server id and mysql port. It can also be 36 // populated from an existing my.cnf, or by command line parameters. 37 type Mycnf struct { 38 // ServerID is the unique id for this server. 39 // Used to create a bunch of named directories. 40 ServerID uint32 41 42 // MysqlPort is the port for the MySQL server running on this machine. 43 // It is mainly used to communicate with topology server. 44 MysqlPort int32 45 46 // DataDir is where the table files are 47 // (used by vt software for Clone) 48 DataDir string 49 50 // InnodbDataHomeDir is the data directory for innodb. 51 // (used by vt software for Clone) 52 InnodbDataHomeDir string 53 54 // InnodbLogGroupHomeDir is the logs directory for innodb. 55 // (used by vt software for Clone) 56 InnodbLogGroupHomeDir string 57 58 // SecureFilePriv is the path for loading secure files 59 // (used by vt software for bulk loading into tablet instances) 60 SecureFilePriv string 61 62 // SocketFile is the path to the local mysql.sock file. 63 // (used by vt software to check server is running) 64 SocketFile string 65 66 // GeneralLogPath is the path to store general logs at, 67 // if general-log is enabled. 68 // (unused by vt software for now) 69 GeneralLogPath string 70 71 // ErrorLogPath is the path to store error logs at. 72 // (unused by vt software for now) 73 ErrorLogPath string 74 75 // SlowLogPath is the slow query log path 76 // (unused by vt software for now) 77 SlowLogPath string 78 79 // RelayLogPath is the path of the relay logs 80 // (unused by vt software for now) 81 RelayLogPath string 82 83 // RelayLogIndexPath is the file name for the relay log index 84 // (unused by vt software for now) 85 RelayLogIndexPath string 86 87 // RelayLogInfoPath is the file name for the relay log info file 88 // (unused by vt software for now) 89 RelayLogInfoPath string 90 91 // BinLogPath is the base path for binlogs 92 // (used by vt software for binlog streaming) 93 BinLogPath string 94 95 // MasterInfoFile is the master.info file location. 96 // Unused when vitess manages mysql config because we set 97 // master_info_repository = TABLE and 98 // relay_log_info_repository = TABLE 99 // However it is possible to use custom cnf files with vitess 100 // and to generate them using command-line flags, so we allow a way to set this property 101 MasterInfoFile string 102 103 // PidFile is the mysql.pid file location 104 // (used by vt software to check server is running) 105 PidFile string 106 107 // TmpDir is where to create temporary tables 108 // (unused by vt software for now) 109 TmpDir string 110 111 mycnfMap map[string]string 112 Path string // the actual path that represents this mycnf 113 } 114 115 // TabletDir returns the tablet directory. 116 func (cnf *Mycnf) TabletDir() string { 117 return path.Dir(cnf.DataDir) 118 } 119 120 func (cnf *Mycnf) lookup(key string) string { 121 key = normKey([]byte(key)) 122 return cnf.mycnfMap[key] 123 } 124 125 func (cnf *Mycnf) lookupWithDefault(key, defaultVal string) (string, error) { 126 val := cnf.lookup(key) 127 if val == "" { 128 if defaultVal == "" { 129 return "", fmt.Errorf("value for key '%v' not set and no default value set", key) 130 } 131 return defaultVal, nil 132 } 133 return val, nil 134 } 135 136 func (cnf *Mycnf) lookupInt(key string) (int, error) { 137 val, err := cnf.lookupWithDefault(key, "") 138 if err != nil { 139 return 0, err 140 } 141 ival, err := strconv.Atoi(val) 142 if err != nil { 143 return 0, fmt.Errorf("failed to convert %s: %v", key, err) 144 } 145 return ival, nil 146 } 147 148 func normKey(bkey []byte) string { 149 // FIXME(msolomon) People are careless about hyphen vs underscore - we should normalize. 150 // But you have to normalize to hyphen, or mysqld_safe can fail. 151 return string(bytes.Replace(bytes.TrimSpace(bkey), []byte("_"), []byte("-"), -1)) 152 } 153 154 // ReadMycnf will read an existing my.cnf from disk, and update the passed in Mycnf object 155 // with values from the my.cnf on disk. 156 func ReadMycnf(mycnf *Mycnf) (*Mycnf, error) { 157 f, err := os.Open(mycnf.Path) 158 if err != nil { 159 return nil, err 160 } 161 defer f.Close() 162 163 buf := bufio.NewReader(f) 164 if err != nil { 165 return nil, err 166 } 167 mycnf.mycnfMap = make(map[string]string) 168 var lval, rval string 169 var parts [][]byte 170 171 for { 172 line, _, err := buf.ReadLine() 173 if err == io.EOF { 174 break 175 } 176 line = bytes.TrimSpace(line) 177 178 parts = bytes.Split(line, []byte("=")) 179 if len(parts) < 2 { 180 continue 181 } 182 lval = normKey(parts[0]) 183 rval = string(bytes.TrimSpace(parts[1])) 184 mycnf.mycnfMap[lval] = rval 185 } 186 187 serverID, err := mycnf.lookupInt("server-id") 188 if err != nil { 189 return nil, err 190 } 191 mycnf.ServerID = uint32(serverID) 192 193 port, err := mycnf.lookupInt("port") 194 if err != nil { 195 return nil, err 196 } 197 mycnf.MysqlPort = int32(port) 198 199 mapping := map[string]*string{ 200 "datadir": &mycnf.DataDir, 201 "innodb_data_home_dir": &mycnf.InnodbDataHomeDir, 202 "innodb_log_group_home_dir": &mycnf.InnodbLogGroupHomeDir, 203 "socket": &mycnf.SocketFile, 204 "general_log_file": &mycnf.GeneralLogPath, 205 "log-error": &mycnf.ErrorLogPath, 206 "slow-query-log-file": &mycnf.SlowLogPath, 207 "relay-log": &mycnf.RelayLogPath, 208 "relay-log-index": &mycnf.RelayLogIndexPath, 209 "relay-log-info-file": &mycnf.RelayLogInfoPath, 210 "log-bin": &mycnf.BinLogPath, 211 "master-info-file": &mycnf.MasterInfoFile, 212 "pid-file": &mycnf.PidFile, 213 "tmpdir": &mycnf.TmpDir, 214 "secure-file-priv": &mycnf.SecureFilePriv, 215 } 216 for key, member := range mapping { 217 val, err := mycnf.lookupWithDefault(key, *member) 218 if err != nil { 219 return nil, err 220 } 221 *member = val 222 } 223 224 return mycnf, nil 225 }