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  }