github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/cloudconfig/cloudinit/cloudinit_centos.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Copyright 2015 Cloudbase Solutions SRL 3 // Licensed under the AGPLv3, see LICENCE file for details. 4 5 package cloudinit 6 7 import ( 8 "fmt" 9 "strings" 10 11 "github.com/juju/juju/feature" 12 "github.com/juju/utils/featureflag" 13 "github.com/juju/utils/packaging" 14 "github.com/juju/utils/packaging/config" 15 "github.com/juju/utils/proxy" 16 "gopkg.in/yaml.v2" 17 ) 18 19 // centOSCloudConfig is the cloudconfig type specific to CentOS machines. 20 // It simply contains a cloudConfig and adds the package management related 21 // methods for CentOS, which are mostly modeled as runcmds. 22 // It implements the cloudinit.Config interface. 23 type centOSCloudConfig struct { 24 *cloudConfig 25 } 26 27 // SetPackageProxy is defined on the PackageProxyConfig interface. 28 func (cfg *centOSCloudConfig) SetPackageProxy(url string) { 29 cfg.SetAttr("package_proxy", url) 30 } 31 32 // addPackageProxyCmd is a helper function which returns the corresponding runcmd 33 // to apply the package proxy settings on a CentOS machine. 34 func addPackageProxyCmd(cfg CloudConfig, url string) string { 35 return fmt.Sprintf("/bin/echo 'proxy=%s' >> /etc/yum.conf", url) 36 } 37 38 // UnsetPackageProxy is defined on the PackageProxyConfig interface. 39 func (cfg *centOSCloudConfig) UnsetPackageProxy() { 40 cfg.UnsetAttr("package_proxy") 41 } 42 43 // PackageProxy is defined on the PackageProxyConfig interface. 44 func (cfg *centOSCloudConfig) PackageProxy() string { 45 proxy, _ := cfg.attrs["package_proxy"].(string) 46 return proxy 47 } 48 49 // SetPackageMirror is defined on the PackageMirrorConfig interface. 50 func (cfg *centOSCloudConfig) SetPackageMirror(url string) { 51 cfg.SetAttr("package_mirror", url) 52 } 53 54 // addPackageMirrorCmd is a helper function that returns the corresponding runcmds 55 // to apply the package mirror settings on a CentOS machine. 56 func addPackageMirrorCmd(cfg CloudConfig, url string) string { 57 return fmt.Sprintf(config.ReplaceCentOSMirror, url) 58 } 59 60 // UnsetPackageMirror is defined on the PackageMirrorConfig interface. 61 func (cfg *centOSCloudConfig) UnsetPackageMirror() { 62 cfg.UnsetAttr("package_mirror") 63 } 64 65 // PackageMirror is defined on the PackageMirrorConfig interface. 66 func (cfg *centOSCloudConfig) PackageMirror() string { 67 mirror, _ := cfg.attrs["package_mirror"].(string) 68 return mirror 69 } 70 71 // AddPackageSource is defined on the PackageSourcesConfig interface. 72 func (cfg *centOSCloudConfig) AddPackageSource(src packaging.PackageSource) { 73 cfg.attrs["package_sources"] = append(cfg.PackageSources(), src) 74 } 75 76 // PackageSources is defined on the PackageSourcesConfig interface. 77 func (cfg *centOSCloudConfig) PackageSources() []packaging.PackageSource { 78 sources, _ := cfg.attrs["package_sources"].([]packaging.PackageSource) 79 return sources 80 } 81 82 // AddPackagePreferences is defined on the PackageSourcesConfig interface. 83 func (cfg *centOSCloudConfig) AddPackagePreferences(prefs packaging.PackagePreferences) { 84 // TODO (aznashwan): research a way of using yum-priorities in the 85 // context of a single package and implement the appropriate runcmds. 86 } 87 88 // PackagePreferences is defined on the PackageSourcesConfig interface. 89 func (cfg *centOSCloudConfig) PackagePreferences() []packaging.PackagePreferences { 90 // TODO (aznashwan): add this when priorities in yum make sense. 91 return []packaging.PackagePreferences{} 92 } 93 94 // Render is defined on the the Renderer interface. 95 func (cfg *centOSCloudConfig) RenderYAML() ([]byte, error) { 96 // Save the fields that we will modify 97 var oldruncmds []string 98 oldruncmds = copyStringSlice(cfg.RunCmds()) 99 100 // check for package proxy setting and add commands: 101 var proxy string 102 if proxy = cfg.PackageProxy(); proxy != "" { 103 cfg.AddRunCmd(addPackageProxyCmd(cfg, proxy)) 104 cfg.UnsetPackageProxy() 105 } 106 107 // check for package mirror settings and add commands: 108 var mirror string 109 if mirror = cfg.PackageMirror(); mirror != "" { 110 cfg.AddRunCmd(addPackageMirrorCmd(cfg, mirror)) 111 cfg.UnsetPackageMirror() 112 } 113 114 // add appropriate commands for package sources configuration: 115 srcs := cfg.PackageSources() 116 for _, src := range srcs { 117 cfg.AddScripts(addPackageSourceCmds(cfg, src)...) 118 } 119 cfg.UnsetAttr("package_sources") 120 121 data, err := yaml.Marshal(cfg.attrs) 122 if err != nil { 123 return nil, err 124 } 125 126 // Restore the modified fields 127 cfg.SetPackageProxy(proxy) 128 cfg.SetPackageMirror(mirror) 129 cfg.SetAttr("package_sources", srcs) 130 if oldruncmds != nil { 131 cfg.SetAttr("runcmd", oldruncmds) 132 } else { 133 cfg.UnsetAttr("runcmd") 134 } 135 136 return append([]byte("#cloud-config\n"), data...), nil 137 } 138 139 func (cfg *centOSCloudConfig) RenderScript() (string, error) { 140 return renderScriptCommon(cfg) 141 } 142 143 // AddCloudArchiveCloudTools is defined on the AdvancedPackagingConfig. 144 func (cfg *centOSCloudConfig) AddCloudArchiveCloudTools() { 145 src, pref := config.GetCloudArchiveSource(cfg.series) 146 cfg.AddPackageSource(src) 147 cfg.AddPackagePreferences(pref) 148 } 149 150 func (cfg *centOSCloudConfig) getCommandsForAddingPackages() ([]string, error) { 151 var cmds []string 152 153 if newMirror := cfg.PackageMirror(); newMirror != "" { 154 cmds = append(cmds, LogProgressCmd("Changing package mirror does not yet work on CentOS")) 155 // TODO(bogdanteleaga, aznashwan): This should work after a further PR 156 // where we add more mirrror options values to environs.Config 157 cmds = append(cmds, addPackageMirrorCmd(cfg, newMirror)) 158 } 159 160 for _, src := range cfg.PackageSources() { 161 // TODO(bogdanteleaga. aznashwan): Keys are usually offered by repositories, and you need to 162 // accept them. Check how this can be done non interactively. 163 cmds = append(cmds, LogProgressCmd("Adding yum repository: %s", src.URL)) 164 cmds = append(cmds, cfg.paccmder.AddRepositoryCmd(src.URL)) 165 } 166 167 // TODO(bogdanteleaga. aznashwan): Research what else needs to be done here 168 169 // Define the "package_get_loop" function 170 cmds = append(cmds, config.PackageManagerLoopFunction) 171 172 if cfg.SystemUpdate() { 173 cmds = append(cmds, LogProgressCmd("Running yum update")) 174 cmds = append(cmds, "package_manager_loop "+cfg.paccmder.UpdateCmd()) 175 } 176 if cfg.SystemUpgrade() { 177 cmds = append(cmds, LogProgressCmd("Running yum upgrade")) 178 cmds = append(cmds, "package_manager_loop "+cfg.paccmder.UpgradeCmd()) 179 } 180 181 pkgs := cfg.Packages() 182 if len(pkgs) > 0 { 183 cmds = append([]string{LogProgressCmd(fmt.Sprintf("Installing %s", strings.Join(pkgs, ", ")))}, cmds...) 184 } 185 for _, pkg := range pkgs { 186 cmds = append(cmds, "package_manager_loop "+cfg.paccmder.InstallCmd(pkg)) 187 } 188 return cmds, nil 189 } 190 191 // AddPackageCommands is defined on the AdvancedPackagingConfig interface. 192 func (cfg *centOSCloudConfig) AddPackageCommands( 193 packageProxySettings proxy.Settings, 194 packageMirror string, 195 addUpdateScripts bool, 196 addUpgradeScripts bool, 197 ) { 198 addPackageCommandsCommon( 199 cfg, 200 packageProxySettings, 201 packageMirror, 202 addUpdateScripts, 203 addUpgradeScripts, 204 cfg.series, 205 ) 206 } 207 208 // addRequiredPackages is defined on the AdvancedPackagingConfig interface. 209 func (cfg *centOSCloudConfig) addRequiredPackages() { 210 packages := []string{ 211 "curl", 212 "bridge-utils", 213 "cloud-utils", 214 "nmap-ncat", 215 "tmux", 216 } 217 if featureflag.Enabled(feature.DeveloperMode) { 218 packages = append(packages, "socat") 219 } 220 221 // The required packages need to come from the correct repo. 222 // For CentOS 7, this requires an rpm cloud archive be up. 223 // In the event of the addition of such a repository, its addition should 224 // happen in the utils/packaging/config package whilst leaving the below 225 // code untouched. 226 for _, pack := range packages { 227 if config.SeriesRequiresCloudArchiveTools(cfg.series) && cfg.pacconfer.IsCloudArchivePackage(pack) { 228 cfg.AddPackage(strings.Join(cfg.pacconfer.ApplyCloudArchiveTarget(pack), " ")) 229 } else { 230 cfg.AddPackage(pack) 231 } 232 } 233 } 234 235 //TODO(bogdanteleaga, aznashwan): On ubuntu when we render the conf as yaml we 236 //have apt_proxy and when we render it as bash we use the equivalent of this. 237 //However on centOS even when rendering the YAML we use a helper function 238 //addPackageProxyCmds. Research if calling the same is fine. 239 func (cfg *centOSCloudConfig) updateProxySettings(proxySettings proxy.Settings) { 240 }