github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/provider/local/config.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 "fmt" 8 "os" 9 "path/filepath" 10 11 "github.com/juju/schema" 12 "gopkg.in/juju/environschema.v1" 13 14 "github.com/juju/juju/agent" 15 "github.com/juju/juju/container/kvm" 16 "github.com/juju/juju/container/lxc" 17 "github.com/juju/juju/environs/config" 18 "github.com/juju/juju/instance" 19 ) 20 21 var checkIfRoot = func() bool { 22 return os.Getuid() == 0 23 } 24 25 // Attribute keys 26 const ( 27 BootstrapIpKey = "bootstrap-ip" 28 ContainerKey = "container" 29 NamespaceKey = "namespace" 30 NetworkBridgeKey = "network-bridge" 31 RootDirKey = "root-dir" 32 StoragePortKey = "storage-port" 33 ) 34 35 // configSchema defines the schema for the configuration attributes 36 // defined by the local provider. 37 var configSchema = environschema.Fields{ 38 RootDirKey: { 39 Description: `The directory that is used for the storage files and database. The default location is $JUJU_HOME/<env-name>. $JUJU_HOME defaults to ~/.juju. Override if needed.`, 40 Type: environschema.Tstring, 41 Example: "~/.juju/local", 42 }, 43 BootstrapIpKey: { 44 Description: `The IP address of the bootstrap machine`, 45 Type: environschema.Tstring, 46 Group: environschema.JujuGroup, 47 }, 48 NetworkBridgeKey: { 49 Description: `The name of the LXC network bridge to use. Override if the default LXC network bridge is different.`, 50 Type: environschema.Tstring, 51 }, 52 ContainerKey: { 53 Description: `The kind of container to use for machines`, 54 Type: environschema.Tstring, 55 Values: []interface{}{ 56 string(instance.LXC), 57 string(instance.KVM), 58 }, 59 }, 60 StoragePortKey: { 61 Description: `The port where the local provider starts the HTTP file server. Override the value if you have multiple local providers, or if the default port is used by another program.`, 62 Type: environschema.Tint, 63 }, 64 NamespaceKey: { 65 Description: `The name space to use for local provider resources. Override if you have multiple local providers`, 66 Type: environschema.Tstring, 67 }, 68 } 69 70 var ( 71 configFields = func() schema.Fields { 72 fs, _, err := configSchema.ValidationSchema() 73 if err != nil { 74 panic(err) 75 } 76 return fs 77 }() 78 // The port defaults below are not entirely arbitrary. Local user web 79 // frameworks often use 8000 or 8080, so I didn't want to use either of 80 // these, but did want the familiarity of using something in the 8000 81 // range. 82 configDefaults = schema.Defaults{ 83 RootDirKey: "", 84 NetworkBridgeKey: "", 85 ContainerKey: string(instance.LXC), 86 BootstrapIpKey: schema.Omit, 87 StoragePortKey: 8040, 88 NamespaceKey: "", 89 } 90 ) 91 92 type environConfig struct { 93 *config.Config 94 attrs map[string]interface{} 95 } 96 97 func newEnvironConfig(config *config.Config, attrs map[string]interface{}) *environConfig { 98 return &environConfig{ 99 Config: config, 100 attrs: attrs, 101 } 102 } 103 104 // Since it is technically possible for two different users on one machine to 105 // have the same local provider name, we need to have a simple way to 106 // namespace the file locations, but more importantly the containers. 107 func (c *environConfig) namespace() string { 108 return c.attrs[NamespaceKey].(string) 109 } 110 111 func (c *environConfig) rootDir() string { 112 return c.attrs[RootDirKey].(string) 113 } 114 115 func (c *environConfig) container() instance.ContainerType { 116 return instance.ContainerType(c.attrs[ContainerKey].(string)) 117 } 118 119 // setDefaultNetworkBridge sets default network bridge if none is 120 // provided. Default network bridge varies based on container type. 121 func (c *environConfig) setDefaultNetworkBridge() { 122 name := c.networkBridge() 123 switch c.container() { 124 case instance.LXC: 125 if name == "" { 126 name = lxc.DefaultLxcBridge 127 } 128 case instance.KVM: 129 if name == "" { 130 name = kvm.DefaultKvmBridge 131 } 132 } 133 c.attrs[NetworkBridgeKey] = name 134 } 135 136 func (c *environConfig) networkBridge() string { 137 // We don't care if it's not a string, because Validate takes care 138 // of that. 139 return c.attrs[NetworkBridgeKey].(string) 140 } 141 142 func (c *environConfig) storageDir() string { 143 return filepath.Join(c.rootDir(), "storage") 144 } 145 146 func (c *environConfig) mongoDir() string { 147 return filepath.Join(c.rootDir(), "db") 148 } 149 150 func (c *environConfig) logDir() string { 151 return fmt.Sprintf("%s-%s", agent.DefaultPaths.LogDir, c.namespace()) 152 } 153 154 // bootstrapIPAddress returns the IP address of the bootstrap machine. 155 // As of 1.18 this is only set inside the environment, and not in the 156 // .jenv file. 157 func (c *environConfig) bootstrapIPAddress() string { 158 addr, _ := c.attrs[BootstrapIpKey].(string) 159 return addr 160 } 161 162 func (c *environConfig) stateServerAddr() string { 163 return fmt.Sprintf("localhost:%d", c.Config.APIPort()) 164 } 165 166 func (c *environConfig) storagePort() int { 167 return c.attrs[StoragePortKey].(int) 168 } 169 170 func (c *environConfig) storageAddr() string { 171 return fmt.Sprintf("%s:%d", c.bootstrapIPAddress(), c.storagePort()) 172 } 173 174 func (c *environConfig) configFile(filename string) string { 175 return filepath.Join(c.rootDir(), filename) 176 } 177 178 func (c *environConfig) createDirs() error { 179 for _, dirname := range []string{ 180 c.storageDir(), 181 c.mongoDir(), 182 } { 183 logger.Tracef("creating directory %s", dirname) 184 if err := os.MkdirAll(dirname, 0755); err != nil { 185 return err 186 } 187 } 188 return nil 189 }