github.com/cloudbase/juju-core@v0.0.0-20140504232958-a7271ac7912f/provider/local/prereqs_linux.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package local 5 6 import ( 7 "errors" 8 "fmt" 9 "os" 10 "os/exec" 11 "regexp" 12 "runtime" 13 14 "launchpad.net/juju-core/agent/mongo" 15 "launchpad.net/juju-core/container/kvm" 16 "launchpad.net/juju-core/instance" 17 "launchpad.net/juju-core/utils" 18 "launchpad.net/juju-core/version" 19 ) 20 21 var notLinuxError = errors.New("The local provider is currently only available for Linux") 22 23 const installMongodUbuntu = "MongoDB server must be installed to enable the local provider:" 24 const aptAddRepositoryJujuStable = ` 25 sudo apt-add-repository ppa:juju/stable # required for MongoDB SSL support 26 sudo apt-get update` 27 const aptGetInstallMongodbServer = ` 28 sudo apt-get install mongodb-server` 29 30 const installMongodGeneric = ` 31 MongoDB server must be installed to enable the local provider. 32 Please consult your operating system distribution's documentation 33 for instructions on installing the MongoDB server. Juju requires 34 a MongoDB server built with SSL support. 35 ` 36 37 const installLxcUbuntu = ` 38 Linux Containers (LXC) userspace tools must be 39 installed to enable the local provider: 40 41 sudo apt-get install lxc` 42 43 const installRsyslogGnutlsUbuntu = ` 44 rsyslog-gnutls must be installed to enable the local provider: 45 46 sudo apt-get install rsyslog-gnutls` 47 48 const installRsyslogGnutlsGeneric = ` 49 rsyslog-gnutls must be installed to enable the local provider. 50 Please consult your operating system distribution's documentation 51 for instructions on installing this package.` 52 53 const installLxcGeneric = ` 54 Linux Containers (LXC) userspace tools must be installed to enable the 55 local provider. Please consult your operating system distribution's 56 documentation for instructions on installing the LXC userspace tools.` 57 58 const errUnsupportedOS = `Unsupported operating system: %s 59 The local provider is currently only available for Linux` 60 61 // lowestMongoVersion is the lowest version of mongo that juju supports. 62 var lowestMongoVersion = version.Number{Major: 2, Minor: 2, Patch: 4} 63 64 // lxclsPath is the path to "lxc-ls", an LXC userspace tool 65 // we check the presence of to determine whether the 66 // tools are installed. This is a variable only to support 67 // unit testing. 68 var lxclsPath = "lxc-ls" 69 70 // isPackageInstalled is a variable to support testing. 71 var isPackageInstalled = utils.IsPackageInstalled 72 73 // defaultRsyslogGnutlsPath is the default path to the 74 // rsyslog GnuTLS module. This is a variable only to 75 // support unit testing. 76 var defaultRsyslogGnutlsPath = "/usr/lib/rsyslog/lmnsd_gtls.so" 77 78 // The operating system the process is running in. 79 // This is a variable only to support unit testing. 80 var goos = runtime.GOOS 81 82 // This is the regex for processing the results of mongod --verison 83 var mongoVerRegex = regexp.MustCompile(`db version v(\d+\.\d+\.\d+)`) 84 85 // VerifyPrerequisites verifies the prerequisites of 86 // the local machine (machine 0) for running the local 87 // provider. 88 func VerifyPrerequisites(containerType instance.ContainerType) error { 89 if goos != "linux" { 90 return fmt.Errorf(errUnsupportedOS, goos) 91 } 92 if err := verifyMongod(); err != nil { 93 return err 94 } 95 if err := verifyRsyslogGnutls(); err != nil { 96 return err 97 } 98 switch containerType { 99 case instance.LXC: 100 return verifyLxc() 101 case instance.KVM: 102 return kvm.VerifyKVMEnabled() 103 } 104 return fmt.Errorf("Unknown container type specified in the config.") 105 } 106 107 func verifyMongod() error { 108 path, err := mongo.MongodPath() 109 if err != nil { 110 return wrapMongodNotExist(err) 111 } 112 113 ver, err := mongodVersion(path) 114 if err != nil { 115 return err 116 } 117 if ver.Compare(lowestMongoVersion) < 0 { 118 return fmt.Errorf("installed version of mongod (%v) is not supported by Juju. "+ 119 "Juju requires version %v or greater.", 120 ver, 121 lowestMongoVersion) 122 } 123 return nil 124 } 125 126 func mongodVersion(path string) (version.Number, error) { 127 data, err := utils.RunCommand(path, "--version") 128 if err != nil { 129 return version.Zero, wrapMongodNotExist(err) 130 } 131 132 return parseVersion(data) 133 } 134 135 func parseVersion(data string) (version.Number, error) { 136 matches := mongoVerRegex.FindStringSubmatch(data) 137 if len(matches) < 2 { 138 return version.Zero, errors.New("could not parse mongod version") 139 } 140 return version.Parse(matches[1]) 141 } 142 143 func verifyLxc() error { 144 _, err := exec.LookPath(lxclsPath) 145 if err != nil { 146 return wrapLxcNotFound(err) 147 } 148 return nil 149 } 150 151 func verifyRsyslogGnutls() error { 152 if isPackageInstalled("rsyslog-gnutls") { 153 return nil 154 } 155 if utils.IsUbuntu() { 156 return errors.New(installRsyslogGnutlsUbuntu) 157 } 158 // Not all Linuxes will distribute the module 159 // in the same way. Check if it's in the default 160 // location too. 161 _, err := os.Stat(defaultRsyslogGnutlsPath) 162 if err == nil { 163 return nil 164 } 165 return fmt.Errorf("%v\n%s", err, installRsyslogGnutlsGeneric) 166 } 167 168 func wrapMongodNotExist(err error) error { 169 if utils.IsUbuntu() { 170 series := version.Current.Series 171 args := []interface{}{err, installMongodUbuntu} 172 format := "%v\n%s\n%s" 173 if series == "precise" || series == "quantal" { 174 format += "%s" 175 args = append(args, aptAddRepositoryJujuStable) 176 } 177 args = append(args, aptGetInstallMongodbServer) 178 return fmt.Errorf(format, args...) 179 } 180 return fmt.Errorf("%v\n%s", err, installMongodGeneric) 181 } 182 183 func wrapLxcNotFound(err error) error { 184 if utils.IsUbuntu() { 185 return fmt.Errorf("%v\n%s", err, installLxcUbuntu) 186 } 187 return fmt.Errorf("%v\n%s", err, installLxcGeneric) 188 }