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

Edit Zone API #603

Merged
merged 27 commits into from
May 23, 2018
Merged

Edit Zone API #603

merged 27 commits into from
May 23, 2018

Conversation

rishubhjain
Copy link
Contributor

No description provided.

Copy link
Member

@aravindavk aravindavk left a comment

Choose a reason for hiding this comment

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

Looks good. A few minor comments

@@ -15,3 +15,7 @@ const (
type AddDeviceReq struct {
Devices []string `json:"devices"`
}

type EditGroupReq struct {
Copy link
Member

Choose a reason for hiding this comment

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

Not required. group is already part of URL

Method: "POST",
Pattern: "/peers/{peerid}/group/{group_id}",
Version: 1,
RequestType: utils.GetTypeString((*deviceapi.EditGroupReq)(nil)),
Copy link
Member

Choose a reason for hiding this comment

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

Same here

ctx := r.Context()
logger := gdctx.GetReqLogger(ctx)

req := new(deviceapi.EditGroupReq)
Copy link
Member

Choose a reason for hiding this comment

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

Not required

}
err = txn.Ctx.Set("peerid", peerID)
if err != nil {
logger.WithError(err).Error("Failed to set data for transaction")
Copy link
Member

Choose a reason for hiding this comment

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

Also use WithField for peerID

}
err = txn.Ctx.Set("groupid", groupID)
if err != nil {
logger.WithError(err).Error("Failed to set data for transaction")
Copy link
Member

Choose a reason for hiding this comment

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

Also use WithField for groupID

restutils.SendHTTPError(ctx, w, http.StatusInternalServerError, "Transaction to edit group failed", api.ErrCodeDefault)
return
}
peerInfo, err := peer.GetPeer(peerID)
Copy link
Member

Choose a reason for hiding this comment

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

PeerInfo response may not be necessory. Just return success with a message

Copy link
Contributor

Choose a reason for hiding this comment

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

@rishubhjain

Add peer and edit peer currently returns peerinfo. However, as this API is under devices, as suggested by Aravinda, it's okay to just return http.StatusOK without a body 👍

func txnEditGroup(c transaction.TxnCtx) error {
var peerID string
var groupID string
var req deviceapi.EditGroupReq
Copy link
Member

Choose a reason for hiding this comment

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

req not required

c.Logger().WithError(err).Error("Failed transaction, cannot find group-id")
return err
}
if err := c.Get("req", req); err != nil {
Copy link
Member

Choose a reason for hiding this comment

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

not required

c.Logger().WithError(err).WithField("peerid", peerID).Error("Peer ID not found in store")
return err
}
peerInfo.MetaData["_group"] = req.Group
Copy link
Member

Choose a reason for hiding this comment

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

Use peerInfo.MetaData["_group"] = groupID

peerInfo.MetaData["_group"] = req.Group
err = peer.AddOrUpdatePeer(peerInfo)
if err != nil {
c.Logger().WithError(err).WithField("peerid", peerID).Error("Failed to update peer Info")
Copy link
Member

Choose a reason for hiding this comment

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

also add WithField groupID

Copy link
Member

@aravindavk aravindavk left a comment

Choose a reason for hiding this comment

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

Looks good

Copy link
Contributor

@prashanthpai prashanthpai left a comment

Choose a reason for hiding this comment

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

I'd prefer the edit peer PR to get in first.

Pattern: "/peers/{peerid}/group/{group_id}",
Version: 1,
ResponseType: utils.GetTypeString((*deviceapi.EditGroupResp)(nil)),
HandlerFunc: groupEditHandler,
Copy link
Contributor

Choose a reason for hiding this comment

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

peerGroupEditHandler

Same comment elsewhere. Prefix peer wherever applicable. Without that, someone new might mistake the group to be related to device and not peer.

c.Logger().WithError(err).WithField("peerid", peerID).Error("Peer ID not found in store")
return err
}
peerInfo.MetaData["_group"] = groupID
Copy link
Contributor

Choose a reason for hiding this comment

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

This is duplicate work. See if you can re-use the edit metadata functionality implemented in the other PR.

Copy link
Member

Choose a reason for hiding this comment

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

Edit Peer functionality can't be used. Because any group key starting with "_" is restricted with that API so that user configured Metadata will not override internal components Metadata.

Copy link
Contributor

Choose a reason for hiding this comment

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

What do you think of this ? Restrict edit peer handler from editing metadata keys that begin with _. We can re-use the transaction step function.

Copy link
Member

Choose a reason for hiding this comment

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

Makes sense.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@prashanthpai I have made changes in the the peer api PR,once that is merged I will update this code. Please review #600

route.Route{
Name: "EditGroup",
Method: "POST",
Pattern: "/peers/{peerid}/group/{group_id}",
Copy link
Contributor

Choose a reason for hiding this comment

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

We've never done this in other APIs - the request data being part of the URL. To maintain uniformity, I'd prefer if this was in the body.

@aravindavk
Copy link
Member

I'd prefer the edit peer PR to get in first.

Edit PR is unrelated to this

req := new(deviceapi.PeerEditGroupReq)
if err := restutils.UnmarshalRequest(r, req); err != nil {
logger.WithError(err).Error("Failed to Unmarshal request")
restutils.SendHTTPError(ctx, w, http.StatusBadRequest, "Unable to marshal request", api.ErrCodeDefault)
Copy link
Contributor

Choose a reason for hiding this comment

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

Unmarshal, not marshal

return
}

peerID := mux.Vars(r)["peerid"]
Copy link
Contributor

Choose a reason for hiding this comment

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

Use uuid.Parse to validate.

}
err = txn.Ctx.Set("peerid", peerID)
if err != nil {
logger.WithError(err).WithField("PeerID", peerID).Error("Failed to set data for transaction")
Copy link
Contributor

Choose a reason for hiding this comment

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

End this error statement with in transaction context. Same comment for this usage elsewhere too.

restutils.SendHTTPError(ctx, w, http.StatusInternalServerError, "Transaction to edit group failed", api.ErrCodeDefault)
return
}
peerInfo, err := peer.GetPeer(peerID)
Copy link
Contributor

Choose a reason for hiding this comment

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

@rishubhjain

Add peer and edit peer currently returns peerinfo. However, as this API is under devices, as suggested by Aravinda, it's okay to just return http.StatusOK without a body 👍

}
}

// RegisterStepFuncs registers transaction step functions with
// Glusterd Transaction framework
func (p *Plugin) RegisterStepFuncs() {
transaction.RegisterStepFunc(txnPrepareDevice, "prepare-device")
transaction.RegisterStepFunc(txnPeerEditGroup, "peer-edit-group")
Copy link
Contributor

Choose a reason for hiding this comment

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

Wait until the edit peer metadata PR gets in. You can re-use code (step function) from that PR here.

@rishubhjain rishubhjain force-pushed the group branch 4 times, most recently from f41a387 to ba23334 Compare March 26, 2018 09:11
@rishubhjain rishubhjain changed the title Edit Group API Edit Zone API Mar 26, 2018
@rishubhjain rishubhjain force-pushed the group branch 5 times, most recently from de27fcf to f0e1922 Compare March 26, 2018 12:14
@@ -81,6 +90,14 @@ func addPeerHandler(w http.ResponseWriter, r *http.Request) {
}

newpeer.MetaData = req.MetaData
if req.Zone != "" {
if newpeer.MetaData != nil {
Copy link
Member

Choose a reason for hiding this comment

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

nit: can be simplified

if newpeer.MetaData == nil {
    newpeer.MetaData = make(map[string]string)
}
newpeer.MetaData["_zone"] = req.Zone

p.MetaData = make(map[string]string)
}
if p.MetaData["_zone"] == "" {
p.MetaData["_zone"] = "1"
Copy link
Member

Choose a reason for hiding this comment

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

Do not default it to "1". If zone is not added for any peers then all peers will belong to same zone(that is "1"). Peer.ID can be used as default.

p.MetaData["_zone"] = p.ID

@@ -49,13 +54,13 @@ func deviceAddHandler(w http.ResponseWriter, r *http.Request) {
}
err = txn.Ctx.Set("peerid", peerID)
if err != nil {
logger.WithError(err).Error("Failed to set data for transaction")
logger.WithError(err).WithField("key", peerID).Error("Failed to set key in transaction context")
Copy link
Member

Choose a reason for hiding this comment

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

To understand structured logging better. Above message will be logged as

Failed to set key in transaction context      key=53503353-0ba8-4fd3-a8cf-aba2798ab8e5

Note: Peer ID used is just for example.

Advantage of structured logging is that, message remains constant even if failure is for different Peer ID and all the dynamic fields are easily parsable by script. Traditionally logs are written as free hand format, but it makes very difficult to parse the logs through scripts for making sense out of log messages. Structured logging will help to address this issue. WithField accepts two fields, one is key and other one is value. Key name should be self explanatory and should not consist spaces. With this understanding, change the above log message as,

logger.WithError(err).WithField("key", "peerid").WithField("value", peerID).Error("Failed to set key in transaction context")

@rishubhjain rishubhjain force-pushed the group branch 2 times, most recently from 7e7e851 to 79e5e6b Compare March 28, 2018 04:34
Copy link
Member

@aravindavk aravindavk left a comment

Choose a reason for hiding this comment

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

Looks good to me

@aravindavk
Copy link
Member

retest this please

@rishubhjain rishubhjain force-pushed the group branch 2 times, most recently from 814dcf2 to ec8c72c Compare March 30, 2018 15:04
Copy link
Member

@aravindavk aravindavk left a comment

Choose a reason for hiding this comment

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

A few minor comments

@@ -80,7 +89,16 @@ func addPeerHandler(w http.ResponseWriter, r *http.Request) {
return
}

newpeer.MetaData = req.MetaData
if newpeer.Metadata == nil {
Copy link
Member

Choose a reason for hiding this comment

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

Since this is Peer Add, it is safe to assume no Metadata exists. if newpeer.Metadata == nil is not required.

p.ClientAddresses, err = normalizeAddrs()
if err != nil {
return err
}

peerInfo, err := GetPeer(gdctx.MyUUID.String())
Copy link
Member

Choose a reason for hiding this comment

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

Why these changes required?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In case the glusterd2 service was restarted and the data (metadata ) already existed then it is important to go and get back the data .

return
}
if !CheckIfDeviceExist(req.Devices, devices) {
logger.WithError(err).WithField("device", req.Devices).Error("One or more already exists")
Copy link
Member

Choose a reason for hiding this comment

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

nit: error message can be changed to "One or more devices already exists"

@@ -13,16 +13,29 @@ func GetDevices(peerID string) ([]deviceapi.Info, error) {
if err != nil {
return nil, err
}
if len(peerInfo.MetaData["devices"]) > 0 {
if len(peerInfo.Metadata["devices"]) > 0 {
Copy link
Member

Choose a reason for hiding this comment

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

_devices?

var deviceInfo []deviceapi.Info
if err := json.Unmarshal([]byte(peerInfo.MetaData["devices"]), &deviceInfo); err != nil {
if err := json.Unmarshal([]byte(peerInfo.Metadata["devices"]), &deviceInfo); err != nil {
Copy link
Member

Choose a reason for hiding this comment

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

_devices

@rishubhjain rishubhjain mentioned this pull request Apr 26, 2018
@@ -25,6 +26,14 @@ func addPeerHandler(w http.ResponseWriter, r *http.Request) {
return
}

for key := range req.Metadata {
if strings.HasPrefix(key, "_") {
logger.WithField("metadata-key", key).Error("Key names starting with '_' are restricted in metadata field")
Copy link
Member

Choose a reason for hiding this comment

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

This error can be added to generic errors list. Used this in multiple places and also Volume metadata will also requires this error msg.

@@ -0,0 +1,51 @@
package cmdexec
Copy link
Member

Choose a reason for hiding this comment

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

Move only device commands to plugins/device/deviceutils/utils.go

package deviceutils
func CreatePV
func CreateVG
func RemovePV
func RemoveVG

Move other parts of code back to transactions.go.

plugins/device/deviceutils/utils.go can be moved to pkg/deviceutils later if required.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why is there a need to move commands to device utils?, won't it be useful if a separate library is made for commands

Copy link
Member

Choose a reason for hiding this comment

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

cmdexec is not a good name for library, doesn't give any clue what that cmdexec is. Another problem with current approach is that this library can't be used without having Transaction context. Library should be independent of Transaction/etcd so that it can be reused in other places like Tests.

Copy link
Member

Choose a reason for hiding this comment

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

Based on the discussion with you, I grouped the device related functions in separate file here 2adafaa#diff-388b0ce2a0b41316c76c470557c4cbd1

@rishubhjain rishubhjain force-pushed the group branch 8 times, most recently from f03e833 to ba5ae60 Compare May 21, 2018 07:26
func CheckIfDeviceExist(reqDevice string, devices []deviceapi.Info) bool {
for _, key := range devices {
if reqDevice == key.Name {
return false
Copy link
Member

Choose a reason for hiding this comment

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

return true?

}
return
}

var devices []deviceapi.Info
err = json.Unmarshal([]byte(peerInfo.Metadata["_"]), &devices)
Copy link
Member

Choose a reason for hiding this comment

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

peerInfo.Metadata["_devices"]?

restutils.SendHTTPError(ctx, w, http.StatusInternalServerError, err)
return
}
if !CheckIfDeviceExist(req.Device, devices) {
Copy link
Member

Choose a reason for hiding this comment

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

flip condition. see comment below

}
err := AddDevices(deviceList, peerID.String())
c.Logger().WithField("device", device).Info("Device setup successful, setting device status to 'DeviceEnabled'")
Copy link
Member

Choose a reason for hiding this comment

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

s/DeviceEnabled/Enabled

Copy link
Contributor

@prashanthpai prashanthpai left a comment

Choose a reason for hiding this comment

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

Have suggested some minor changes.

Further, the contents/logic present in txnPeerEdit() need not be a transaction step but can be handled in the handler itself. It simplifies the code. Considering that this PR has been on review for a long time, I'm okay if you can address that refactoring in a separate PR.

//CreatePV is used to create physical volume.
func CreatePV(device string) error {
pvcreateCmd := exec.Command("pvcreate", "--metadatasize=128M", "--dataalignment=256K", device)
if err := pvcreateCmd.Run(); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

The Go report service will likely flag this as redundant. You can directly return.

return pvcreateCmd.Run()

Please do the same for all the functions in this file.

return nil, err
}
return deviceInfo, nil
}
return nil, nil
}

// AddDevices adds device to specific peer
func AddDevices(devices []deviceapi.Info, peerID string) error {
//CheckIfDeviceExist returns error if all devices already exist or returns list of devices to be added
Copy link
Contributor

Choose a reason for hiding this comment

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

Incorrect comment: This function returns true if any of the devices exist.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, do not export this function until you have an external consumer out of this package.

}

// AddDevice adds device of specific peer
func AddDevice(device deviceapi.Info, peerID string) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

Do not export this if it's not currently used outside this package.

return err
}
if err := c.Get("req", req); err != nil {
c.Logger().WithError(err).Error("Failed transaction, cannot find device-details")

Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion for improvement (not in this PR but later):

Every call to c.Get translates to a etcd client call. You can create a local structure containing both peer ID and device name and then set it in the transaction context.

}
err := AddDevices(deviceList, peerID.String())
c.Logger().WithField("device", device).Info("Device setup successful, setting device status to 'Enabled'")
deviceInfo.State = deviceapi.DeviceEnabled
Copy link
Contributor

Choose a reason for hiding this comment

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

You can create the entire deviceapi.Info structure here itself for better readability:

deviceInfo = deviceapi.Info {
    Name : device,
    State: deviceapi.DeviceEnabled,
}

@rishubhjain
Copy link
Contributor Author

@prashanthpai Addressed the comments, please review

@prashanthpai prashanthpai merged commit 09f1358 into gluster:master May 23, 2018
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