Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(643)

Side by Side Diff: agent/mongo/mongo.go

Issue 69600043: mongo stuff to agent/mongod, add EnsureMongoServer
Patch Set: mongo stuff to agent/mongod, add EnsureMongoServer Created 11 years, 1 month ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 package mongo
2
3 import (
4 "fmt"
5 "os"
6 "os/exec"
7 "path"
8 "path/filepath"
9 "strings"
10
11 "launchpad.net/loggo"
12
13 "launchpad.net/juju-core/upstart"
14 "launchpad.net/juju-core/utils"
15 )
16
17 const (
18 maxFiles = 65000
19 maxProcs = 20000
20 JujuMongodPathDefault = "/usr/lib/juju/bin/mongod"
21 )
22
23 var (
24 logger = loggo.GetLogger("juju.agent.mongo")
25
26 oldMongoServiceName = "juju-db"
27
28 // JujuMongodPath is the path to the juju-specific mongod instance.
29 JujuMongodPath = JujuMongodPathDefault
rog 2014/03/04 16:24:46 or just: JujuMongodPath = "/usr/lib/juju/bin/mongo
natefinch 2014/03/04 17:01:05 Done.
30 )
31
32 // MongoPath returns the executable path to be used to run mongod on this
33 // machine. If the juju-bundled version of mongo exists, it will return that
34 // path, otherwise it will return the command to run mongod from the path.
35 func MongodPath() (string, error) {
36 if _, err := os.Stat(JujuMongodPath); err == nil {
37 return JujuMongodPath, nil
38 }
39
40 s, err := exec.Command("/usr/bin/which", "mongod").Output()
rog 2014/03/04 16:24:46 path, err := exec.LookPath("mongod") if err != nil
natefinch 2014/03/04 17:01:05 I always forget about LookPath. Done.
41 if err != nil {
42 // this should never happen, unless which doesn't exist
43 return "", fmt.Errorf("cannot determine mongod path: %v", err)
44 }
45 path := strings.TrimSpace(string(s))
46 if path == "" {
47 return path, fmt.Errorf("cannot find mongod in $PATH")
48 }
49 return path, nil
50 }
51
52 // EnsureMongoServer ensures that the correct mongo upstart script is installed
53 // and running.
54 //
55 // This method will remove old versions of the mongo upstart script as necessary
56 // before installing the new version.
57 func EnsureMongoServer(dir string, port int) error {
58 name := makeServiceName(mongoScriptVersion)
59 service, err := MongoUpstartService(name, dir, port)
60 if err != nil {
61 return err
62 }
63 if service.Installed() {
64 return nil
65 }
66
67 if err := removeOldMongoServices(mongoScriptVersion); err != nil {
68 return err
69 }
70
71 if err := makeJournalDirs(dir); err != nil {
72 return err
73 }
74
75 if err := service.Install(); err != nil {
76 return fmt.Errorf("failed to install mongo service %q: %v", serv ice.Name, err)
77 }
78 return service.Start()
79 }
80
81 func makeJournalDirs(dir string) error {
82 journalDir := path.Join(dir, "journal")
83
84 if err := os.MkdirAll(journalDir, 0700); err != nil {
85 logger.Errorf("failed to make mongo journal dir %s: %v", journal Dir, err)
86 return err
87 }
88
89 // manually create the prealloc files, since otherwise they get created as 100M files.
90 zeroes := make([]byte, 64*1024) // should be enough for anyone
91 for x := 0; x < 3; x++ {
92 name := fmt.Sprintf("prealloc.%d", x)
93 filename := filepath.Join(journalDir, name)
94 f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRU NC, 0700)
95 if err != nil {
96 return fmt.Errorf("failed to open mongo prealloc file %q : %v", filename, err)
97 }
98 defer f.Close()
99 // write 64kb 16x = 1mb
100 for y := 0; y < 16; y++ {
rog 2014/03/04 16:24:46 or a little more directly. for total := 0; total
natefinch 2014/03/04 17:01:05 Done.
101 if _, err := f.Write(zeroes); err != nil {
102 return fmt.Errorf("failed to write to mongo prea lloc file %q: %v", filename, err)
103 }
104 }
105 }
106 return nil
107 }
108
109 // removeOldMongoServices looks for any old juju mongo upstart scripts and
110 // removes them.
111 func removeOldMongoServices(curVersion int) error {
112 old := upstart.NewService(oldMongoServiceName)
113 if err := old.StopAndRemove(); err != nil {
114 logger.Errorf("Failed to remove old mongo upstart service %q: %v ", old.Name, err)
115 return err
116 }
117
118 // the new formatting for the script name started at version 2
119 for x := 2; x < curVersion; x++ {
120 old := upstart.NewService(makeServiceName(x))
121 if err := old.StopAndRemove(); err != nil {
122 logger.Errorf("Failed to remove old mongo upstart servic e %q: %v", old.Name, err)
123 return err
124 }
125 }
126 return nil
127 }
128
129 func makeServiceName(version int) string {
130 return fmt.Sprintf("juju-db-v%d", version)
131 }
132
133 // mongoScriptVersion keeps track of changes to the mongo upstart script.
134 // Update this version when you update the script that gets installed from
135 // MongoUpstartService.
136 const mongoScriptVersion = 2
137
138 // MongoUpstartService returns the upstart config for the mongo state service.
139 //
140 // This method assumes there is a server.pem keyfile in dataDir.
141 func MongoUpstartService(name, dataDir string, port int) (*upstart.Conf, error) {
142
143 keyFile := path.Join(dataDir, "server.pem")
144 svc := upstart.NewService(name)
145
146 dbDir := path.Join(dataDir, "db")
147
148 mongodpath, err := MongodPath()
149 if err != nil {
150 return nil, err
151 }
152
153 conf := &upstart.Conf{
154 Service: *svc,
155 Desc: "juju state database",
156 Limit: map[string]string{
157 "nofile": fmt.Sprintf("%d %d", maxFiles, maxFiles),
158 "nproc": fmt.Sprintf("%d %d", maxProcs, maxProcs),
159 },
160 Cmd: mongodpath +
161 " --auth" +
162 " --dbpath=" + dbDir +
163 " --sslOnNormalPorts" +
164 " --sslPEMKeyFile " + utils.ShQuote(keyFile) +
165 " --sslPEMKeyPassword ignored" +
166 " --bind_ip 0.0.0.0" +
167 " --port " + fmt.Sprint(port) +
168 " --noprealloc" +
169 " --syslog" +
170 " --smallfiles",
171 // TODO(Nate): uncomment when we commit HA stuff
172 // +
173 // " --replSet juju",
174 }
175 return conf, nil
176 }
OLDNEW
« no previous file with comments | « [revision details] ('k') | agent/mongo/mongo_test.go » ('j') | agent/mongo/mongo_test.go » ('J')

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b