Skip to content
This repository was archived by the owner on Mar 26, 2020. It is now read-only.

volgen: Code based Volfile generation#497

Merged
kshlm merged 7 commits intogluster:masterfrom
aravindavk:volgen2
Jan 10, 2018
Merged

volgen: Code based Volfile generation#497
kshlm merged 7 commits intogluster:masterfrom
aravindavk:volgen2

Conversation

@aravindavk
Copy link
Copy Markdown
Member

@aravindavk aravindavk commented Dec 20, 2017

Sub volumes support is added to Volinfo. Code based volfile generation
is implemented(Still exploring the possible approach to do that based on
input json/yml/toml)

All volfiles available in $SRC/glusterd2/volgen2/volfile_*.go

Features:

  • Easy to add condition while generating volfile(For example, bitrot
    volfile only contains local bricks information)
  • Easy to generate Cluster level, Volume level and Brick level volfiles
  • Adding new volfile support is easy(Add one file)
  • Full access to Cluster Info/Volume Info/Brick Info
  • All supported volfiles are available now
  • All generated volfiles are stored in etcd
  • REST endpoint available to trigger regeneration of volfiles(Selective
    regeneration not yet available)

Limitations:

  • Currently limited to code based volfile generation. If new volfile
    added or modified, Glusterd2 need to be recompiled. I tried template
    based approach to support cluster volfiles but it is getting over
    complecated. If this is not blocker now, we can proceed with this
    approach.

Future:

  • Template file(json/yml/toml) support can be added on top of
    this if required.

Fixes: #388
Signed-off-by: Aravinda VK avishwan@redhat.com

@amarts
Copy link
Copy Markdown
Member

amarts commented Dec 27, 2017

Currently limited to code based volfile generation. If new volfile added or modified, Glusterd2 need to be recompiled. I tried template based approach to support cluster volfiles but it is getting over complecated. If this is not blocker now, we can proceed with this approach.

Ack!

Copy link
Copy Markdown
Member

@kshlm kshlm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, I like the new volfile and entry types and methods associated with them. Much cleaner than what I had done. Makes it easier to write custom generator funtions than before. I see no problems inusing this new framework to generate graphs using templates, but that can be done a little later.

One major concern I have right now is that, there is a lot of code duplication. There are several patterns in use, which can all be simplified into standalone functions that can be reused. This will also help in later work to use templates.

I've mainly looked at the volgen and volinfo changes, and a little of the volume create request in this review. I've not looked at the changes done to other commands.

logger.WithError(err).Error("could not prepare node list")
restutils.SendHTTPError(ctx, w, http.StatusInternalServerError, err.Error(), api.ErrCodeDefault)
return
var nodesMap = make(map[string]int)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could just update nodesFromBricks to accept []Brickinfo, and pass the bricks variable you created earlier.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok

if req.Arbiter != 0 {
if req.Replica != 3 || req.Arbiter != 1 {
return nil, errors.New("For arbiter configuration, replica count must be 3 and arbiter count must be 1. The 3rd brick of the replica will be the arbiter")
for idx, subvolreq := range req.Subvols {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assumption here with the request is that the subvols are only 2 levels deep, which works for existing cases. But it will be nice if we were to support an arbitrary levels, which will help us implement a tiered volume much more easily in the future. This shouldn't need too much changes to the request format.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do have that support in Subvol struct, but not checked that in all other places now.

I need to consider, subvol.Bricks if subvol.Subvols is nil. I will work on this part later.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do have that support in Subvol struct, but not checked that in all other places now.

Yup. I noticed that.

}

var bricks []brick.Brickinfo
for _, subvol := range volinfo.Subvols {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pattern is repeated many times to get the bricks list of a volume. Please have a common method on the *Volinfo to get a list of bricks. This will also help us easily extend the volume subvol structure later on.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just realized now that, it is used in only two places volume-create and volume-expand. VolumeCreateReq is (VolumeCreateReq->Subvols->Bricks) and VolumeExpandReq is (VolumeExpandReq->Bricks). Not easy to have common func. I moved the code to brickutils but as two func.(duplicate code not avoided but now available in single place)

)

last := volfile.RootEntry.
Add("protocol/server", vol, b).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can very easily be converted to depend on the template file we have. But we can do that later.

volfile.FileName = vol.Name

dht := volfile.RootEntry.Add("debug/io-stats", vol, nil).SetName(vol.Name).
Add("performance/io-threads", vol, nil).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All client volfiles have this section with these common xlators. There should be a single function to add these xlators that is used where required. And this can also be easily generated from a template.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will introduce AddMany and accept list.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No I didn't mean this. What I want is a single function that adds this particular list of xlators in this particular order. That single function can be reused elsewhere.

Comment thread glusterd2/volgen2/volfile_fuse.go Outdated

for subvolIdx, subvol := range vol.Subvols {
if subvol.Type == volume.SubvolReplicate {
name := fmt.Sprintf("%s-replicate-%d", vol.Name, subvolIdx)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not be programatically generating the names for replicate/ec/dist (cluster) xlators each time we generate volfiles. We should do this once when the volume is created, or when a new brick set is added to the volume and save it with the volinfo, and use the saved names here. This will allow us to also accept subvol names during volume create, which will help with migration from 3.x to 4.0.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice idea.

I do have subvol name like s1, s2.. I will change the subvol name as <volname>-<subvoltype>-<idx> in subvol struct itself

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than index, give it unique names, uuids. Index will become hard to keep track of after a few expansions/shrinks of the the volume.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes please! This is one of my primary ask. (Hence I was asking for ability to pass the distribute subvolume name in API itself (to help with backward compatibility)).

Comment thread glusterd2/volgen2/volfile_fuse.go Outdated
Add("cluster/distribute", vol, nil)

for subvolIdx, subvol := range vol.Subvols {
if subvol.Type == volume.SubvolReplicate {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why only replicate? Wouldn't EC also require this?

Also, bricks are being added to the graph only when this condition is true. So distribute volumes don't have any bricks added to the graph.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't considered EC since EC support patch was in review. I will look into this condition again

Comment thread glusterd2/volgen2/volfile_fuse.go Outdated
Add("performance/write-behind", vol, nil).
Add("cluster/distribute", vol, nil)

for subvolIdx, subvol := range vol.Subvols {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be made a common function as well. We will need to attach the cluster graph to other graphs several times.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not done as single function since bitd volfile differs with respect to local bricks. I will give it a try now.

@aravindavk
Copy link
Copy Markdown
Member Author

@kshlm Thanks for the comments, I will address the comments and refresh the patch soon.

@aravindavk
Copy link
Copy Markdown
Member Author

@kshlm please review

Copy link
Copy Markdown
Member

@kshlm kshlm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need some more details on how the volfiles are actually being generated for volume create and other apis.

A few more comments about refactoring code for better readability.

And my request from the previous review about a common function to add the client xlator stack is yet to be done. If this isn't something you want to do now, please let me know.

DoFunc: "vol-create.Validate",
Nodes: nodes,
},
{
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When exactly are volfiles generated? I see the new volfile endpoint, but I don't understand how exactly it works.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In $SRC/glusterd2/commands/volumes/common.go:storeVolume, Incremental generation of volfiles is not yet implemented. All the Volfiles will be (re)generated when volinfo is stored.(Create/Expand/Set etc)

if !uuid.Equal(b.NodeID, gdctx.MyUUID) {
continue
}
for _, b := range vol.GetBricks(true) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a small nit. The volume variable is named vol here but volinfo in the startAllBricks() function above. Isn't consistent.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not changed the names in existing code. I will update this.

Comment thread glusterd2/volgen2/generate.go Outdated
}

// Generate generates all the volfiles(Cluster/Volume/Brick)
func Generate() error {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is huge, and can be split into individual functions for generating volume volfiles, brick volfiles and cluster volfiles.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And my request from the previous review about a common function to add the client xlator stack is yet to be done. If this isn't something you want to do now, please let me know.

Only client graph and gfproxy are using common list of xlators for now. But that may differ in future. I don't see much repeatation there.

Type string
VolumeID uuid.UUID
BrickID uuid.UUID
ExtraOptions map[string]string
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the difference between ExtraOptions and ExtraData? A comment here will help.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will add the details

Comment thread glusterd2/volgen2/volgen.go Outdated
"github.com/pborman/uuid"
)

var varStrRE = regexp.MustCompile(`\{\{\s*(\S+)\s*\}\}`)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move the var string code into its own file. Keeps things much more readable.

Comment thread glusterd2/volgen2/volgen.go Outdated

// getValue returns value if found for provided graph.xlator.keys in the options map
// XXX: Not possibly the best place for this
func getValue(graph, xl string, keys []string, opts map[string]string) (string, string, bool) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getValue and getOptions can be moved into a seperate files (utils?).

Comment thread glusterd2/volume/struct.go Outdated
}

// GetBricks returns a list of Bricks
func (v *Volinfo) GetBricks(onlyLocal bool) []brick.Brickinfo {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be nicer if this were two functions GetBricks and GetLocalBricks. Makes it much more understandable when calling from elsewhere, as you don't have any trouble understanding the true/false being passed.

This current GetBricks(bool) function can become and unexported getBricks(bool) and the newer exported GetBricks() and GetLocalBricks() functions can call it.

Comment thread pkg/api/volume_req.go
type VolExpandReq struct {
ReplicaCount int `json:"replica,omitempty"`
Bricks []string `json:"bricks"`
ReplicaCount int `json:"replica,omitempty"`
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is okay for now. But the expected API to add bricks which aligns with the new create API, is to be able to accept a list of subvols with the new bricks/subvols. For eg.,

[
    {
        "SubvolID": "00adc43c-6eeb-47d9-912a-12daf6cde2c7",
        "Bricks": [
            {
                "NodeID": "8d1c03a7-0ac8-4072-a8c2-83f31c92ccd2",
                "Path": "/new/brick"
            }
        ],
        "Subvols": []
    },
    {
        "SubvolID": "3378e563-705d-4eb0-a9a0-cb9bf2301634",
        "Bricks": [
            {
                "NodeID": "e8986e52-bb46-4bbc-91b6-0c45b0ef1872",
                "Path": "/new/brick"
            }
        ],
        "Subvols": []
    }
]

This will make it slightly harder for our cli, but makes the expand api way more powerful.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for supporting current syntax for Volume Expand. We need to have discussion on all the Sub volume based commands. Like Add new subvol, Delete Subvol, Expand a subvol etc.

Sub volumes support is added to Volinfo. Code based volfile generation
is implemented(Still exploring the possible approach to do that based on
input json/yml/toml)

All volfiles available in `$SRC/glusterd2/volgen2/volfile_*.go`

Features:

- Easy to add condition while generating volfile(For example, bitrot
  volfile only contains local bricks information)
- Easy to generate Cluster level, Volume level and Brick level volfiles
- Adding new volfile support is easy(Add one file)
- Full access to Cluster Info/Volume Info/Brick Info
- All supported volfiles are available now
- All generated volfiles are stored in etcd
- REST endpoint available to trigger regeneration of volfiles(Selective
  regeneration not yet available)

Limitations:
- Currently limited to code based volfile generation. If new volfile
  added or modified, Glusterd2 need to be recompiled. I tried template
  based approach to support cluster volfiles but it is getting over
  complecated. If this is not blocker now, we can proceed with this
  approach.

Future:
- Template file(json/yml/toml) support can be added on top of
  this if required.

Fixes: #388
Signed-off-by: Aravinda VK <avishwan@redhat.com>
Signed-off-by: Aravinda VK <avishwan@redhat.com>
Merged duplicate code, simplified interface for volfiles.
Now it is easy to support both interface code and template for
volfile generation

Signed-off-by: Aravinda VK <avishwan@redhat.com>
Signed-off-by: Aravinda VK <avishwan@redhat.com>
Added subvolume Name and ID in volume-expand

Signed-off-by: Aravinda VK <avishwan@redhat.com>
Signed-off-by: Aravinda VK <avishwan@redhat.com>
Also rebased after disperse volume integration

Signed-off-by: Aravinda VK <avishwan@redhat.com>
@aravindavk
Copy link
Copy Markdown
Member Author

@kshlm updated the code and rebased again. Please review

@kshlm kshlm merged commit 8ef3beb into gluster:master Jan 10, 2018
@aravindavk aravindavk deleted the volgen2 branch January 11, 2018 06:27
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants