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