github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/mongo/service.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package mongo
     5  
     6  import (
     7  	"fmt"
     8  	"path/filepath"
     9  	"strconv"
    10  
    11  	"github.com/juju/errors"
    12  	"github.com/juju/utils"
    13  
    14  	"github.com/juju/juju/service"
    15  	"github.com/juju/juju/service/common"
    16  )
    17  
    18  const (
    19  	maxFiles = 65000
    20  	maxProcs = 20000
    21  
    22  	serviceName    = "juju-db"
    23  	serviceTimeout = 300 // 5 minutes
    24  
    25  	// SharedSecretFile is the name of the Mongo shared secret file
    26  	// located within the Juju data directory.
    27  	SharedSecretFile = "shared-secret"
    28  
    29  	// ReplicaSetName is the name of the replica set that juju uses for its
    30  	// state servers.
    31  	ReplicaSetName = "juju"
    32  )
    33  
    34  var (
    35  	// This is the name of an environment variable that we use in the
    36  	// init system conf file when mongo NUMA support is used.
    37  	multinodeVarName = "MULTI_NODE"
    38  	// This value will be used to wrap desired mongo cmd in numactl if wanted/needed
    39  	numaCtlWrap = "$%v"
    40  	// Extra shell script fragment for init script template.
    41  	// This determines if we are dealing with multi-node environment
    42  	detectMultiNodeScript = `%v=""
    43  if [ $(find /sys/devices/system/node/ -maxdepth 1 -mindepth 1 -type d -name node\* | wc -l ) -gt 1 ]
    44  then
    45      %v=" numactl --interleave=all "
    46      # Ensure sysctl turns off zone_reclaim_mode if not already set
    47      (grep -q vm.zone_reclaim_mode /etc/sysctl.conf || echo vm.zone_reclaim_mode = 0 >> /etc/sysctl.conf) && sysctl -p
    48  fi
    49  `
    50  )
    51  
    52  type mongoService interface {
    53  	Exists() (bool, error)
    54  	Installed() (bool, error)
    55  	Running() (bool, error)
    56  	Start() error
    57  	Stop() error
    58  	Install() error
    59  	Remove() error
    60  }
    61  
    62  var newService = func(name string, conf common.Conf) (mongoService, error) {
    63  	return service.DiscoverService(name, conf)
    64  }
    65  
    66  var discoverService = func(name string) (mongoService, error) {
    67  	return service.DiscoverService(name, common.Conf{})
    68  }
    69  
    70  // IsServiceInstalled returns whether the MongoDB init service
    71  // configuration is present.
    72  var IsServiceInstalled = isServiceInstalled
    73  
    74  func isServiceInstalled(namespace string) (bool, error) {
    75  	svc, err := discoverService(ServiceName(namespace))
    76  	if err != nil {
    77  		return false, errors.Trace(err)
    78  	}
    79  	return svc.Installed()
    80  }
    81  
    82  // RemoveService removes the mongoDB init service from this machine.
    83  func RemoveService(namespace string) error {
    84  	svc, err := discoverService(ServiceName(namespace))
    85  	if err != nil {
    86  		return errors.Trace(err)
    87  	}
    88  	if err := svc.Stop(); err != nil {
    89  		return errors.Trace(err)
    90  	}
    91  	if err := svc.Remove(); err != nil {
    92  		return errors.Trace(err)
    93  	}
    94  	return nil
    95  }
    96  
    97  // ServiceName returns the name of the init service config for mongo using
    98  // the given namespace.
    99  func ServiceName(namespace string) string {
   100  	if namespace != "" {
   101  		return fmt.Sprintf("%s-%s", serviceName, namespace)
   102  	}
   103  	return serviceName
   104  }
   105  
   106  func sslKeyPath(dataDir string) string {
   107  	return filepath.Join(dataDir, "server.pem")
   108  }
   109  
   110  func sharedSecretPath(dataDir string) string {
   111  	return filepath.Join(dataDir, SharedSecretFile)
   112  }
   113  
   114  // newConf returns the init system config for the mongo state service.
   115  func newConf(dataDir, dbDir, mongoPath string, port, oplogSizeMB int, wantNumaCtl bool) common.Conf {
   116  	mongoCmd := mongoPath +
   117  		" --auth" +
   118  		" --dbpath " + utils.ShQuote(dbDir) +
   119  		" --sslOnNormalPorts" +
   120  		" --sslPEMKeyFile " + utils.ShQuote(sslKeyPath(dataDir)) +
   121  		" --sslPEMKeyPassword ignored" +
   122  		" --port " + fmt.Sprint(port) +
   123  		" --noprealloc" +
   124  		" --syslog" +
   125  		" --smallfiles" +
   126  		" --journal" +
   127  		" --keyFile " + utils.ShQuote(sharedSecretPath(dataDir)) +
   128  		" --replSet " + ReplicaSetName +
   129  		" --ipv6" +
   130  		" --oplogSize " + strconv.Itoa(oplogSizeMB)
   131  	extraScript := ""
   132  	if wantNumaCtl {
   133  		extraScript = fmt.Sprintf(detectMultiNodeScript, multinodeVarName, multinodeVarName)
   134  		mongoCmd = fmt.Sprintf(numaCtlWrap, multinodeVarName) + mongoCmd
   135  	}
   136  	conf := common.Conf{
   137  		Desc: "juju state database",
   138  		Limit: map[string]int{
   139  			"nofile": maxFiles,
   140  			"nproc":  maxProcs,
   141  		},
   142  		Timeout:     serviceTimeout,
   143  		ExtraScript: extraScript,
   144  		ExecStart:   mongoCmd,
   145  	}
   146  	return conf
   147  }