Skip to content

Commit

Permalink
linstor: use user and group name instead of id
Browse files Browse the repository at this point in the history
Recent LINSTOR versions support passing the user id and group as names
instead of UID and GID. This means that we can pass "nobody:nobody"
directly instead of making a guess about what the UID and GID will be.

Try to be backward compatible by parsing back the UID and GID if the
MkfsParams property exists and passing the numbers back to LINSTOR as
user and group strings.
  • Loading branch information
chrboe committed Jul 1, 2024
1 parent 86b70a5 commit 75a1cff
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 44 deletions.
2 changes: 1 addition & 1 deletion cmd/nfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ linstor-gateway nfs create restricted 10.10.22.44/16 2G --allowed-ips 10.10.0.0/
Number: i + 1,
SizeKiB: uint64(val.Value / unit.K),
FileSystem: filesystem,
FileSystemRootOwner: common.UidGid{Uid: 65534, Gid: 65534}, // corresponds to "nobody:nobody"
FileSystemRootOwner: common.UserGroup{User: "nobody", Group: "nobody"},
},
})
}
Expand Down
18 changes: 9 additions & 9 deletions pkg/common/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,20 @@ import (
"github.com/LINBIT/golinstor/client"
)

type UidGid struct {
Uid int
Gid int
type UserGroup struct {
User string
Group string
}

func (u *UidGid) String() string {
return fmt.Sprintf("%d:%d", u.Uid, u.Gid)
func (u *UserGroup) String() string {
return fmt.Sprintf("%s:%s", u.User, u.Group)
}

type VolumeConfig struct {
Number int `json:"number"`
SizeKiB uint64 `json:"size_kib"`
FileSystem string `json:"file_system,omitempty"`
FileSystemRootOwner UidGid `json:"file_system_root_owner,omitempty"`
Number int `json:"number"`
SizeKiB uint64 `json:"size_kib"`
FileSystem string `json:"file_system,omitempty"`
FileSystemRootOwner UserGroup `json:"file_system_root_owner,omitempty"`
}

type ResourceStatus struct {
Expand Down
10 changes: 6 additions & 4 deletions pkg/common/resource_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package common

import (
"fmt"
"github.com/LINBIT/golinstor/client"
"github.com/LINBIT/linstor-gateway/pkg/reactor"
log "github.com/sirupsen/logrus"
"net"
"path/filepath"
"strings"

"github.com/LINBIT/golinstor/client"
log "github.com/sirupsen/logrus"

"github.com/LINBIT/linstor-gateway/pkg/reactor"
)

const (
Expand Down Expand Up @@ -37,7 +39,7 @@ func ClusterPrivateVolume() VolumeConfig {
Number: 0,
SizeKiB: clusterPrivateVolumeSizeKiB,
FileSystem: clusterPrivateVolumeFileSystem,
FileSystemRootOwner: UidGid{Uid: 0, Gid: 0},
FileSystemRootOwner: UserGroup{User: "root", Group: "root"},
}
}

Expand Down
5 changes: 2 additions & 3 deletions pkg/linstorcontrol/linstorcontrol.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"errors"
"fmt"
"sort"
"strconv"

"github.com/icza/gog"

Expand Down Expand Up @@ -219,8 +218,8 @@ func (l *Linstor) EnsureResource(ctx context.Context, res Resource, mayExist boo
volProps := map[string]string{}
if vol.FileSystem != "" {
volProps[apiconsts.NamespcFilesystem+"/"+apiconsts.KeyFsType] = vol.FileSystem
volProps[apiconsts.NamespcFilesystem+"/"+apiconsts.KeyFsUser] = strconv.Itoa(vol.FileSystemRootOwner.Uid)
volProps[apiconsts.NamespcFilesystem+"/"+apiconsts.KeyFsGroup] = strconv.Itoa(vol.FileSystemRootOwner.Gid)
volProps[apiconsts.NamespcFilesystem+"/"+apiconsts.KeyFsUser] = vol.FileSystemRootOwner.User
volProps[apiconsts.NamespcFilesystem+"/"+apiconsts.KeyFsGroup] = vol.FileSystemRootOwner.Group
}
var volFlags []string
if res.GrossSize {
Expand Down
42 changes: 21 additions & 21 deletions pkg/nfs/resource_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,22 +153,16 @@ func FromPromoter(cfg *reactor.PromoterConfig, definition *client.ResourceDefini
return r, nil
}

func parseRootOwner(mkfsParams string) (common.UidGid, error) {
func parseRootOwner(mkfsParams string) (common.UserGroup, error) {
rootOwnerRegex := regexp.MustCompile(`-E root_owner=(\d+):(\d+)`)
matches := rootOwnerRegex.FindStringSubmatch(mkfsParams)
if len(matches) != 3 {
return common.UidGid{}, fmt.Errorf("failed to parse uid and gid from MkfsParams: %q", mkfsParams)
return common.UserGroup{}, fmt.Errorf("failed to parse uid and gid from MkfsParams: %q", mkfsParams)
}

uid, err := strconv.Atoi(matches[1])
if err != nil {
return common.UidGid{}, fmt.Errorf("failed to parse uid from MkfsParams: %q", matches[1])
}
gid, err := strconv.Atoi(matches[2])
if err != nil {
return common.UidGid{}, fmt.Errorf("failed to parse gid from MkfsParams: %q", matches[2])
}
return common.UidGid{Uid: uid, Gid: gid}, nil
return common.UserGroup{
User: matches[1],
Group: matches[2],
}, nil
}

// parseVolume converts a resource agent of the type "ocf:heartbeat:Filesystem"
Expand Down Expand Up @@ -203,16 +197,22 @@ func parseVolume(agent *reactor.ResourceAgent, volumes []client.VolumeDefinition
if val, ok := vol.Props[apiconsts.NamespcFilesystem+"/Type"]; ok {
filesystem = val
}
var rootOwner common.UidGid
if val, ok := vol.Props[apiconsts.NamespcFilesystem+"/MkfsParams"]; ok {
rootOwner, err = parseRootOwner(val)
if err != nil {
log.WithFields(log.Fields{
"err": err,
"volume": vol.VolumeNumber,
"resource": resName,
}).Warnf("invalid MkfsParams for volume: %q", val)
var rootOwner common.UserGroup
if val, ok := vol.Props[apiconsts.NamespcFilesystem+apiconsts.KeyFsUser]; ok {
rootOwner.User = val
}
if val, ok := vol.Props[apiconsts.NamespcFilesystem+apiconsts.KeyFsGroup]; ok {
rootOwner.Group = val
}
if rootOwner.User == "" || rootOwner.Group == "" {
// for backwards compatibility, we also support the root_owner parameter in MkfsParams
if val, ok := vol.Props[apiconsts.NamespcFilesystem+apiconsts.KeyFsMkfsparameters]; ok {
rootOwner, err = parseRootOwner(val)
if err != nil {
return nil, err
}
}

}
if vol.VolumeNumber == nil {
vol.VolumeNumber = gog.Ptr(int32(0))
Expand Down
13 changes: 7 additions & 6 deletions pkg/nfs/resource_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ import (

func filesystemProps(vol VolumeConfig) map[string]string {
return map[string]string{
apiconsts.NamespcFilesystem + "/Type": vol.FileSystem,
apiconsts.NamespcFilesystem + "/MkfsParams": "-E nodiscard -E root_owner=" + vol.FileSystemRootOwner.String(),
apiconsts.NamespcFilesystem + "/Type": vol.FileSystem,
apiconsts.NamespcFilesystem + apiconsts.KeyFsUser: vol.FileSystemRootOwner.User,
apiconsts.NamespcFilesystem + apiconsts.KeyFsGroup: vol.FileSystemRootOwner.Group,
}
}

Expand All @@ -38,7 +39,7 @@ func TestResource_RoundTrip(t *testing.T) {
Number: 1,
SizeKiB: 1024,
FileSystem: "ext4",
FileSystemRootOwner: common.UidGid{Uid: 47, Gid: 11},
FileSystemRootOwner: common.UserGroup{User: "someone", Group: "somegroup"},
},
ExportPath: "/",
},
Expand Down Expand Up @@ -273,7 +274,7 @@ func TestParseRootOwner(t *testing.T) {
tests := []struct {
name string
input string
want common.UidGid
want common.UserGroup
wantErr bool
}{{
name: "empty",
Expand All @@ -286,11 +287,11 @@ func TestParseRootOwner(t *testing.T) {
}, {
name: "normal",
input: "-E root_owner=123:456",
want: common.UidGid{Uid: 123, Gid: 456},
want: common.UserGroup{User: "123", Group: "456"},
}, {
name: "other_text",
input: "-E something=else -E root_owner=123:456 -E other=stuff",
want: common.UidGid{Uid: 123, Gid: 456},
want: common.UserGroup{User: "123", Group: "456"},
}}
for i := range tests {
tcase := &tests[i]
Expand Down

0 comments on commit 75a1cff

Please sign in to comment.