10
"github.com/juju/loggo"
12
"launchpad.net/juju-core/upstart"
13
"launchpad.net/juju-core/utils"
22
logger = loggo.GetLogger("juju.agent.mongo")
24
oldMongoServiceName = "juju-db"
26
// JujuMongodPath holds the default path to the juju-specific mongod.
27
JujuMongodPath = "/usr/lib/juju/bin/mongod"
28
// MongodbServerPath holds the default path to the generic mongod.
29
MongodbServerPath = "/usr/bin/mongod"
32
// MongoPackageForSeries returns the name of the mongo package for the series
33
// of the machine that it is going to be running on.
34
func MongoPackageForSeries(series string) string {
36
case "precise", "quantal", "raring", "saucy":
37
return "mongodb-server"
44
// MongodPathForSeries returns the path to the mongod executable for the
45
// series of the machine that it is going to be running on.
46
func MongodPathForSeries(series string) string {
47
if series == "trusty" {
50
return MongodbServerPath
53
// MongoPath returns the executable path to be used to run mongod on this
54
// machine. If the juju-bundled version of mongo exists, it will return that
55
// path, otherwise it will return the command to run mongod from the path.
56
func MongodPath() (string, error) {
57
if _, err := os.Stat(JujuMongodPath); err == nil {
58
return JujuMongodPath, nil
61
path, err := exec.LookPath("mongod")
68
// EnsureMongoServer ensures that the correct mongo upstart script is installed
71
// This method will remove old versions of the mongo upstart script as necessary
72
// before installing the new version.
73
func EnsureMongoServer(dir string, port int) error {
74
// NOTE: ensure that the right package is installed?
75
name := makeServiceName(mongoScriptVersion)
76
// TODO: get the series from somewhere, non trusty values return
77
// the existing default path.
78
mongodPath := MongodPathForSeries("some-series")
79
service, err := MongoUpstartService(name, mongodPath, dir, port)
83
if service.Installed() {
87
if err := removeOldMongoServices(mongoScriptVersion); err != nil {
91
if err := makeJournalDirs(dir); err != nil {
95
if err := service.Install(); err != nil {
96
return fmt.Errorf("failed to install mongo service %q: %v", service.Name, err)
98
return service.Start()
101
func makeJournalDirs(dir string) error {
102
journalDir := path.Join(dir, "journal")
104
if err := os.MkdirAll(journalDir, 0700); err != nil {
105
logger.Errorf("failed to make mongo journal dir %s: %v", journalDir, err)
109
// manually create the prealloc files, since otherwise they get created as 100M files.
110
zeroes := make([]byte, 64*1024) // should be enough for anyone
111
for x := 0; x < 3; x++ {
112
name := fmt.Sprintf("prealloc.%d", x)
113
filename := filepath.Join(journalDir, name)
114
f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0700)
116
return fmt.Errorf("failed to open mongo prealloc file %q: %v", filename, err)
119
for total := 0; total < 1024*1024; {
120
n, err := f.Write(zeroes)
122
return fmt.Errorf("failed to write to mongo prealloc file %q: %v", filename, err)
130
// removeOldMongoServices looks for any old juju mongo upstart scripts and
132
func removeOldMongoServices(curVersion int) error {
133
old := upstart.NewService(oldMongoServiceName)
134
if err := old.StopAndRemove(); err != nil {
135
logger.Errorf("Failed to remove old mongo upstart service %q: %v", old.Name, err)
139
// the new formatting for the script name started at version 2
140
for x := 2; x < curVersion; x++ {
141
old := upstart.NewService(makeServiceName(x))
142
if err := old.StopAndRemove(); err != nil {
143
logger.Errorf("Failed to remove old mongo upstart service %q: %v", old.Name, err)
150
func makeServiceName(version int) string {
151
return fmt.Sprintf("juju-db-v%d", version)
154
// mongoScriptVersion keeps track of changes to the mongo upstart script.
155
// Update this version when you update the script that gets installed from
156
// MongoUpstartService.
157
const mongoScriptVersion = 2
159
// MongoUpstartService returns the upstart config for the mongo state service.
161
// This method assumes there is a server.pem keyfile in dataDir.
162
func MongoUpstartService(name, mongodExec, dataDir string, port int) (*upstart.Conf, error) {
164
keyFile := path.Join(dataDir, "server.pem")
165
svc := upstart.NewService(name)
167
dbDir := path.Join(dataDir, "db")
169
conf := &upstart.Conf{
171
Desc: "juju state database",
172
Limit: map[string]string{
173
"nofile": fmt.Sprintf("%d %d", maxFiles, maxFiles),
174
"nproc": fmt.Sprintf("%d %d", maxProcs, maxProcs),
178
" --dbpath=" + dbDir +
179
" --sslOnNormalPorts" +
180
" --sslPEMKeyFile " + utils.ShQuote(keyFile) +
181
" --sslPEMKeyPassword ignored" +
182
" --bind_ip 0.0.0.0" +
183
" --port " + fmt.Sprint(port) +
187
// TODO(Nate): uncomment when we commit HA stuff
189
// " --replSet juju",