Merge pull request #1371 from adrianreber/master
checkpoint: check if system supports pre-dumping
This commit is contained in:
commit
f8ce01dbdc
|
@ -535,6 +535,56 @@ func (c *linuxContainer) NotifyMemoryPressure(level PressureLevel) (<-chan struc
|
||||||
return notifyMemoryPressure(c.cgroupManager.GetPaths(), level)
|
return notifyMemoryPressure(c.cgroupManager.GetPaths(), level)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var criuFeatures *criurpc.CriuFeatures
|
||||||
|
|
||||||
|
func (c *linuxContainer) checkCriuFeatures(criuOpts *CriuOpts, rpcOpts *criurpc.CriuOpts, criuFeat *criurpc.CriuFeatures) error {
|
||||||
|
|
||||||
|
var t criurpc.CriuReqType
|
||||||
|
t = criurpc.CriuReqType_FEATURE_CHECK
|
||||||
|
|
||||||
|
if err := c.checkCriuVersion("1.8"); err != nil {
|
||||||
|
// Feature checking was introduced with CRIU 1.8.
|
||||||
|
// Ignore the feature check if an older CRIU version is used
|
||||||
|
// and just act as before.
|
||||||
|
// As all automated PR testing is done using CRIU 1.7 this
|
||||||
|
// code will not be tested by automated PR testing.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure the features we are looking for are really not from
|
||||||
|
// some previous check
|
||||||
|
criuFeatures = nil
|
||||||
|
|
||||||
|
req := &criurpc.CriuReq{
|
||||||
|
Type: &t,
|
||||||
|
// Theoretically this should not be necessary but CRIU
|
||||||
|
// segfaults if Opts is empty.
|
||||||
|
// Fixed in CRIU 2.12
|
||||||
|
Opts: rpcOpts,
|
||||||
|
Features: criuFeat,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := c.criuSwrk(nil, req, criuOpts, false)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Debugf("%s", err)
|
||||||
|
return fmt.Errorf("CRIU feature check failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Debugf("Feature check says: %s", criuFeatures)
|
||||||
|
missingFeatures := false
|
||||||
|
|
||||||
|
if *criuFeat.MemTrack && !*criuFeatures.MemTrack {
|
||||||
|
missingFeatures = true
|
||||||
|
logrus.Debugf("CRIU does not support MemTrack")
|
||||||
|
}
|
||||||
|
|
||||||
|
if missingFeatures {
|
||||||
|
return fmt.Errorf("CRIU is missing features")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// checkCriuVersion checks Criu version greater than or equal to minVersion
|
// checkCriuVersion checks Criu version greater than or equal to minVersion
|
||||||
func (c *linuxContainer) checkCriuVersion(minVersion string) error {
|
func (c *linuxContainer) checkCriuVersion(minVersion string) error {
|
||||||
var x, y, z, versionReq int
|
var x, y, z, versionReq int
|
||||||
|
@ -717,6 +767,14 @@ func (c *linuxContainer) Checkpoint(criuOpts *CriuOpts) error {
|
||||||
|
|
||||||
var t criurpc.CriuReqType
|
var t criurpc.CriuReqType
|
||||||
if criuOpts.PreDump {
|
if criuOpts.PreDump {
|
||||||
|
feat := criurpc.CriuFeatures{
|
||||||
|
MemTrack: proto.Bool(true),
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.checkCriuFeatures(criuOpts, &rpcOpts, &feat); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
t = criurpc.CriuReqType_PRE_DUMP
|
t = criurpc.CriuReqType_PRE_DUMP
|
||||||
} else {
|
} else {
|
||||||
t = criurpc.CriuReqType_DUMP
|
t = criurpc.CriuReqType_DUMP
|
||||||
|
@ -1018,16 +1076,21 @@ func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts *
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.Debugf("Using CRIU in %s mode", req.GetType().String())
|
logrus.Debugf("Using CRIU in %s mode", req.GetType().String())
|
||||||
val := reflect.ValueOf(req.GetOpts())
|
// In the case of criurpc.CriuReqType_FEATURE_CHECK req.GetOpts()
|
||||||
v := reflect.Indirect(val)
|
// should be empty. For older CRIU versions it still will be
|
||||||
for i := 0; i < v.NumField(); i++ {
|
// available but empty.
|
||||||
st := v.Type()
|
if req.GetType() != criurpc.CriuReqType_FEATURE_CHECK {
|
||||||
name := st.Field(i).Name
|
val := reflect.ValueOf(req.GetOpts())
|
||||||
if strings.HasPrefix(name, "XXX_") {
|
v := reflect.Indirect(val)
|
||||||
continue
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
st := v.Type()
|
||||||
|
name := st.Field(i).Name
|
||||||
|
if strings.HasPrefix(name, "XXX_") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
value := val.MethodByName("Get" + name).Call([]reflect.Value{})
|
||||||
|
logrus.Debugf("CRIU option %s with value %v", name, value[0])
|
||||||
}
|
}
|
||||||
value := val.MethodByName("Get" + name).Call([]reflect.Value{})
|
|
||||||
logrus.Debugf("CRIU option %s with value %v", name, value[0])
|
|
||||||
}
|
}
|
||||||
data, err := proto.Marshal(req)
|
data, err := proto.Marshal(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1063,6 +1126,10 @@ func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts *
|
||||||
|
|
||||||
t := resp.GetType()
|
t := resp.GetType()
|
||||||
switch {
|
switch {
|
||||||
|
case t == criurpc.CriuReqType_FEATURE_CHECK:
|
||||||
|
logrus.Debugf("Feature check says: %s", resp)
|
||||||
|
criuFeatures = resp.GetFeatures()
|
||||||
|
break
|
||||||
case t == criurpc.CriuReqType_NOTIFY:
|
case t == criurpc.CriuReqType_NOTIFY:
|
||||||
if err := c.criuNotifications(resp, process, opts, extFds); err != nil {
|
if err := c.criuNotifications(resp, process, opts, extFds); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
Loading…
Reference in New Issue