Exemplo n.º 1
0
// --- tests --------------------------------------------------------------------------
func TestPass_pledge(t *testing.T) {

	fmt.Fprintf(os.Stderr, "\n------- make passthrou pledge -----------\n")
	host := "host"
	port := "7890"
	commence := time.Now().Unix() + 3600
	expiry := int64(commence + 45)
	id := "res-test-pass-pledge"
	ukey := "my-cookie"

	ppt1, err := gizmos.Mk_pass_pledge(&host, &port, commence, expiry, &id, &ukey)
	if err != nil {
		fmt.Fprintf(os.Stderr, "cannot make pass pledge; all other passthrough tests aborted: %s	[FAIL]\n", err)
		t.Fail()
		return
	}
	fmt.Fprintf(os.Stderr, "mk successful\n")

	pptc := ppt1.Clone("cloned")
	if pptc == nil {
		fmt.Fprintf(os.Stderr, "cannot clone pass pledge; all other passthrough tests aborted	[FAIL]\n")
		t.Fail()
		return
	}
	fmt.Fprintf(os.Stderr, "clone successful\n")

	host2 := "host2"
	port2 := "7890"
	id2 := "res-test-pass-pledge2"
	ukey2 := "my-cookie"
	ppt2, err := gizmos.Mk_pass_pledge(&host2, &port2, commence, expiry, &id2, &ukey2)
	if err != nil {
		fmt.Fprintf(os.Stderr, "cannot make second pass pledge; all other passthrough tests aborted: %s	[FAIL]\n", err)
		t.Fail()
		return
	}

	gp := gizmos.Pledge(pptc) // must convert to a generic pledge so we can take address off next
	if ppt1.Equals(&gp) {
		fmt.Fprintf(os.Stderr, "clone reports equal [OK]\n")
	} else {
		fmt.Fprintf(os.Stderr, "clone reports !equal [FAIL]\n")
	}

	gp = gizmos.Pledge(ppt2) // must convert to a generic pledge so we can take address off next
	if ppt1.Equals(&gp) {
		fmt.Fprintf(os.Stderr, "second pledge reports equal [FAIL]\n")
	} else {
		fmt.Fprintf(os.Stderr, "second pledge reports !equal [OK]\n")
	}

	fmt.Fprintf(os.Stderr, "json:   %s\n", ppt1.To_json())
	fmt.Fprintf(os.Stderr, "string: %s\n", ppt1)
	fmt.Fprintf(os.Stderr, "chkpt: %s\n", ppt1.To_chkpt())

}
Exemplo n.º 2
0
/*
	Pulls the reservation from the inventory. Similar to delete, but not quite the same.
	This will clone the pledge. The clone is expired and left in the inventory to force
	a reset of flowmods. The network manager is sent a request to delete the queues
	associated with the path and the path is removed from the original pledge. The original
	pledge is returned so that it can be used to generate a new set of paths based on the
	hosts, expiry and bandwidth requirements of the initial reservation.

	Unlike the get/del functions, this is meant for internal support and does not
	require a cookie.

	It is important to delete the reservation from the network manager point of view
	BEFORE the expiry is reset. If expiry is set first then the network manager will
	cause queue timeslices to be split on that boundary leaving dangling queues.
*/
func (inv *Inventory) yank_res(name *string) (p *gizmos.Pledge, state error) {

	state = nil
	p = inv.cache[*name]
	if p != nil {
		switch pldg := (*p).(type) {
		case *gizmos.Pledge_bw:
			rm_sheep.Baa(2, "resgmgr: yanked reservation: %s", (*p).To_str())
			cp := pldg.Clone(*name + ".yank") // clone but DO NOT set conclude time until after network delete!

			icp := gizmos.Pledge(cp)        // must convert to a pledge interface
			inv.cache[*name+".yank"] = &icp // and then insert the address of the interface

			inv.cache[*name] = nil // yank original from the list
			delete(inv.cache, *name)
			pldg.Set_path_list(nil) // no path list for this pledge

			ch := make(chan *ipc.Chmsg)
			defer close(ch) // close it on return
			req := ipc.Mk_chmsg()
			req.Send_req(nw_ch, ch, REQ_DEL, cp, nil) // delete from the network point of view
			req = <-ch                                // wait for response from network
			state = req.State

			// now safe to set these
			cp.Set_expiry(time.Now().Unix() + 1) // force clone to be expired
			cp.Reset_pushed()                    // force it to go out again

			// not supported for other pledge types
		}
	} else {
		state = fmt.Errorf("no reservation with name: %s", *name)
		rm_sheep.Baa(2, "resgmgr: unable to yank, no reservation with name: %s", *name)
	}

	return
}
Exemplo n.º 3
0
/*
 *	Parse and react to a POST to /tegu/mirrors/. We expect JSON describing the mirror request, to wit:
 *		{
 *			"start_time": "nnn",                 // optional
 *			"end_time": "nnn",                   // required
 *			"output": "<output spec>",           // required
 *			"port": [ "port1" , "port2", ...],   // required
 *			"vlan": "vlan",                      // optional
 *			"cookie": "value",                   // optional
 *			"name": "mirrorname",                // optional
 *		}
 *
 *	Because multiple mirrors may be created as a result, we return an array of JSON results, one for each mirror:
 *		[
 *		  {
 *			"name": "mirrorname",   // tegu or user-defined mirror name
 *			"url": "url",           // URL to use for DELETE or GET
 *			"error": "err"          // error message (if any)
 *		  },
 *		  ....
 *		]
 */
func mirror_post(in *http.Request, out http.ResponseWriter, data []byte) (code int, msg string) {
	http_sheep.Baa(5, "Request data: "+string(data))
	code = http.StatusOK

	// 1. Unmarshall the JSON request, check for required fields
	type req_type struct {
		Start_time string   `json:"start_time"`
		End_time   string   `json:"end_time"` // required
		Output     string   `json:"output"`   // required
		Port       []string `json:"port"`     // required
		Vlan       string   `json:"vlan"`
		Cookie     string   `json:"cookie"`
		Name       string   `json:"name"`
	}
	var req req_type
	if err := json.Unmarshal(data, &req); err != nil {
		code = http.StatusBadRequest
		msg = "Bad JSON: " + err.Error()
		return
	}
	if req.End_time == "" || req.Output == "" || len(req.Port) == 0 {
		code = http.StatusBadRequest
		msg = "Missing a required field."
		return
	}

	// 2. Check start/end times, and VLAN list
	stime, etime, err := checkTimes(req.Start_time, req.End_time)
	if err != nil {
		code = http.StatusBadRequest
		msg = err.Error()
		return
	}
	err = validVlanList(req.Vlan)
	if err != nil {
		code = http.StatusBadRequest
		msg = err.Error()
		return
	}

	// 3. Generate random name if not given
	if req.Name == "" {
		req.Name = generateMirrorName()
	} else if !validName(req.Name) {
		code = http.StatusBadRequest
		msg = "Invalid mirror name: " + req.Name
		return
	}

	// 4. Validate input ports, and assign into groups
	plist, err := validatePorts(req.Port, req.Name)
	if err != nil {
		// no valid ports, give up
		code = http.StatusBadRequest
		msg = err.Error()
		return
	}

	// 5. Validate output port
	newport, err := validateOutputPort(&req.Output)
	if err != nil {
		code = http.StatusBadRequest
		msg = err.Error()
		return
	}
	req.Output = *newport

	// 6. Make one pledge per mirror, send to reservation mgr, build JSON return string
	scheme := "http"
	if isSSL {
		scheme = "https"
	}
	code = http.StatusCreated
	sep := "\n"
	bs := bytes.NewBufferString("[")
	for key, mirror := range *plist {
		if key != "_badports_" {
			// Make a pledge
			phost := key
			nam := mirror.name
			res, err := gizmos.Mk_mirror_pledge(mirror.ports, &req.Output, stime, etime, &nam, &req.Cookie, &phost, &req.Vlan)
			if res != nil {
				req := ipc.Mk_chmsg()
				my_ch := make(chan *ipc.Chmsg) // allocate channel for responses to our requests
				defer close(my_ch)             // close it on return

				gp := gizmos.Pledge(res)                                            // convert to generic pledge to pass
				req.Send_req(rmgr_ch, my_ch, REQ_DUPCHECK, &gp, nil)                // see if we have a duplicate in the cache
				req = <-my_ch                                                       // get response from the network thread
				if req.Response_data != nil && req.Response_data.(*string) != nil { // response is a pointer to string, if the pointer isn't nil it's a dup
					rp := req.Response_data.(*string)
					if rp != nil {
						http_sheep.Baa(1, "duplicate mirror reservation was dropped")
						err = fmt.Errorf("reservation duplicates existing reservation: %s", *rp)
					}
				} else {
					req = ipc.Mk_chmsg()
					ip := gizmos.Pledge(res)                        // must pass an interface pointer to resmgr
					req.Send_req(rmgr_ch, my_ch, REQ_ADD, &ip, nil) // network OK'd it, so add it to the inventory
					req = <-my_ch                                   // wait for completion

					if req.State == nil {
						ckptreq := ipc.Mk_chmsg()
						ckptreq.Send_req(rmgr_ch, nil, REQ_CHKPT, nil, nil) // request a chkpt now, but don't wait on it
					} else {
						err = fmt.Errorf("%s", req.State)
					}
				}

				if res_paused {
					http_sheep.Baa(1, "reservations are paused, accepted reservation will not be pushed until resumed")
					res.Pause(false) // when paused we must mark the reservation as paused and pushed so it doesn't push until resume received
					res.Set_pushed()
				}

			} else {
				if err == nil {
					err = fmt.Errorf("specific reason unknown") // ensure we have something for message
				}
			}

			mirror.err = err
		}

		bs.WriteString(fmt.Sprintf(`%s { "name": "%s", `, sep, mirror.name))
		bs.WriteString(fmt.Sprintf(`"port": [ `))
		sep2 := ""
		for _, p := range mirror.ports {
			bs.WriteString(fmt.Sprintf(`%s"%s"`, sep2, p))
			sep2 = ", "
		}
		bs.WriteString(fmt.Sprintf(` ], `))
		if mirror.err == nil {
			bs.WriteString(fmt.Sprintf(`"url": "%s://%s/tegu/mirrors/%s/"`, scheme, in.Host, mirror.name))
		} else {
			bs.WriteString(fmt.Sprintf(`"error": "%s"`, mirror.err.Error()))
		}
		bs.WriteString(" }")
		sep = ",\n"
	}
	bs.WriteString("\n]\n")
	msg = bs.String()
	return
}