Beispiel #1
0
func unmarshalVolCreateRequest(msg *volume.VolCreateRequest, r *http.Request) (int, error) {
	e := utils.GetJSONFromRequest(r, msg)
	if e != nil {
		log.WithField("error", e).Error("Failed to parse the JSON Request")
		return 422, gderrors.ErrJSONParsingFailed
	}

	if msg.Name == "" {
		log.Error("Volume name is empty")
		return http.StatusBadRequest, gderrors.ErrEmptyVolName
	}
	if len(msg.Bricks) <= 0 {
		log.WithField("volume", msg.Name).Error("Brick list is empty")
		return http.StatusBadRequest, gderrors.ErrEmptyBrickList
	}
	return 0, nil

}
Beispiel #2
0
func (c *Command) volumeCreate(w http.ResponseWriter, r *http.Request) {

	var msg volume.VolCreateRequest

	e := utils.GetJSONFromRequest(r, &msg)
	if e != nil {
		client.SendResponse(w, -1, 422, errors.ErrJSONParsingFailed.Error(), 422, "")
		return
	}

	if msg.Name == "" {
		log.Error("Volume name is empty")
		client.SendResponse(w, -1, http.StatusBadRequest, errors.ErrEmptyVolName.Error(), http.StatusBadRequest, "")
		return
	}
	if len(msg.Bricks) <= 0 {
		log.Error("Brick list is empty")
		client.SendResponse(w, -1, http.StatusBadRequest, errors.ErrEmptyBrickList.Error(), http.StatusBadRequest, "")
		return
	}

	if context.Store.VolumeExists(msg.Name) {
		log.WithField("Volume", msg.Name).Error("Volume already exists")
		client.SendResponse(w, -1, http.StatusBadRequest, errors.ErrVolExists.Error(), http.StatusBadRequest, "")
		return
	}

	vol := volume.NewVolumeEntry(msg)
	e = context.Store.AddOrUpdateVolume(vol)
	if e != nil {
		log.WithField("error", e).Error("Couldn't add volume to store")
		client.SendResponse(w, -1, http.StatusInternalServerError, e.Error(), http.StatusInternalServerError, "")
		return
	}

	// Creating client  and server volfile
	volgen.GenerateVolfile(vol)

	log.WithField("volume", vol.Name).Debug("NewVolume added to store")
	client.SendResponse(w, 0, 0, "", http.StatusCreated, "")
}
Beispiel #3
0
func addPeerHandler(w http.ResponseWriter, r *http.Request) {
	var req peer.PeerAddRequest
	if e := utils.GetJSONFromRequest(r, &req); e != nil {
		rest.SendHTTPError(w, http.StatusBadRequest, e.Error())
		return
	}

	if len(req.Addresses) < 1 {
		rest.SendHTTPError(w, http.StatusBadRequest, errors.ErrNoHostnamesPresent.Error())
		return
	}

	if req.Name == "" {
		req.Name = req.Addresses[0]
	}

	//TODO: Do proper validation before initiating the add process

	//FIXME: In the correct add process, the peer being probed would add it's details to the store once it's been validated. The code below is just a temporary stand-in to show how the API's would work

	p := &peer.Peer{
		ID:        uuid.NewRandom(),
		Name:      req.Name,
		Addresses: req.Addresses,
	}

	rsp, e := client.ValidateAddPeer(&req)
	if e != nil {
		rest.SendHTTPError(w, http.StatusInternalServerError, *rsp.OpError)
		return
	}
	if e = peer.AddOrUpdatePeer(p); e != nil {
		rest.SendHTTPError(w, http.StatusInternalServerError, e.Error())
		return
	}

	rest.SendHTTPResponse(w, http.StatusOK, nil)

}
Beispiel #4
0
func addPeerHandler(w http.ResponseWriter, r *http.Request) {

	// FIXME: This is not txn based, yet. Behaviour when multiple simultaneous
	// add peer requests are sent to same node is unknown.

	var req PeerAddReq
	if e := utils.GetJSONFromRequest(r, &req); e != nil {
		rest.SendHTTPError(w, http.StatusBadRequest, e.Error())
		return
	}

	if len(req.Addresses) < 1 {
		rest.SendHTTPError(w, http.StatusBadRequest, errors.ErrNoHostnamesPresent.Error())
		return
	}

	// A peer can have multiple addresses. For now, we use only the first
	// address present in the req.Addresses list.

	remotePeerAddress, err := utils.FormRemotePeerAddress(req.Addresses[0])
	if err != nil {
		rest.SendHTTPError(w, http.StatusBadRequest, err.Error())
		return
	}

	// This remote call will return the remote peer's ID (UUID), name
	// and etcd peer url.
	remotePeer, e := ValidateAddPeer(remotePeerAddress, &req)
	if e != nil {
		rest.SendHTTPError(w, http.StatusInternalServerError, remotePeer.OpError)
		return
	}

	// TODO: Parse addresses considering ports to figure this out.
	if isPeerInCluster(remotePeer.UUID) {
		rest.SendHTTPError(w, http.StatusInternalServerError, "Peer already in cluster")
		return
	}

	// If user hasn't specified peer name, use the name returned by remote
	// peer which defaults to it's hostname.
	if req.Name == "" {
		req.Name = remotePeer.PeerName
	}

	// Adding a member is a two step process:
	// 	1. Add the new member to the cluster via the members API. This is
	//	   performed on this node i.e the one that just accepted peer add
	//	   request from the user.
	//	2. Start the new member on the target node (the new peer) with the new
	//         cluster configuration, including a list of the updated members
	//	   (existing members + the new member).

	newMember, e := etcdmgmt.EtcdMemberAdd("http://" + remotePeer.EtcdPeerAddress)
	if e != nil {
		log.WithFields(log.Fields{
			"error":   e,
			"uuid":    remotePeer.UUID,
			"name":    req.Name,
			"address": remotePeer.EtcdPeerAddress,
		}).Error("Failed to add member to etcd cluster.")
		rest.SendHTTPError(w, http.StatusInternalServerError, e.Error())
		return
	}

	log.WithField("member-id", newMember.ID).Info("Added new member to etcd cluster")

	mlist, e := etcdmgmt.EtcdMemberList()
	if e != nil {
		log.WithField("error", e).Error("Failed to list members in etcd cluster")
		rest.SendHTTPError(w, http.StatusInternalServerError, e.Error())
		return
	}

	// Member name of the newly added etcd member has not been set at this point.
	conf := []string{}
	for _, memb := range mlist {
		for _, u := range memb.PeerURLs {
			n := memb.Name
			if memb.ID == newMember.ID {
				n = remotePeer.UUID
			}
			conf = append(conf, fmt.Sprintf("%s=%s", n, u))
		}
	}

	var etcdConf EtcdConfigReq
	etcdConf.EtcdName = remotePeer.UUID
	etcdConf.InitialCluster = strings.Join(conf, ",")
	etcdConf.ClusterState = "existing"

	log.WithField("initial-cluster", etcdConf.InitialCluster).Debug("Reconfiguring etcd on remote peer")

	etcdrsp, e := ConfigureRemoteETCD(remotePeerAddress, &etcdConf)
	if e != nil {
		log.WithField("err", e).Error("Failed to configure remote etcd")
		rest.SendHTTPError(w, http.StatusInternalServerError, etcdrsp.OpError)
		return
	}

	// Create a new peer object and add it to the store.
	p := &peer.Peer{
		ID:        uuid.Parse(remotePeer.UUID),
		Name:      req.Name,
		Addresses: req.Addresses,
		MemberID:  newMember.ID,
	}
	if e = peer.AddOrUpdatePeer(p); e != nil {
		log.WithFields(log.Fields{
			"error":     e,
			"peer/node": p.Name,
		}).Error("Failed to add peer into the etcd store")
		rest.SendHTTPError(w, http.StatusInternalServerError, e.Error())
		return
	}

	body := map[string]uuid.UUID{"id": p.ID}
	rest.SendHTTPResponse(w, http.StatusCreated, body)
}