[lxc-devel] [lxd/master] Introduce volatile.idmap.current
stgraber on Github
lxc-bot at linuxcontainers.org
Thu Mar 28 02:09:42 UTC 2019
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 545 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190327/d6cd433e/attachment.bin>
-------------- next part --------------
From d3f636a7eef8aaf3d0402bc1e84894ebdbf014e4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 27 Mar 2019 18:01:29 -0400
Subject: [PATCH 1/5] lxd/containers: Implement new idmap functions
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/container.go | 6 ++++--
lxd/container_lxc.go | 27 +++++++++++++++++++++++++++
2 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/lxd/container.go b/lxd/container.go
index 89c94e95ac..354aae4011 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -673,10 +673,12 @@ type container interface {
StorageStart() (bool, error)
StorageStop() (bool, error)
Storage() storage
- IdmapSet() (*idmap.IdmapSet, error)
- LastIdmapSet() (*idmap.IdmapSet, error)
TemplateApply(trigger string) error
DaemonState() *state.State
+
+ CurrentIdmap() (*idmap.IdmapSet, error)
+ DiskIdmap() (*idmap.IdmapSet, error)
+ NextIdmap() (*idmap.IdmapSet, error)
}
// Loader functions
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index f3b8b5f8a0..5e383ae078 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -8735,6 +8735,33 @@ func (c *containerLXC) LastIdmapSet() (*idmap.IdmapSet, error) {
return c.idmapsetFromConfig("volatile.last_state.idmap")
}
+func (c *containerLXC) CurrentIdmap() (*idmap.IdmapSet, error) {
+ jsonIdmap, ok := c.LocalConfig()["volatile.idmap.current"]
+ if !ok {
+ return c.DiskIdmap()
+ }
+
+ return idmapsetFromString(jsonIdmap)
+}
+
+func (c *containerLXC) DiskIdmap() (*idmap.IdmapSet, error) {
+ jsonIdmap, ok := c.LocalConfig()["volatile.last_state.idmap"]
+ if !ok {
+ return nil, nil
+ }
+
+ return idmapsetFromString(jsonIdmap)
+}
+
+func (c *containerLXC) NextIdmap() (*idmap.IdmapSet, error) {
+ jsonIdmap, ok := c.LocalConfig()["volatile.idmap.next"]
+ if !ok {
+ return c.CurrentIdmap()
+ }
+
+ return idmapsetFromString(jsonIdmap)
+}
+
func (c *containerLXC) DaemonState() *state.State {
// FIXME: This function should go away, since the abstract container
// interface should not be coupled with internal state details.
From 45a853a05b0165235c7c77683bbb6b98fa947be1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 27 Mar 2019 18:26:01 -0400
Subject: [PATCH 2/5] lxd: Port to new idmap functions
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/container_console.go | 2 +-
lxd/container_exec.go | 2 +-
lxd/devlxd.go | 2 +-
lxd/migrate_container.go | 2 +-
lxd/storage.go | 20 +++++++++++++++-----
5 files changed, 19 insertions(+), 9 deletions(-)
diff --git a/lxd/container_console.go b/lxd/container_console.go
index b12f060fe5..e2741bc8ca 100644
--- a/lxd/container_console.go
+++ b/lxd/container_console.go
@@ -303,7 +303,7 @@ func containerConsolePost(d *Daemon, r *http.Request) Response {
ws := &consoleWs{}
ws.fds = map[int]string{}
- idmapset, err := c.IdmapSet()
+ idmapset, err := c.CurrentIdmap()
if err != nil {
return InternalError(err)
}
diff --git a/lxd/container_exec.go b/lxd/container_exec.go
index 71c694a06d..238b1df3a0 100644
--- a/lxd/container_exec.go
+++ b/lxd/container_exec.go
@@ -426,7 +426,7 @@ func containerExecPost(d *Daemon, r *http.Request) Response {
ws := &execWs{}
ws.fds = map[int]string{}
- idmapset, err := c.IdmapSet()
+ idmapset, err := c.CurrentIdmap()
if err != nil {
return InternalError(err)
}
diff --git a/lxd/devlxd.go b/lxd/devlxd.go
index eb7735b215..a15fd2306c 100644
--- a/lxd/devlxd.go
+++ b/lxd/devlxd.go
@@ -231,7 +231,7 @@ func hoistReq(f func(*Daemon, container, http.ResponseWriter, *http.Request) *de
// Access control
rootUid := int64(0)
- idmapset, err := c.LastIdmapSet()
+ idmapset, err := c.CurrentIdmap()
if err == nil && idmapset != nil {
uid, _ := idmapset.ShiftIntoNs(0, 0)
rootUid = int64(uid)
diff --git a/lxd/migrate_container.go b/lxd/migrate_container.go
index 69d3ec2eeb..ff4c476705 100644
--- a/lxd/migrate_container.go
+++ b/lxd/migrate_container.go
@@ -337,7 +337,7 @@ func (s *migrationSourceWs) Do(migrateOp *operation) error {
idmaps := make([]*migration.IDMapType, 0)
- idmapset, err := s.container.LastIdmapSet()
+ idmapset, err := s.container.DiskIdmap()
if err != nil {
return err
}
diff --git a/lxd/storage.go b/lxd/storage.go
index 1f9438a05d..41ea2e09e3 100644
--- a/lxd/storage.go
+++ b/lxd/storage.go
@@ -411,7 +411,7 @@ func storagePoolVolumeAttachInit(s *state.State, poolName string, volumeName str
return st, nil
}
- // get last idmapset
+ // Get the on-disk idmap for the volume
var lastIdmap *idmap.IdmapSet
if poolVolumePut.Config["volatile.idmap.last"] != "" {
lastIdmap, err = idmapsetFromString(poolVolumePut.Config["volatile.idmap.last"])
@@ -421,8 +421,13 @@ func storagePoolVolumeAttachInit(s *state.State, poolName string, volumeName str
}
}
- // get next idmapset
- nextIdmap, err := c.IdmapSet()
+ // Get the container's idmap
+ var nextIdmap *idmap.IdmapSet
+ if c.IsRunning() {
+ nextIdmap, err = c.CurrentIdmap()
+ } else {
+ nextIdmap, err = c.NextIdmap()
+ }
if err != nil {
return nil, err
}
@@ -460,7 +465,12 @@ func storagePoolVolumeAttachInit(s *state.State, poolName string, volumeName str
continue
}
- ctNextIdmap, err := ct.IdmapSet()
+ var ctNextIdmap *idmap.IdmapSet
+ if ct.IsRunning() {
+ ctNextIdmap, err = ct.CurrentIdmap()
+ } else {
+ ctNextIdmap, err = ct.NextIdmap()
+ }
if err != nil {
return nil, fmt.Errorf("Failed to retrieve idmap of container")
}
@@ -745,7 +755,7 @@ func deleteSnapshotMountpoint(snapshotMountpoint string, snapshotsSymlinkTarget
}
func resetContainerDiskIdmap(container container, srcIdmap *idmap.IdmapSet) error {
- dstIdmap, err := container.IdmapSet()
+ dstIdmap, err := container.DiskIdmap()
if err != nil {
return err
}
From 8075ed43f9f68eff0c3d5ad5a18024c3a1154213 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 27 Mar 2019 18:38:18 -0400
Subject: [PATCH 3/5] lxd/containers: Port to new idmap functions
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/container_lxc.go | 74 ++++++++++---------------------------------
lxd/container_test.go | 12 +++----
2 files changed, 23 insertions(+), 63 deletions(-)
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 5e383ae078..98e08d4c3a 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -1225,7 +1225,7 @@ func (c *containerLXC) initLXC(config bool) error {
}
// Setup idmap
- idmapset, err := c.IdmapSet()
+ idmapset, err := c.NextIdmap()
if err != nil {
return err
}
@@ -1976,12 +1976,12 @@ func (c *containerLXC) startCommon() (string, error) {
}
/* Deal with idmap changes */
- idmap, err := c.IdmapSet()
+ idmap, err := c.NextIdmap()
if err != nil {
return "", errors.Wrap(err, "Set ID map")
}
- lastIdmap, err := c.LastIdmapSet()
+ lastIdmap, err := c.DiskIdmap()
if err != nil {
return "", errors.Wrap(err, "Set last ID map")
}
@@ -2038,12 +2038,17 @@ func (c *containerLXC) startCommon() (string, error) {
}
}
+ err = c.ConfigKeySet("volatile.last_state.idmap", jsonIdmap)
+ if err != nil {
+ return "", errors.Wrapf(err, "Set volatile.last_state.idmap config key on container %q (id %d)", c.name, c.id)
+ }
+
c.updateProgress("")
}
- err = c.ConfigKeySet("volatile.last_state.idmap", jsonIdmap)
+ err = c.ConfigKeySet("volatile.idmap.current", jsonIdmap)
if err != nil {
- return "", errors.Wrapf(err, "Set volatile.last_state.idmap config key on container %q (id %d)", c.name, c.id)
+ return "", errors.Wrapf(err, "Set volatile.idmap.current config key on container %q (id %d)", c.name, c.id)
}
// Generate the Seccomp profile
@@ -5064,7 +5069,7 @@ func (c *containerLXC) Export(w io.Writer, properties map[string]string) error {
}
// Unshift the container
- idmap, err := c.LastIdmapSet()
+ idmap, err := c.DiskIdmap()
if err != nil {
logger.Error("Failed exporting container", ctxMap)
return err
@@ -5392,7 +5397,7 @@ func (c *containerLXC) Migrate(args *CriuMigrationArgs) error {
* namespace.
*/
if !c.IsPrivileged() {
- idmapset, err := c.IdmapSet()
+ idmapset, err := c.CurrentIdmap()
if err != nil {
return err
}
@@ -5599,7 +5604,7 @@ func (c *containerLXC) templateApplyNow(trigger string) error {
// Get the right uid and gid for the container
if !c.IsPrivileged() {
- idmapset, err := c.IdmapSet()
+ idmapset, err := c.DiskIdmap()
if err != nil {
return errors.Wrap(err, "Failed to set ID map")
}
@@ -5842,7 +5847,7 @@ func (c *containerLXC) FilePull(srcpath string, dstpath string) (int64, int64, o
// Unmap uid and gid if needed
if !c.IsRunning() {
- idmapset, err := c.LastIdmapSet()
+ idmapset, err := c.DiskIdmap()
if err != nil {
return -1, -1, 0, "", nil, err
}
@@ -5862,7 +5867,7 @@ func (c *containerLXC) FilePush(type_ string, srcpath string, dstpath string, ui
// Map uid and gid if needed
if !c.IsRunning() {
- idmapset, err := c.LastIdmapSet()
+ idmapset, err := c.DiskIdmap()
if err != nil {
return err
}
@@ -6368,7 +6373,7 @@ func (c *containerLXC) tarStoreFile(linkmap map[uint64]string, offset int, tw *t
// Unshift the id under /rootfs/ for unpriv containers
if !c.IsPrivileged() && strings.HasPrefix(hdr.Name, "/rootfs") {
- idmapset, err := c.IdmapSet()
+ idmapset, err := c.DiskIdmap()
if err != nil {
return err
}
@@ -6719,7 +6724,7 @@ func (c *containerLXC) createUnixDevice(prefix string, m types.Device, defaultMo
return nil, fmt.Errorf("Failed to chmod device %s: %s", devPath, err)
}
- idmapset, err := c.IdmapSet()
+ idmapset, err := c.CurrentIdmap()
if err != nil {
return nil, err
}
@@ -8672,25 +8677,6 @@ func (c *containerLXC) Id() int {
return c.id
}
-func (c *containerLXC) IdmapSet() (*idmap.IdmapSet, error) {
- var err error
-
- if c.idmapset != nil {
- return c.idmapset, nil
- }
-
- if c.IsPrivileged() {
- return nil, nil
- }
-
- c.idmapset, err = c.NextIdmapSet()
- if err != nil {
- return nil, err
- }
-
- return c.idmapset, nil
-}
-
func (c *containerLXC) InitPID() int {
// Load the go-lxc struct
err := c.initLXC(false)
@@ -8709,32 +8695,6 @@ func (c *containerLXC) LocalDevices() types.Devices {
return c.localDevices
}
-func (c *containerLXC) idmapsetFromConfig(k string) (*idmap.IdmapSet, error) {
- lastJsonIdmap := c.LocalConfig()[k]
-
- if lastJsonIdmap == "" {
- return c.IdmapSet()
- }
-
- return idmapsetFromString(lastJsonIdmap)
-}
-
-func (c *containerLXC) NextIdmapSet() (*idmap.IdmapSet, error) {
- if c.localConfig["volatile.idmap.next"] != "" {
- return c.idmapsetFromConfig("volatile.idmap.next")
- } else if c.IsPrivileged() {
- return nil, nil
- } else if c.state.OS.IdmapSet != nil {
- return c.state.OS.IdmapSet, nil
- }
-
- return nil, fmt.Errorf("Unable to determine the idmap")
-}
-
-func (c *containerLXC) LastIdmapSet() (*idmap.IdmapSet, error) {
- return c.idmapsetFromConfig("volatile.last_state.idmap")
-}
-
func (c *containerLXC) CurrentIdmap() (*idmap.IdmapSet, error) {
jsonIdmap, ok := c.LocalConfig()["volatile.idmap.current"]
if !ok {
diff --git a/lxd/container_test.go b/lxd/container_test.go
index 263412b787..caa3adebe0 100644
--- a/lxd/container_test.go
+++ b/lxd/container_test.go
@@ -264,9 +264,9 @@ func (suite *containerTestSuite) TestContainer_findIdmap_isolated() {
suite.Req.Nil(err)
defer c2.Delete()
- map1, err := c1.(*containerLXC).NextIdmapSet()
+ map1, err := c1.(*containerLXC).NextIdmap()
suite.Req.Nil(err)
- map2, err := c2.(*containerLXC).NextIdmapSet()
+ map2, err := c2.(*containerLXC).NextIdmap()
suite.Req.Nil(err)
host := suite.d.os.IdmapSet.Idmap[0]
@@ -305,9 +305,9 @@ func (suite *containerTestSuite) TestContainer_findIdmap_mixed() {
suite.Req.Nil(err)
defer c2.Delete()
- map1, err := c1.(*containerLXC).NextIdmapSet()
+ map1, err := c1.(*containerLXC).NextIdmap()
suite.Req.Nil(err)
- map2, err := c2.(*containerLXC).NextIdmapSet()
+ map2, err := c2.(*containerLXC).NextIdmap()
suite.Req.Nil(err)
host := suite.d.os.IdmapSet.Idmap[0]
@@ -337,7 +337,7 @@ func (suite *containerTestSuite) TestContainer_findIdmap_raw() {
suite.Req.Nil(err)
defer c1.Delete()
- map1, err := c1.(*containerLXC).NextIdmapSet()
+ map1, err := c1.(*containerLXC).NextIdmap()
suite.Req.Nil(err)
host := suite.d.os.IdmapSet.Idmap[0]
@@ -383,7 +383,7 @@ func (suite *containerTestSuite) TestContainer_findIdmap_maxed() {
defer c.Delete()
- m, err := c.(*containerLXC).NextIdmapSet()
+ m, err := c.(*containerLXC).NextIdmap()
suite.Req.Nil(err)
maps = append(maps, m)
From f7a5e23f978661ba10dae6f6d575cfd22b1b8b9c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 27 Mar 2019 18:42:07 -0400
Subject: [PATCH 4/5] doc: Introduce volatile.idmap.current
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
doc/containers.md | 1 +
scripts/bash/lxd-client | 6 +++---
shared/container.go | 3 ++-
3 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/doc/containers.md b/doc/containers.md
index 2e853f59d3..b3949ff418 100644
--- a/doc/containers.md
+++ b/doc/containers.md
@@ -92,6 +92,7 @@ volatile.apply\_quota | string | - | Disk quota to be a
volatile.apply\_template | string | - | The name of a template hook which should be triggered upon next startup
volatile.base\_image | string | - | The hash of the image the container was created from, if any.
volatile.idmap.base | integer | - | The first id in the container's primary idmap range
+volatile.idmap.current | string | - | The idmap currently in use by the container
volatile.idmap.next | string | - | The idmap to use next time the container starts
volatile.last\_state.idmap | string | - | Serialized container uid/gid map
volatile.last\_state.power | string | - | Container state as of last host shutdown
diff --git a/scripts/bash/lxd-client b/scripts/bash/lxd-client
index c8e09f5793..41ee4f3ff1 100644
--- a/scripts/bash/lxd-client
+++ b/scripts/bash/lxd-client
@@ -92,9 +92,9 @@ _have lxc && {
security.syscalls.blacklist_compat security.syscalls.blacklist_default \
snapshots.schedule snapshots.schedule.stopped snapshots.pattern \
volatile.apply_quota volatile.apply_template volatile.base_image \
- volatile.idmap.base volatile.idmap.next volatile.last_state.idmap \
- volatile.last_state.power user.meta-data user.network-config \
- user.network_mode user.user-data user.vendor-data"
+ volatile.idmap.base volatile.idmap.current volatile.idmap.next \
+ volatile.last_state.idmap volatile.last_state.power user.meta-data \
+ user.network-config user.network_mode user.user-data user.vendor-data"
networks_keys="bridge.driver bridge.external_interfaces bridge.mode \
bridge.mtu bridge.hwaddr dns.domain dns.mode fan.overlay_subnet fan.type \
diff --git a/shared/container.go b/shared/container.go
index 824a142355..6e609959d0 100644
--- a/shared/container.go
+++ b/shared/container.go
@@ -302,8 +302,9 @@ var KnownContainerConfigKeys = map[string]func(value string) error{
"volatile.base_image": IsAny,
"volatile.last_state.idmap": IsAny,
"volatile.last_state.power": IsAny,
- "volatile.idmap.next": IsAny,
"volatile.idmap.base": IsAny,
+ "volatile.idmap.current": IsAny,
+ "volatile.idmap.next": IsAny,
"volatile.apply_quota": IsAny,
}
From e9f79646430c8513ed01b7efdcd5f0cfdce44f50 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 27 Mar 2019 22:08:30 -0400
Subject: [PATCH 5/5] api: Add id_map_current API extension
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
doc/api-extensions.md | 12 ++++++++++++
shared/version/api.go | 1 +
2 files changed, 13 insertions(+)
diff --git a/doc/api-extensions.md b/doc/api-extensions.md
index d30fc52cbd..20395ea9bf 100644
--- a/doc/api-extensions.md
+++ b/doc/api-extensions.md
@@ -710,3 +710,15 @@ Shows the NUMA node for all CPUs and GPUs.
## kernel\_features
Exposes the state of optional kernel features through the server environment.
+
+## id\_map\_current
+This introduces a new internal `volatile.idmap.current` key which is
+used to track the current mapping for the container.
+
+This effectively gives us:
+ - `volatile.last\_state.idmap` => On-disk idmap
+ - `volatile.idmap.current` => Current kernel map
+ - `volatile.idmap.next` => Next on-disk idmap
+
+This is required to implement environments where the on-disk map isn't
+changed but the kernel map is (e.g. shiftfs).
diff --git a/shared/version/api.go b/shared/version/api.go
index 6481e4f786..6d056c5747 100644
--- a/shared/version/api.go
+++ b/shared/version/api.go
@@ -144,6 +144,7 @@ var APIExtensions = []string{
"resources_gpu",
"resources_numa",
"kernel_features",
+ "id_map_current",
}
// APIExtensionsCount returns the number of available API extensions.
More information about the lxc-devel
mailing list