Adding servicing update to postRunProcessing for Windows containers.
This change enables the workflow of finishing installing Windows OS updates in the container after it has completed running, via a special servicing container. Signed-off-by: Stefan J. Wernli <swernli@microsoft.com>
This commit is contained in:
parent
e974eadd94
commit
da92dad59f
9 changed files with 128 additions and 9 deletions
|
@ -16,9 +16,21 @@ func platformConstructExitStatus(e libcontainerd.StateInfo) *container.ExitStatu
|
|||
|
||||
// postRunProcessing perfoms any processing needed on the container after it has stopped.
|
||||
func (daemon *Daemon) postRunProcessing(container *container.Container, e libcontainerd.StateInfo) error {
|
||||
//TODO Windows - handle update processing here...
|
||||
if e.UpdatePending {
|
||||
return fmt.Errorf("Windows: Update handling not implemented.")
|
||||
spec, err := daemon.createSpec(container)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
servicingOption := &libcontainerd.ServicingOption{
|
||||
IsServicing: true,
|
||||
}
|
||||
|
||||
// Create a new servicing container, which will start, complete the update, and merge back the
|
||||
// results if it succeeded, all as part of the below function call.
|
||||
if err := daemon.containerd.Create((container.ID + "_servicing"), *spec, servicingOption); err != nil {
|
||||
return fmt.Errorf("Post-run update servicing failed: %s", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ source 'hack/.vendor-helpers.sh'
|
|||
|
||||
# the following lines are in sorted order, FYI
|
||||
clone git github.com/Azure/go-ansiterm 70b2c90b260171e829f1ebd7c17f600c11858dbe
|
||||
clone git github.com/Microsoft/hcsshim v0.2.1
|
||||
clone git github.com/Microsoft/hcsshim v0.2.2
|
||||
clone git github.com/Microsoft/go-winio v0.3.0
|
||||
clone git github.com/Sirupsen/logrus v0.9.0 # logrus is a common dependency among multiple deps
|
||||
clone git github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a
|
||||
|
|
|
@ -96,6 +96,7 @@ type containerInit struct {
|
|||
HvPartition bool // True if it a Hyper-V Container
|
||||
EndpointList []string // List of networking endpoints to be attached to container
|
||||
HvRuntime *hvRuntime // Hyper-V container settings
|
||||
Servicing bool // True if this container is for servicing
|
||||
}
|
||||
|
||||
// defaultOwner is a tag passed to HCS to allow it to differentiate between
|
||||
|
@ -157,6 +158,13 @@ func (clnt *client) Create(containerID string, spec Spec, options ...CreateOptio
|
|||
}
|
||||
}
|
||||
|
||||
for _, option := range options {
|
||||
if s, ok := option.(*ServicingOption); ok {
|
||||
cu.Servicing = s.IsServicing
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if cu.HvPartition {
|
||||
cu.SandboxPath = filepath.Dir(spec.Windows.LayerFolder)
|
||||
} else {
|
||||
|
|
|
@ -35,13 +35,32 @@ func (ctr *container) newProcess(friendlyName string) *process {
|
|||
func (ctr *container) start() error {
|
||||
var err error
|
||||
|
||||
// Start the container
|
||||
// Start the container. If this is a servicing container, this call will block
|
||||
// until the container is done with the servicing execution.
|
||||
logrus.Debugln("Starting container ", ctr.containerID)
|
||||
if err = hcsshim.StartComputeSystem(ctr.containerID); err != nil {
|
||||
logrus.Errorf("Failed to start compute system: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
for _, option := range ctr.options {
|
||||
if s, ok := option.(*ServicingOption); ok && s.IsServicing {
|
||||
// Since the servicing operation is complete when StartCommputeSystem returns without error,
|
||||
// we can shutdown (which triggers merge) and exit early.
|
||||
const shutdownTimeout = 5 * 60 * 1000 // 4 minutes
|
||||
const terminateTimeout = 1 * 60 * 1000 // 1 minute
|
||||
if err := hcsshim.ShutdownComputeSystem(ctr.containerID, shutdownTimeout, ""); err != nil {
|
||||
logrus.Errorf("Failed during cleanup of servicing container: %s", err)
|
||||
// Terminate the container, ignoring errors.
|
||||
if err2 := hcsshim.TerminateComputeSystem(ctr.containerID, terminateTimeout, ""); err2 != nil {
|
||||
logrus.Errorf("Failed to terminate container %s after shutdown failure: %q", ctr.containerID, err2)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
createProcessParms := hcsshim.CreateProcessParams{
|
||||
EmulateConsole: ctr.ociSpec.Process.Terminal,
|
||||
WorkingDirectory: ctr.ociSpec.Process.Cwd,
|
||||
|
@ -149,10 +168,13 @@ func (ctr *container) waitExit(pid uint32, processFriendlyName string, isFirstPr
|
|||
// If this is the init process, always call into vmcompute.dll to
|
||||
// shutdown the container after we have completed.
|
||||
if isFirstProcessToStart {
|
||||
|
||||
// TODO Windows - add call into hcsshim to check if an update
|
||||
// is pending once that is available.
|
||||
//si.UpdatePending = CHECK IF UPDATE NEEDED
|
||||
propertyCheckFlag := 1 // Include update pending check.
|
||||
csProperties, err := hcsshim.GetComputeSystemProperties(ctr.containerID, uint32(propertyCheckFlag))
|
||||
if err != nil {
|
||||
logrus.Warnf("GetComputeSystemProperties failed (container may have been killed): %s", err)
|
||||
} else {
|
||||
si.UpdatePending = csProperties.AreUpdatesPending
|
||||
}
|
||||
|
||||
logrus.Debugf("Shutting down container %s", ctr.containerID)
|
||||
// Explicit timeout here rather than hcsshim.TimeoutInfinte to avoid a
|
||||
|
|
|
@ -22,7 +22,8 @@ type StateInfo struct {
|
|||
CommonStateInfo
|
||||
|
||||
// Platform specific StateInfo
|
||||
UpdatePending bool
|
||||
|
||||
UpdatePending bool // Indicates that there are some update operations pending that should be completed by a servicing container.
|
||||
}
|
||||
|
||||
// Stats contains a stats properties from containerd.
|
||||
|
@ -30,3 +31,9 @@ type Stats struct{}
|
|||
|
||||
// Resources defines updatable container resource values.
|
||||
type Resources struct{}
|
||||
|
||||
// ServicingOption is an empty CreateOption with a no-op application that siginifies
|
||||
// the container needs to be use for a Windows servicing operation.
|
||||
type ServicingOption struct {
|
||||
IsServicing bool
|
||||
}
|
||||
|
|
|
@ -14,3 +14,8 @@ func setupEnvironmentVariables(a []string) map[string]string {
|
|||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// Apply for a servicing option is a no-op.
|
||||
func (s *ServicingOption) Apply(interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
|
43
vendor/src/github.com/Microsoft/hcsshim/getcomputesystemproperties.go
vendored
Normal file
43
vendor/src/github.com/Microsoft/hcsshim/getcomputesystemproperties.go
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
package hcsshim
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
)
|
||||
|
||||
// ComputeSystemProperties is a struct describing the returned properties.
|
||||
type ComputeSystemProperties struct {
|
||||
ID string
|
||||
Name string
|
||||
Stopped bool
|
||||
AreUpdatesPending bool
|
||||
}
|
||||
|
||||
// GetComputeSystemProperties gets the properties for the compute system with the given ID.
|
||||
func GetComputeSystemProperties(id string, flags uint32) (ComputeSystemProperties, error) {
|
||||
title := "hcsshim::GetComputeSystemProperties "
|
||||
|
||||
csProps := ComputeSystemProperties{
|
||||
Stopped: false,
|
||||
AreUpdatesPending: false,
|
||||
}
|
||||
|
||||
logrus.Debugf("Calling proc")
|
||||
var buffer *uint16
|
||||
err := getComputeSystemProperties(id, flags, &buffer)
|
||||
if err != nil {
|
||||
err = makeError(err, title, "")
|
||||
logrus.Error(err)
|
||||
return csProps, err
|
||||
}
|
||||
propData := convertAndFreeCoTaskMemString(buffer)
|
||||
logrus.Debugf(title+" - succeeded output=%s", propData)
|
||||
|
||||
if err = json.Unmarshal([]byte(propData), &csProps); err != nil {
|
||||
logrus.Error(err)
|
||||
return csProps, err
|
||||
}
|
||||
|
||||
return csProps, nil
|
||||
}
|
|
@ -48,6 +48,7 @@ import (
|
|||
//sys terminateComputeSystem(id string) (hr error) = vmcompute.TerminateComputeSystem?
|
||||
//sys terminateProcessInComputeSystem(id string, pid uint32) (hr error) = vmcompute.TerminateProcessInComputeSystem?
|
||||
//sys waitForProcessInComputeSystem(id string, pid uint32, timeout uint32, exitCode *uint32) (hr error) = vmcompute.WaitForProcessInComputeSystem?
|
||||
//sys getComputeSystemProperties(id string, flags uint32, properties **uint16) (hr error) = vmcompute.GetComputeSystemProperties?
|
||||
|
||||
//sys _hnsCall(method string, path string, object string, response **uint16) (hr error) = vmcompute.HNSCall?
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ var (
|
|||
procTerminateComputeSystem = modvmcompute.NewProc("TerminateComputeSystem")
|
||||
procTerminateProcessInComputeSystem = modvmcompute.NewProc("TerminateProcessInComputeSystem")
|
||||
procWaitForProcessInComputeSystem = modvmcompute.NewProc("WaitForProcessInComputeSystem")
|
||||
procGetComputeSystemProperties = modvmcompute.NewProc("GetComputeSystemProperties")
|
||||
procHNSCall = modvmcompute.NewProc("HNSCall")
|
||||
)
|
||||
|
||||
|
@ -713,6 +714,26 @@ func _waitForProcessInComputeSystem(id *uint16, pid uint32, timeout uint32, exit
|
|||
return
|
||||
}
|
||||
|
||||
func getComputeSystemProperties(id string, flags uint32, properties **uint16) (hr error) {
|
||||
var _p0 *uint16
|
||||
_p0, hr = syscall.UTF16PtrFromString(id)
|
||||
if hr != nil {
|
||||
return
|
||||
}
|
||||
return _getComputeSystemProperties(_p0, flags, properties)
|
||||
}
|
||||
|
||||
func _getComputeSystemProperties(id *uint16, flags uint32, properties **uint16) (hr error) {
|
||||
if hr = procGetComputeSystemProperties.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procGetComputeSystemProperties.Addr(), 3, uintptr(unsafe.Pointer(id)), uintptr(flags), uintptr(unsafe.Pointer(properties)))
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func _hnsCall(method string, path string, object string, response **uint16) (hr error) {
|
||||
var _p0 *uint16
|
||||
_p0, hr = syscall.UTF16PtrFromString(method)
|
||||
|
|
Loading…
Reference in a new issue