Merge pull request #29869 from cpuguy83/backport_28263
[cherry-pick] Moves graphdriver plugin docs out of experimental
This commit is contained in:
commit
7d58f5fb88
11 changed files with 178 additions and 95 deletions
|
@ -570,6 +570,7 @@ func NewDaemon(config *Config, registryService registry.Service, containerdRemot
|
|||
UIDMaps: uidMaps,
|
||||
GIDMaps: gidMaps,
|
||||
PluginGetter: d.PluginStore,
|
||||
ExperimentalEnabled: config.Experimental,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -150,16 +150,16 @@ func Register(name string, initFunc InitFunc) error {
|
|||
}
|
||||
|
||||
// GetDriver initializes and returns the registered driver
|
||||
func GetDriver(name, home string, options []string, uidMaps, gidMaps []idtools.IDMap, pg plugingetter.PluginGetter) (Driver, error) {
|
||||
func GetDriver(name string, pg plugingetter.PluginGetter, config Options) (Driver, error) {
|
||||
if initFunc, exists := drivers[name]; exists {
|
||||
return initFunc(filepath.Join(home, name), options, uidMaps, gidMaps)
|
||||
return initFunc(filepath.Join(config.Root, name), config.DriverOptions, config.UIDMaps, config.GIDMaps)
|
||||
}
|
||||
|
||||
pluginDriver, err := lookupPlugin(name, home, options, pg)
|
||||
pluginDriver, err := lookupPlugin(name, pg, config)
|
||||
if err == nil {
|
||||
return pluginDriver, nil
|
||||
}
|
||||
logrus.WithError(err).WithField("driver", name).WithField("home-dir", home).Error("Failed to GetDriver graph")
|
||||
logrus.WithError(err).WithField("driver", name).WithField("home-dir", config.Root).Error("Failed to GetDriver graph")
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
|
@ -172,15 +172,24 @@ func getBuiltinDriver(name, home string, options []string, uidMaps, gidMaps []id
|
|||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
// Options is used to initialize a graphdriver
|
||||
type Options struct {
|
||||
Root string
|
||||
DriverOptions []string
|
||||
UIDMaps []idtools.IDMap
|
||||
GIDMaps []idtools.IDMap
|
||||
ExperimentalEnabled bool
|
||||
}
|
||||
|
||||
// New creates the driver and initializes it at the specified root.
|
||||
func New(root, name string, options []string, uidMaps, gidMaps []idtools.IDMap, pg plugingetter.PluginGetter) (Driver, error) {
|
||||
func New(name string, pg plugingetter.PluginGetter, config Options) (Driver, error) {
|
||||
if name != "" {
|
||||
logrus.Debugf("[graphdriver] trying provided driver: %s", name) // so the logs show specified driver
|
||||
return GetDriver(name, root, options, uidMaps, gidMaps, pg)
|
||||
return GetDriver(name, pg, config)
|
||||
}
|
||||
|
||||
// Guess for prior driver
|
||||
driversMap := scanPriorDrivers(root)
|
||||
driversMap := scanPriorDrivers(config.Root)
|
||||
for _, name := range priority {
|
||||
if name == "vfs" {
|
||||
// don't use vfs even if there is state present.
|
||||
|
@ -189,7 +198,7 @@ func New(root, name string, options []string, uidMaps, gidMaps []idtools.IDMap,
|
|||
if _, prior := driversMap[name]; prior {
|
||||
// of the state found from prior drivers, check in order of our priority
|
||||
// which we would prefer
|
||||
driver, err := getBuiltinDriver(name, root, options, uidMaps, gidMaps)
|
||||
driver, err := getBuiltinDriver(name, config.Root, config.DriverOptions, config.UIDMaps, config.GIDMaps)
|
||||
if err != nil {
|
||||
// unlike below, we will return error here, because there is prior
|
||||
// state, and now it is no longer supported/prereq/compatible, so
|
||||
|
@ -207,7 +216,7 @@ func New(root, name string, options []string, uidMaps, gidMaps []idtools.IDMap,
|
|||
driversSlice = append(driversSlice, name)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%s contains several valid graphdrivers: %s; Please cleanup or explicitly choose storage driver (-s <DRIVER>)", root, strings.Join(driversSlice, ", "))
|
||||
return nil, fmt.Errorf("%s contains several valid graphdrivers: %s; Please cleanup or explicitly choose storage driver (-s <DRIVER>)", config.Root, strings.Join(driversSlice, ", "))
|
||||
}
|
||||
|
||||
logrus.Infof("[graphdriver] using prior storage driver: %s", name)
|
||||
|
@ -217,7 +226,7 @@ func New(root, name string, options []string, uidMaps, gidMaps []idtools.IDMap,
|
|||
|
||||
// Check for priority drivers first
|
||||
for _, name := range priority {
|
||||
driver, err := getBuiltinDriver(name, root, options, uidMaps, gidMaps)
|
||||
driver, err := getBuiltinDriver(name, config.Root, config.DriverOptions, config.UIDMaps, config.GIDMaps)
|
||||
if err != nil {
|
||||
if isDriverNotSupported(err) {
|
||||
continue
|
||||
|
@ -229,7 +238,7 @@ func New(root, name string, options []string, uidMaps, gidMaps []idtools.IDMap,
|
|||
|
||||
// Check all registered drivers if no priority driver is found
|
||||
for name, initFunc := range drivers {
|
||||
driver, err := initFunc(filepath.Join(root, name), options, uidMaps, gidMaps)
|
||||
driver, err := initFunc(filepath.Join(config.Root, name), config.DriverOptions, config.UIDMaps, config.GIDMaps)
|
||||
if err != nil {
|
||||
if isDriverNotSupported(err) {
|
||||
continue
|
||||
|
|
|
@ -41,7 +41,7 @@ func newDriver(t testing.TB, name string, options []string) *Driver {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
d, err := graphdriver.GetDriver(name, root, options, nil, nil, nil)
|
||||
d, err := graphdriver.GetDriver(name, nil, graphdriver.Options{DriverOptions: options, Root: root})
|
||||
if err != nil {
|
||||
t.Logf("graphdriver: %v\n", err)
|
||||
if err == graphdriver.ErrNotSupported || err == graphdriver.ErrPrerequisites || err == graphdriver.ErrIncompatibleFS {
|
||||
|
|
|
@ -18,15 +18,19 @@ type pluginClient interface {
|
|||
SendFile(string, io.Reader, interface{}) error
|
||||
}
|
||||
|
||||
func lookupPlugin(name, home string, opts []string, pg plugingetter.PluginGetter) (Driver, error) {
|
||||
pl, err := pg.Get(name, "GraphDriver", plugingetter.LOOKUP)
|
||||
func lookupPlugin(name string, pg plugingetter.PluginGetter, config Options) (Driver, error) {
|
||||
if !config.ExperimentalEnabled {
|
||||
return nil, fmt.Errorf("graphdriver plugins are only supported with experimental mode")
|
||||
}
|
||||
pl, err := pg.Get(name, "GraphDriver", plugingetter.ACQUIRE)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error looking up graphdriver plugin %s: %v", name, err)
|
||||
}
|
||||
return newPluginDriver(name, home, opts, pl)
|
||||
return newPluginDriver(name, pl, config)
|
||||
}
|
||||
|
||||
func newPluginDriver(name, home string, opts []string, pl plugingetter.CompatPlugin) (Driver, error) {
|
||||
func newPluginDriver(name string, pl plugingetter.CompatPlugin, config Options) (Driver, error) {
|
||||
home := config.Root
|
||||
if !pl.IsV1() {
|
||||
if p, ok := pl.(*v2.Plugin); ok {
|
||||
if p.PropagatedMount != "" {
|
||||
|
@ -35,5 +39,5 @@ func newPluginDriver(name, home string, opts []string, pl plugingetter.CompatPlu
|
|||
}
|
||||
}
|
||||
proxy := &graphDriverProxy{name, pl}
|
||||
return proxy, proxy.Init(filepath.Join(home, name), opts)
|
||||
return proxy, proxy.Init(filepath.Join(home, name), config.DriverOptions, config.UIDMaps, config.GIDMaps)
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"path/filepath"
|
||||
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/plugingetter"
|
||||
)
|
||||
|
||||
|
@ -16,9 +17,10 @@ type graphDriverProxy struct {
|
|||
}
|
||||
|
||||
type graphDriverRequest struct {
|
||||
ID string `json:",omitempty"`
|
||||
Parent string `json:",omitempty"`
|
||||
MountLabel string `json:",omitempty"`
|
||||
ID string `json:",omitempty"`
|
||||
Parent string `json:",omitempty"`
|
||||
MountLabel string `json:",omitempty"`
|
||||
StorageOpt map[string]string `json:",omitempty"`
|
||||
}
|
||||
|
||||
type graphDriverResponse struct {
|
||||
|
@ -32,11 +34,13 @@ type graphDriverResponse struct {
|
|||
}
|
||||
|
||||
type graphDriverInitRequest struct {
|
||||
Home string
|
||||
Opts []string
|
||||
Home string
|
||||
Opts []string `json:"Opts"`
|
||||
UIDMaps []idtools.IDMap `json:"UIDMaps"`
|
||||
GIDMaps []idtools.IDMap `json:"GIDMaps"`
|
||||
}
|
||||
|
||||
func (d *graphDriverProxy) Init(home string, opts []string) error {
|
||||
func (d *graphDriverProxy) Init(home string, opts []string, uidMaps, gidMaps []idtools.IDMap) error {
|
||||
if !d.p.IsV1() {
|
||||
if cp, ok := d.p.(plugingetter.CountedPlugin); ok {
|
||||
// always acquire here, it will be cleaned up on daemon shutdown
|
||||
|
@ -44,8 +48,10 @@ func (d *graphDriverProxy) Init(home string, opts []string) error {
|
|||
}
|
||||
}
|
||||
args := &graphDriverInitRequest{
|
||||
Home: home,
|
||||
Opts: opts,
|
||||
Home: home,
|
||||
Opts: opts,
|
||||
UIDMaps: uidMaps,
|
||||
GIDMaps: gidMaps,
|
||||
}
|
||||
var ret graphDriverResponse
|
||||
if err := d.p.Client().Call("GraphDriver.Init", args, &ret); err != nil {
|
||||
|
@ -62,16 +68,15 @@ func (d *graphDriverProxy) String() string {
|
|||
}
|
||||
|
||||
func (d *graphDriverProxy) CreateReadWrite(id, parent string, opts *CreateOpts) error {
|
||||
mountLabel := ""
|
||||
args := &graphDriverRequest{
|
||||
ID: id,
|
||||
Parent: parent,
|
||||
}
|
||||
if opts != nil {
|
||||
mountLabel = opts.MountLabel
|
||||
args.MountLabel = opts.MountLabel
|
||||
args.StorageOpt = opts.StorageOpt
|
||||
}
|
||||
|
||||
args := &graphDriverRequest{
|
||||
ID: id,
|
||||
Parent: parent,
|
||||
MountLabel: mountLabel,
|
||||
}
|
||||
var ret graphDriverResponse
|
||||
if err := d.p.Client().Call("GraphDriver.CreateReadWrite", args, &ret); err != nil {
|
||||
return err
|
||||
|
@ -83,14 +88,13 @@ func (d *graphDriverProxy) CreateReadWrite(id, parent string, opts *CreateOpts)
|
|||
}
|
||||
|
||||
func (d *graphDriverProxy) Create(id, parent string, opts *CreateOpts) error {
|
||||
mountLabel := ""
|
||||
if opts != nil {
|
||||
mountLabel = opts.MountLabel
|
||||
}
|
||||
args := &graphDriverRequest{
|
||||
ID: id,
|
||||
Parent: parent,
|
||||
MountLabel: mountLabel,
|
||||
ID: id,
|
||||
Parent: parent,
|
||||
}
|
||||
if opts != nil {
|
||||
args.MountLabel = opts.MountLabel
|
||||
args.StorageOpt = opts.StorageOpt
|
||||
}
|
||||
var ret graphDriverResponse
|
||||
if err := d.p.Client().Call("GraphDriver.Create", args, &ret); err != nil {
|
||||
|
|
|
@ -1,12 +1,42 @@
|
|||
# Experimental: Docker graph driver plugins
|
||||
---
|
||||
title: "Graphdriver plugins"
|
||||
description: "How to manage image and container filesystems with external plugins"
|
||||
keywords: "Examples, Usage, storage, image, docker, data, graph, plugin, api"
|
||||
advisory: experimental
|
||||
---
|
||||
|
||||
<!-- This file is maintained within the docker/docker Github
|
||||
repository at https://github.com/docker/docker/. Make all
|
||||
pull requests against that repo. If you see this file in
|
||||
another repository, consider it read-only there, as it will
|
||||
periodically be overwritten by the definitive file. Pull
|
||||
requests which include edits to this file in other repositories
|
||||
will be rejected.
|
||||
-->
|
||||
|
||||
|
||||
## Changelog
|
||||
|
||||
### 1.13.0
|
||||
|
||||
- Support v2 plugins
|
||||
|
||||
# Docker graph driver plugins
|
||||
|
||||
Docker graph driver plugins enable admins to use an external/out-of-process
|
||||
graph driver for use with Docker engine. This is an alternative to using the
|
||||
built-in storage drivers, such as aufs/overlay/devicemapper/btrfs.
|
||||
|
||||
A graph driver plugin is used for image and container fs storage, as such
|
||||
the plugin must be started and available for connections prior to Docker Engine
|
||||
being started.
|
||||
You need to install and enable the plugin and then restart the Docker daemon
|
||||
before using the plugin. See the following example for the correct ordering
|
||||
of steps.
|
||||
|
||||
```
|
||||
$ docker plugin install cpuguy83/docker-overlay2-graphdriver-plugin # this command also enables the driver
|
||||
<output supressed>
|
||||
$ pkill dockerd
|
||||
$ dockerd --experimental -s cpuguy83/docker-overlay2-graphdriver-plugin
|
||||
```
|
||||
|
||||
# Write a graph driver plugin
|
||||
|
||||
|
@ -22,20 +52,30 @@ expected to provide the rootfs for containers as well as image layer storage.
|
|||
### /GraphDriver.Init
|
||||
|
||||
**Request**:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"Home": "/graph/home/path",
|
||||
"Opts": []
|
||||
"Opts": [],
|
||||
"UIDMaps": [],
|
||||
"GIDMaps": []
|
||||
}
|
||||
```
|
||||
|
||||
Initialize the graph driver plugin with a home directory and array of options.
|
||||
Plugins are not required to accept these options as the Docker Engine does not
|
||||
require that the plugin use this path or options, they are only being passed
|
||||
through from the user.
|
||||
These are passed through from the user, but the plugin is not required to parse
|
||||
or honor them.
|
||||
|
||||
The request also includes a list of UID and GID mappings, structed as follows:
|
||||
```json
|
||||
{
|
||||
"ContainerID": 0,
|
||||
"HostID": 0,
|
||||
"Size": 0
|
||||
}
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"Err": ""
|
||||
}
|
||||
|
@ -47,20 +87,21 @@ Respond with a non-empty string error if an error occurred.
|
|||
### /GraphDriver.Create
|
||||
|
||||
**Request**:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"ID": "46fe8644f2572fd1e505364f7581e0c9dbc7f14640bd1fb6ce97714fb6fc5187",
|
||||
"Parent": "2cd9c322cb78a55e8212aa3ea8425a4180236d7106938ec921d0935a4b8ca142"
|
||||
"MountLabel": ""
|
||||
"Parent": "2cd9c322cb78a55e8212aa3ea8425a4180236d7106938ec921d0935a4b8ca142",
|
||||
"MountLabel": "",
|
||||
"StorageOpt": {}
|
||||
}
|
||||
```
|
||||
|
||||
Create a new, empty, read-only filesystem layer with the specified
|
||||
`ID`, `Parent` and `MountLabel`. `Parent` may be an empty string,
|
||||
which would indicate that there is no parent layer.
|
||||
`ID`, `Parent` and `MountLabel`. If `Parent` is an empty string, there is no
|
||||
parent layer. `StorageOpt` is map of strings which indicate storage options.
|
||||
|
||||
**Response**:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"Err": ""
|
||||
}
|
||||
|
@ -71,11 +112,12 @@ Respond with a non-empty string error if an error occurred.
|
|||
### /GraphDriver.CreateReadWrite
|
||||
|
||||
**Request**:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"ID": "46fe8644f2572fd1e505364f7581e0c9dbc7f14640bd1fb6ce97714fb6fc5187",
|
||||
"Parent": "2cd9c322cb78a55e8212aa3ea8425a4180236d7106938ec921d0935a4b8ca142"
|
||||
"MountLabel": ""
|
||||
"Parent": "2cd9c322cb78a55e8212aa3ea8425a4180236d7106938ec921d0935a4b8ca142",
|
||||
"MountLabel": "",
|
||||
"StorageOpt": {}
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -84,7 +126,7 @@ Similar to `/GraphDriver.Create` but creates a read-write filesystem layer.
|
|||
### /GraphDriver.Remove
|
||||
|
||||
**Request**:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"ID": "46fe8644f2572fd1e505364f7581e0c9dbc7f14640bd1fb6ce97714fb6fc5187"
|
||||
}
|
||||
|
@ -93,7 +135,7 @@ Similar to `/GraphDriver.Create` but creates a read-write filesystem layer.
|
|||
Remove the filesystem layer with this given `ID`.
|
||||
|
||||
**Response**:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"Err": ""
|
||||
}
|
||||
|
@ -104,9 +146,9 @@ Respond with a non-empty string error if an error occurred.
|
|||
### /GraphDriver.Get
|
||||
|
||||
**Request**:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"ID": "46fe8644f2572fd1e505364f7581e0c9dbc7f14640bd1fb6ce97714fb6fc5187"
|
||||
"ID": "46fe8644f2572fd1e505364f7581e0c9dbc7f14640bd1fb6ce97714fb6fc5187",
|
||||
"MountLabel": ""
|
||||
}
|
||||
```
|
||||
|
@ -114,7 +156,7 @@ Respond with a non-empty string error if an error occurred.
|
|||
Get the mountpoint for the layered filesystem referred to by the given `ID`.
|
||||
|
||||
**Response**:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"Dir": "/var/mygraph/46fe8644f2572fd1e505364f7581e0c9dbc7f14640bd1fb6ce97714fb6fc5187",
|
||||
"Err": ""
|
||||
|
@ -127,7 +169,7 @@ Respond with a non-empty string error if an error occurred.
|
|||
### /GraphDriver.Put
|
||||
|
||||
**Request**:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"ID": "46fe8644f2572fd1e505364f7581e0c9dbc7f14640bd1fb6ce97714fb6fc5187"
|
||||
}
|
||||
|
@ -137,7 +179,7 @@ Release the system resources for the specified `ID`, such as unmounting the
|
|||
filesystem layer.
|
||||
|
||||
**Response**:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"Err": ""
|
||||
}
|
||||
|
@ -148,7 +190,7 @@ Respond with a non-empty string error if an error occurred.
|
|||
### /GraphDriver.Exists
|
||||
|
||||
**Request**:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"ID": "46fe8644f2572fd1e505364f7581e0c9dbc7f14640bd1fb6ce97714fb6fc5187"
|
||||
}
|
||||
|
@ -157,7 +199,7 @@ Respond with a non-empty string error if an error occurred.
|
|||
Determine if a filesystem layer with the specified `ID` exists.
|
||||
|
||||
**Response**:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"Exists": true
|
||||
}
|
||||
|
@ -169,14 +211,14 @@ Respond with a boolean for whether or not the filesystem layer with the specifie
|
|||
### /GraphDriver.Status
|
||||
|
||||
**Request**:
|
||||
```
|
||||
```json
|
||||
{}
|
||||
```
|
||||
|
||||
Get low-level diagnostic information about the graph driver.
|
||||
|
||||
**Response**:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"Status": [[]]
|
||||
}
|
||||
|
@ -189,7 +231,7 @@ information.
|
|||
### /GraphDriver.GetMetadata
|
||||
|
||||
**Request**:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"ID": "46fe8644f2572fd1e505364f7581e0c9dbc7f14640bd1fb6ce97714fb6fc5187"
|
||||
}
|
||||
|
@ -199,7 +241,7 @@ Get low-level diagnostic information about the layered filesystem with the
|
|||
with the specified `ID`
|
||||
|
||||
**Response**:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"Metadata": {},
|
||||
"Err": ""
|
||||
|
@ -213,15 +255,15 @@ Respond with a non-empty string error if an error occurred.
|
|||
### /GraphDriver.Cleanup
|
||||
|
||||
**Request**:
|
||||
```
|
||||
```json
|
||||
{}
|
||||
```
|
||||
|
||||
Perform necessary tasks to release resources help by the plugin, for example
|
||||
Perform necessary tasks to release resources help by the plugin, such as
|
||||
unmounting all the layered file systems.
|
||||
|
||||
**Response**:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"Err": ""
|
||||
}
|
||||
|
@ -233,7 +275,7 @@ Respond with a non-empty string error if an error occurred.
|
|||
### /GraphDriver.Diff
|
||||
|
||||
**Request**:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"ID": "46fe8644f2572fd1e505364f7581e0c9dbc7f14640bd1fb6ce97714fb6fc5187",
|
||||
"Parent": "2cd9c322cb78a55e8212aa3ea8425a4180236d7106938ec921d0935a4b8ca142"
|
||||
|
@ -251,7 +293,7 @@ and `Parent`. `Parent` may be an empty string, in which case there is no parent.
|
|||
### /GraphDriver.Changes
|
||||
|
||||
**Request**:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"ID": "46fe8644f2572fd1e505364f7581e0c9dbc7f14640bd1fb6ce97714fb6fc5187",
|
||||
"Parent": "2cd9c322cb78a55e8212aa3ea8425a4180236d7106938ec921d0935a4b8ca142"
|
||||
|
@ -259,18 +301,18 @@ and `Parent`. `Parent` may be an empty string, in which case there is no parent.
|
|||
```
|
||||
|
||||
Get a list of changes between the filesystem layers specified by the `ID` and
|
||||
`Parent`. `Parent` may be an empty string, in which case there is no parent.
|
||||
`Parent`. If `Parent` is an empty string, there is no parent.
|
||||
|
||||
**Response**:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"Changes": [{}],
|
||||
"Err": ""
|
||||
}
|
||||
```
|
||||
|
||||
Responds with a list of changes. The structure of a change is:
|
||||
```
|
||||
Respond with a list of changes. The structure of a change is:
|
||||
```json
|
||||
"Path": "/some/path",
|
||||
"Kind": 0,
|
||||
```
|
||||
|
@ -300,7 +342,7 @@ and `Parent`
|
|||
- parent (required)- the `Parent` of the given `ID`
|
||||
|
||||
**Response**:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"Size": 512366,
|
||||
"Err": ""
|
||||
|
@ -313,7 +355,7 @@ Respond with a non-empty string error if an error occurred.
|
|||
### /GraphDriver.DiffSize
|
||||
|
||||
**Request**:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"ID": "46fe8644f2572fd1e505364f7581e0c9dbc7f14640bd1fb6ce97714fb6fc5187",
|
||||
"Parent": "2cd9c322cb78a55e8212aa3ea8425a4180236d7106938ec921d0935a4b8ca142"
|
||||
|
@ -323,7 +365,7 @@ Respond with a non-empty string error if an error occurred.
|
|||
Calculate the changes between the specified `ID`
|
||||
|
||||
**Response**:
|
||||
```
|
||||
```json
|
||||
{
|
||||
"Size": 512366,
|
||||
"Err": ""
|
|
@ -258,7 +258,7 @@ func (s *DockerDaemonSuite) TestVolumePlugin(c *check.C) {
|
|||
}
|
||||
|
||||
func (s *DockerDaemonSuite) TestGraphdriverPlugin(c *check.C) {
|
||||
testRequires(c, Network, IsAmd64, DaemonIsLinux, overlaySupported)
|
||||
testRequires(c, Network, IsAmd64, DaemonIsLinux, overlay2Supported, ExperimentalDaemon)
|
||||
|
||||
s.d.Start()
|
||||
|
||||
|
@ -268,7 +268,7 @@ func (s *DockerDaemonSuite) TestGraphdriverPlugin(c *check.C) {
|
|||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
|
||||
// restart the daemon with the plugin set as the storage driver
|
||||
s.d.Restart("-s", plugin)
|
||||
s.d.Restart("-s", plugin, "--storage-opt", "overlay2.override_kernel_check=1")
|
||||
|
||||
// run a container
|
||||
out, err = s.d.Cmd("run", "--rm", "busybox", "true") // this will pull busybox using the plugin
|
||||
|
|
|
@ -79,6 +79,8 @@ var (
|
|||
|
||||
// daemonPid is the pid of the main test daemon
|
||||
daemonPid int
|
||||
|
||||
daemonKernelVersion string
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -134,6 +136,7 @@ func init() {
|
|||
type Info struct {
|
||||
DockerRootDir string
|
||||
ExperimentalBuild bool
|
||||
KernelVersion string
|
||||
}
|
||||
var i Info
|
||||
status, b, err := sockRequest("GET", "/info", nil)
|
||||
|
@ -141,6 +144,7 @@ func init() {
|
|||
if err = json.Unmarshal(b, &i); err == nil {
|
||||
dockerBasePath = i.DockerRootDir
|
||||
experimentalDaemon = i.ExperimentalBuild
|
||||
daemonKernelVersion = i.KernelVersion
|
||||
}
|
||||
}
|
||||
volumesConfigPath = dockerBasePath + "/volumes"
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/pkg/parsers/kernel"
|
||||
"github.com/docker/docker/pkg/sysinfo"
|
||||
)
|
||||
|
||||
|
@ -124,7 +125,7 @@ var (
|
|||
},
|
||||
"Test cannot be run without a kernel (4.3+) supporting ambient capabilities",
|
||||
}
|
||||
overlaySupported = testRequirement{
|
||||
overlayFSSupported = testRequirement{
|
||||
func() bool {
|
||||
cmd := exec.Command(dockerBinary, "run", "--rm", "busybox", "/bin/sh", "-c", "cat /proc/filesystems")
|
||||
out, err := cmd.CombinedOutput()
|
||||
|
@ -133,7 +134,23 @@ var (
|
|||
}
|
||||
return bytes.Contains(out, []byte("overlay\n"))
|
||||
},
|
||||
"Test cannot be run wihtout suppport for ovelayfs",
|
||||
"Test cannot be run without suppport for overlayfs",
|
||||
}
|
||||
overlay2Supported = testRequirement{
|
||||
func() bool {
|
||||
if !overlayFSSupported.Condition() {
|
||||
return false
|
||||
}
|
||||
|
||||
daemonV, err := kernel.ParseRelease(daemonKernelVersion)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
requiredV := kernel.VersionInfo{Kernel: 4}
|
||||
return kernel.CompareKernelVersion(*daemonV, requiredV) > -1
|
||||
|
||||
},
|
||||
"Test cannot be run without overlay2 support (kernel 4.0+)",
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
@ -45,17 +45,18 @@ type StoreOptions struct {
|
|||
UIDMaps []idtools.IDMap
|
||||
GIDMaps []idtools.IDMap
|
||||
PluginGetter plugingetter.PluginGetter
|
||||
ExperimentalEnabled bool
|
||||
}
|
||||
|
||||
// NewStoreFromOptions creates a new Store instance
|
||||
func NewStoreFromOptions(options StoreOptions) (Store, error) {
|
||||
driver, err := graphdriver.New(
|
||||
options.StorePath,
|
||||
options.GraphDriver,
|
||||
options.GraphDriverOptions,
|
||||
options.UIDMaps,
|
||||
options.GIDMaps,
|
||||
options.PluginGetter)
|
||||
driver, err := graphdriver.New(options.GraphDriver, options.PluginGetter, graphdriver.Options{
|
||||
Root: options.StorePath,
|
||||
DriverOptions: options.GraphDriverOptions,
|
||||
UIDMaps: options.UIDMaps,
|
||||
GIDMaps: options.GIDMaps,
|
||||
ExperimentalEnabled: options.ExperimentalEnabled,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error initializing graphdriver: %v", err)
|
||||
}
|
||||
|
|
|
@ -39,7 +39,8 @@ func newVFSGraphDriver(td string) (graphdriver.Driver, error) {
|
|||
},
|
||||
}
|
||||
|
||||
return graphdriver.GetDriver("vfs", td, nil, uidMap, gidMap, nil)
|
||||
options := graphdriver.Options{Root: td, UIDMaps: uidMap, GIDMaps: gidMap}
|
||||
return graphdriver.GetDriver("vfs", nil, options)
|
||||
}
|
||||
|
||||
func newTestGraphDriver(t *testing.T) (graphdriver.Driver, func()) {
|
||||
|
|
Loading…
Reference in a new issue