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 }