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  }