mirror of https://github.com/docker/docs.git
				
				
				
			
		
			
				
	
	
		
			234 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			234 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Go
		
	
	
	
| package provision
 | |
| 
 | |
| import (
 | |
| 	"bufio"
 | |
| 	"fmt"
 | |
| 	"net/http"
 | |
| 	"strings"
 | |
| 
 | |
| 	"github.com/docker/machine/commands/mcndirs"
 | |
| 	"github.com/docker/machine/libmachine/auth"
 | |
| 	"github.com/docker/machine/libmachine/drivers"
 | |
| 	"github.com/docker/machine/libmachine/engine"
 | |
| 	"github.com/docker/machine/libmachine/log"
 | |
| 	"github.com/docker/machine/libmachine/mcnutils"
 | |
| 	"github.com/docker/machine/libmachine/provision/pkgaction"
 | |
| 	"github.com/docker/machine/libmachine/provision/serviceaction"
 | |
| 	"github.com/docker/machine/libmachine/state"
 | |
| 	"github.com/docker/machine/libmachine/swarm"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	versionsURL  = "http://releases.rancher.com/os/versions.yml"
 | |
| 	isoURL       = "https://github.com/rancherio/os/releases/download/%s/machine-rancheros.iso"
 | |
| 	hostnameTmpl = `sudo mkdir -p /var/lib/rancher/conf/cloud-config.d/  
 | |
| sudo tee /var/lib/rancher/conf/cloud-config.d/machine-hostname.yml << EOF
 | |
| #cloud-config
 | |
| 
 | |
| hostname: %s
 | |
| EOF
 | |
| `
 | |
| )
 | |
| 
 | |
| func init() {
 | |
| 	Register("RancherOS", &RegisteredProvisioner{
 | |
| 		New: NewRancherProvisioner,
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func NewRancherProvisioner(d drivers.Driver) Provisioner {
 | |
| 	return &RancherProvisioner{
 | |
| 		GenericProvisioner{
 | |
| 			SSHCommander:      GenericSSHCommander{Driver: d},
 | |
| 			DockerOptionsDir:  "/var/lib/rancher/conf",
 | |
| 			DaemonOptionsFile: "/var/lib/rancher/conf/docker",
 | |
| 			OsReleaseID:       "rancheros",
 | |
| 			Driver:            d,
 | |
| 		},
 | |
| 	}
 | |
| }
 | |
| 
 | |
| type RancherProvisioner struct {
 | |
| 	GenericProvisioner
 | |
| }
 | |
| 
 | |
| func (provisioner *RancherProvisioner) String() string {
 | |
| 	return "rancheros"
 | |
| }
 | |
| 
 | |
| func (provisioner *RancherProvisioner) Service(name string, action serviceaction.ServiceAction) error {
 | |
| 	command := fmt.Sprintf("sudo system-docker %s %s", action.String(), name)
 | |
| 
 | |
| 	if _, err := provisioner.SSHCommand(command); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (provisioner *RancherProvisioner) Package(name string, action pkgaction.PackageAction) error {
 | |
| 	var packageAction string
 | |
| 
 | |
| 	if name == "docker" && action == pkgaction.Upgrade {
 | |
| 		return provisioner.upgrade()
 | |
| 	}
 | |
| 
 | |
| 	switch action {
 | |
| 	case pkgaction.Install:
 | |
| 		packageAction = "enabled"
 | |
| 	case pkgaction.Remove:
 | |
| 		packageAction = "disable"
 | |
| 	case pkgaction.Upgrade:
 | |
| 		// TODO: support upgrade
 | |
| 		packageAction = "upgrade"
 | |
| 	}
 | |
| 
 | |
| 	command := fmt.Sprintf("sudo rancherctl service %s %s", packageAction, name)
 | |
| 
 | |
| 	if _, err := provisioner.SSHCommand(command); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (provisioner *RancherProvisioner) Provision(swarmOptions swarm.Options, authOptions auth.Options, engineOptions engine.Options) error {
 | |
| 	provisioner.SwarmOptions = swarmOptions
 | |
| 	provisioner.AuthOptions = authOptions
 | |
| 	provisioner.EngineOptions = engineOptions
 | |
| 	swarmOptions.Env = engineOptions.Env
 | |
| 
 | |
| 	if provisioner.EngineOptions.StorageDriver == "" {
 | |
| 		provisioner.EngineOptions.StorageDriver = "overlay"
 | |
| 	} else if provisioner.EngineOptions.StorageDriver != "overlay" {
 | |
| 		return fmt.Errorf("Unsupported storage driver: %s", provisioner.EngineOptions.StorageDriver)
 | |
| 	}
 | |
| 
 | |
| 	log.Debugf("Setting hostname %s", provisioner.Driver.GetMachineName())
 | |
| 	if err := provisioner.SetHostname(provisioner.Driver.GetMachineName()); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	for _, pkg := range provisioner.Packages {
 | |
| 		log.Debugf("Installing package %s", pkg)
 | |
| 		if err := provisioner.Package(pkg, pkgaction.Install); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	log.Debugf("Preparing certificates")
 | |
| 	provisioner.AuthOptions = setRemoteAuthOptions(provisioner)
 | |
| 
 | |
| 	log.Debugf("Setting up certificates")
 | |
| 	if err := ConfigureAuth(provisioner); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	log.Debugf("Configuring swarm")
 | |
| 	if err := configureSwarm(provisioner, swarmOptions, provisioner.AuthOptions); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (provisioner *RancherProvisioner) SetHostname(hostname string) error {
 | |
| 	// /etc/hosts is bind mounted from Docker, this is hack to that the generic provisioner doesn't try to mv /etc/hosts
 | |
| 	if _, err := provisioner.SSHCommand("sed /127.0.1.1/d /etc/hosts > /tmp/hosts && cat /tmp/hosts | sudo tee /etc/hosts"); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	if err := provisioner.GenericProvisioner.SetHostname(hostname); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	if _, err := provisioner.SSHCommand(fmt.Sprintf(hostnameTmpl, hostname)); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (provisioner *RancherProvisioner) upgrade() error {
 | |
| 	switch provisioner.Driver.DriverName() {
 | |
| 	case "virtualbox":
 | |
| 		return provisioner.upgradeIso()
 | |
| 	default:
 | |
| 		log.Infof("Running upgrade")
 | |
| 		if _, err := provisioner.SSHCommand("sudo rancherctl os upgrade -f --no-reboot"); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 
 | |
| 		log.Infof("Upgrade succeeded, rebooting")
 | |
| 		// ignore errors here because the SSH connection will close
 | |
| 		provisioner.SSHCommand("sudo reboot")
 | |
| 
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (provisioner *RancherProvisioner) upgradeIso() error {
 | |
| 	// Largely copied from Boot2Docker provisioner, we should find a way to share this code
 | |
| 	log.Info("Stopping machine to do the upgrade...")
 | |
| 
 | |
| 	if err := provisioner.Driver.Stop(); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	if err := mcnutils.WaitFor(drivers.MachineInState(provisioner.Driver, state.Stopped)); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	machineName := provisioner.GetDriver().GetMachineName()
 | |
| 
 | |
| 	log.Infof("Upgrading machine %s...", machineName)
 | |
| 
 | |
| 	// TODO: Ideally, we should not read from mcndirs directory at all.
 | |
| 	// The driver should be able to communicate how and where to place the
 | |
| 	// relevant files.
 | |
| 	b2dutils := mcnutils.NewB2dUtils(mcndirs.GetBaseDir())
 | |
| 
 | |
| 	url, err := provisioner.getLatestISOURL()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	if err := b2dutils.DownloadISOFromURL(url); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	// Copy the latest version of boot2docker ISO to the machine's directory
 | |
| 	if err := b2dutils.CopyIsoToMachineDir("", machineName); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	log.Infof("Starting machine back up...")
 | |
| 
 | |
| 	if err := provisioner.Driver.Start(); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	return mcnutils.WaitFor(drivers.MachineInState(provisioner.Driver, state.Running))
 | |
| }
 | |
| 
 | |
| func (provisioner *RancherProvisioner) getLatestISOURL() (string, error) {
 | |
| 	log.Debugf("Reading %s", versionsURL)
 | |
| 	resp, err := http.Get(versionsURL)
 | |
| 	if err != nil {
 | |
| 		return "", err
 | |
| 	}
 | |
| 	defer resp.Body.Close()
 | |
| 
 | |
| 	// Don't want to pull in yaml parser, we'll do this manually
 | |
| 	scanner := bufio.NewScanner(resp.Body)
 | |
| 	for scanner.Scan() {
 | |
| 		line := scanner.Text()
 | |
| 		if strings.HasPrefix(line, "current: ") {
 | |
| 			log.Debugf("Found %s", line)
 | |
| 			return fmt.Sprintf(isoURL, strings.Split(line, ":")[2]), err
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return "", fmt.Errorf("Failed to find current version")
 | |
| }
 |