github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/upgradeseries/upgrader.go (about) 1 // Copyright 2018 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package upgradeseries 5 6 import ( 7 "strings" 8 9 "github.com/juju/errors" 10 11 "github.com/juju/juju/juju/paths" 12 "github.com/juju/juju/service" 13 "github.com/juju/juju/service/systemd" 14 "github.com/juju/juju/version" 15 ) 16 17 //go:generate mockgen -package mocks -destination mocks/servicemanager_mock.go github.com/juju/juju/service SystemdServiceManager 18 19 var ( 20 systemdDir = systemd.EtcSystemdDir 21 systemdMultiUserDir = systemd.EtcSystemdMultiUserDir 22 ) 23 24 // Upgrader describes methods required to perform file-system manipulation in 25 // preparation for upgrading the host Ubuntu version. 26 type Upgrader interface { 27 PerformUpgrade() error 28 } 29 30 // upgrader implements the Upgrader interface for a specific (from/to) upgrade 31 // of the host Ubuntu version, via the systemd service manager. 32 type upgrader struct { 33 logger Logger 34 35 fromSeries string 36 fromInit string 37 toSeries string 38 toInit string 39 40 machineAgent string 41 unitAgents []string 42 43 manager service.SystemdServiceManager 44 } 45 46 // NewUpgrader uses the input function to determine the series that should be 47 // supported, and returns a reference to a new Upgrader that supports it. 48 func NewUpgrader(toSeries string, manager service.SystemdServiceManager, logger Logger) (Upgrader, error) { 49 fromSeries, err := hostSeries() 50 if err != nil { 51 return nil, errors.Trace(err) 52 } 53 fromInit, err := service.VersionInitSystem(fromSeries) 54 if err != nil { 55 return nil, errors.Trace(err) 56 } 57 58 toInit, err := service.VersionInitSystem(toSeries) 59 if err != nil { 60 return nil, errors.Trace(err) 61 } 62 63 return &upgrader{ 64 logger: logger, 65 fromSeries: fromSeries, 66 fromInit: fromInit, 67 toSeries: toSeries, 68 toInit: toInit, 69 manager: manager, 70 }, nil 71 } 72 73 // PerformUpgrade writes Juju binaries and service files that allow the machine 74 // and unit agents to run on the target version of Ubuntu. 75 func (u *upgrader) PerformUpgrade() error { 76 if err := u.populateAgents(); err != nil { 77 return errors.Trace(err) 78 } 79 80 if err := u.ensureSystemdFiles(); err != nil { 81 return errors.Trace(err) 82 } 83 84 return errors.Trace(u.ensureAgentBinaries()) 85 } 86 87 // populateAgents discovers and sets the names of the machine and unit agents. 88 // If there are any other agents determined, a warning is logged to notify that 89 // they are being skipped from the upgrade process. 90 func (u *upgrader) populateAgents() (err error) { 91 var unknown []string 92 u.machineAgent, u.unitAgents, unknown, err = u.manager.FindAgents(paths.NixDataDir) 93 if err != nil { 94 return errors.Trace(err) 95 } 96 if len(unknown) > 0 { 97 u.logger.Warningf("skipping agents not of type machine or unit: %s", strings.Join(unknown, ", ")) 98 } 99 return nil 100 } 101 102 // ensureSystemdFiles determines whether re-writing service files to target 103 // systemd is required. If it is, the necessary changes are invoked via the 104 // service manager. 105 func (u *upgrader) ensureSystemdFiles() error { 106 if u.fromInit == service.InitSystemSystemd || u.toInit != service.InitSystemSystemd { 107 return nil 108 } 109 110 services, links, failed, err := u.manager.WriteSystemdAgents( 111 u.machineAgent, u.unitAgents, paths.NixDataDir, systemdDir, systemdMultiUserDir) 112 113 if len(services) > 0 { 114 u.logger.Infof("agents written and linked by systemd: %s", strings.Join(services, ", ")) 115 } 116 if len(links) > 0 { 117 u.logger.Infof("agents written and linked by symlink: %s", strings.Join(links, ", ")) 118 } 119 120 return errors.Annotatef(err, "failed to write agents: %s", strings.Join(failed, ", ")) 121 } 122 123 // ensureAgentBinaries ensures that the jujud binary and links exist in the 124 // right tools path for the target OS series, and that individual agents use 125 // those files. 126 func (u *upgrader) ensureAgentBinaries() error { 127 if err := u.manager.CopyAgentBinary( 128 u.machineAgent, u.unitAgents, paths.NixDataDir, u.toSeries, u.fromSeries, version.Current); err != nil { 129 return errors.Trace(err) 130 } 131 132 u.logger.Infof("copied agent binaries for series %q", u.toSeries) 133 return nil 134 }