Example #1
0
func TestVolumeEntryExpandMaxBrickLimit(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Create the app
	app := NewTestApp(tmpfile)
	defer app.Close()

	// Create a large cluster
	err := setupSampleDbWithTopology(app,
		10,     // clusters
		4,      // nodes_per_cluster
		24,     // devices_per_node,
		600*GB, // disksize)
	)
	tests.Assert(t, err == nil)

	// Create large volume
	v := createSampleVolumeEntry(100)
	err = v.Create(app.db, app.executor, app.allocator)
	tests.Assert(t, err == nil)

	// Add a bunch of bricks until the limit
	fakebricks := make(sort.StringSlice, BRICK_MAX_NUM-len(v.Bricks))
	v.Bricks = append(v.Bricks, fakebricks...)

	// Try to expand the volume, but it will return that the max number
	// of bricks has been reached
	err = v.Expand(app.db, app.executor, app.allocator, 100)
	tests.Assert(t, err == ErrMaxBricks, err)
}
Example #2
0
func TestNewBrickEntryNewInfoResponse(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Create the app
	app := NewTestApp(tmpfile)
	defer app.Close()

	// Create a brick
	b := NewBrickEntry(10, 20, 5, "abc", "def")

	// Save element in database
	err := app.db.Update(func(tx *bolt.Tx) error {
		return b.Save(tx)
	})
	tests.Assert(t, err == nil)

	var info *BrickInfo
	err = app.db.View(func(tx *bolt.Tx) error {
		brick, err := NewBrickEntryFromId(tx, b.Id())
		if err != nil {
			return err
		}

		info, err = brick.NewInfoResponse(tx)
		return err
	})
	tests.Assert(t, err == nil)
	tests.Assert(t, reflect.DeepEqual(*info, b.Info))
}
Example #3
0
func TestGlusterFSDBFileLoad(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	db := NewGlusterFSDB(tmpfile)

	db.nodes["one"] = &NodeEntry{
		Info: requests.NodeInfoResp{
			Name: "nodetest",
		},
	}
	db.volumes["a"] = &VolumeEntry{
		Info: requests.VolumeInfoResp{
			Name: "volumetest",
		},
	}

	err := db.Commit()
	tests.Assert(t, err == nil)

	newdb := NewGlusterFSDB(tmpfile)
	tests.Assert(t, newdb != nil)

	tests.Assert(t, newdb.nodes["one"].Info.Name == db.nodes["one"].Info.Name)
	tests.Assert(t, newdb.volumes["a"].Info.Name == db.volumes["a"].Info.Name)
}
Example #4
0
func TestVolumeExpandIdNotFound(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Create the app
	app := NewTestApp(tmpfile)
	defer app.Close()
	router := mux.NewRouter()
	app.SetRoutes(router)

	// Setup the server
	ts := httptest.NewServer(router)
	defer ts.Close()

	// JSON Request
	request := []byte(`{
        "expand_size" : 100
    }`)

	// Now that we have some data in the database, we can
	// make a request for the clutser list
	r, err := http.Post(ts.URL+"/volumes/12345/expand",
		"application/json",
		bytes.NewBuffer(request))
	tests.Assert(t, err == nil)
	tests.Assert(t, r.StatusCode == http.StatusNotFound, r.StatusCode)
	body, err := ioutil.ReadAll(io.LimitReader(r.Body, r.ContentLength))
	tests.Assert(t, err == nil)
	r.Body.Close()
	tests.Assert(t, strings.Contains(string(body), "Id not found"))
}
Example #5
0
func TestVolumeCreateSmallSize(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Create the app
	app := NewTestApp(tmpfile)
	defer app.Close()
	router := mux.NewRouter()
	app.SetRoutes(router)

	// Setup the server
	ts := httptest.NewServer(router)
	defer ts.Close()

	// VolumeCreate JSON Request
	request := []byte(`{
        "size" : 0
    }`)

	// Send request
	r, err := http.Post(ts.URL+"/volumes", "application/json", bytes.NewBuffer(request))
	tests.Assert(t, err == nil)
	tests.Assert(t, r.StatusCode == http.StatusBadRequest)
	body, err := ioutil.ReadAll(io.LimitReader(r.Body, r.ContentLength))
	tests.Assert(t, err == nil)
	r.Body.Close()
	tests.Assert(t, strings.Contains(string(body), "Invalid volume size"))
}
Example #6
0
func TestNewBrickEntryFromId(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Create the app
	app := NewTestApp(tmpfile)
	defer app.Close()

	// Create a brick
	b := NewBrickEntry(10, 20, 5, "abc", "def")

	// Save element in database
	err := app.db.Update(func(tx *bolt.Tx) error {
		return b.Save(tx)
	})
	tests.Assert(t, err == nil)

	var brick *BrickEntry
	err = app.db.View(func(tx *bolt.Tx) error {
		var err error
		brick, err = NewBrickEntryFromId(tx, b.Info.Id)
		return err
	})
	tests.Assert(t, err == nil)
	tests.Assert(t, reflect.DeepEqual(brick, b))

}
Example #7
0
func TestVolumeEntryFromId(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Create the app
	app := NewTestApp(tmpfile)
	defer app.Close()

	// Create a volume entry
	v := createSampleVolumeEntry(1024)

	// Save in database
	err := app.db.Update(func(tx *bolt.Tx) error {
		return v.Save(tx)
	})
	tests.Assert(t, err == nil)

	// Load from database
	var entry *VolumeEntry
	err = app.db.View(func(tx *bolt.Tx) error {
		var err error
		entry, err = NewVolumeEntryFromId(tx, v.Info.Id)
		return err
	})
	tests.Assert(t, err == nil)
	tests.Assert(t, reflect.DeepEqual(entry, v))

}
Example #8
0
func TestVolumeListEmpty(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Create the app
	app := NewTestApp(tmpfile)
	defer app.Close()
	router := mux.NewRouter()
	app.SetRoutes(router)

	// Setup the server
	ts := httptest.NewServer(router)
	defer ts.Close()

	// Get volumes, there should be none
	r, err := http.Get(ts.URL + "/volumes")
	tests.Assert(t, r.StatusCode == http.StatusOK)
	tests.Assert(t, err == nil)
	tests.Assert(t, r.Header.Get("Content-Type") == "application/json; charset=UTF-8")

	// Read response
	var msg VolumeListResponse
	err = utils.GetJsonFromResponse(r, &msg)
	tests.Assert(t, err == nil)
	tests.Assert(t, len(msg.Volumes) == 0)
}
Example #9
0
func TestClientCluster(t *testing.T) {
	db := tests.Tempfile()
	defer os.Remove(db)

	// Create the app
	app := glusterfs.NewTestApp(db)
	defer app.Close()

	// Setup the server
	ts := setupHeketiServer(app)
	defer ts.Close()

	// Create cluster with unknown user
	c := NewClient(ts.URL, "asdf", "")
	tests.Assert(t, c != nil)
	cluster, err := c.ClusterCreate()
	tests.Assert(t, err != nil)
	tests.Assert(t, cluster == nil)

	// Create cluster with bad password
	c = NewClient(ts.URL, "admin", "badpassword")
	tests.Assert(t, c != nil)
	cluster, err = c.ClusterCreate()
	tests.Assert(t, err != nil)
	tests.Assert(t, cluster == nil)

	// Create cluster correctly
	c = NewClient(ts.URL, "admin", TEST_ADMIN_KEY)
	tests.Assert(t, c != nil)
	cluster, err = c.ClusterCreate()
	tests.Assert(t, err == nil)
	tests.Assert(t, cluster.Id != "")
	tests.Assert(t, len(cluster.Nodes) == 0)
	tests.Assert(t, len(cluster.Volumes) == 0)

	// Request bad id
	info, err := c.ClusterInfo("bad")
	tests.Assert(t, err != nil)
	tests.Assert(t, info == nil)

	// Get information about the client
	info, err = c.ClusterInfo(cluster.Id)
	tests.Assert(t, err == nil)
	tests.Assert(t, reflect.DeepEqual(info, cluster))

	// Get a list of clusters
	list, err := c.ClusterList()
	tests.Assert(t, err == nil)
	tests.Assert(t, len(list.Clusters) == 1)
	tests.Assert(t, list.Clusters[0] == info.Id)

	// Delete non-existent cluster
	err = c.ClusterDelete("badid")
	tests.Assert(t, err != nil)

	// Delete current cluster
	err = c.ClusterDelete(info.Id)
	tests.Assert(t, err == nil)
}
Example #10
0
func TestVolumeDelete(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Create the app
	app := NewTestApp(tmpfile)
	defer app.Close()
	router := mux.NewRouter()
	app.SetRoutes(router)

	// Setup the server
	ts := httptest.NewServer(router)
	defer ts.Close()

	// Setup database
	err := setupSampleDbWithTopology(app,
		1,    // clusters
		10,   // nodes_per_cluster
		10,   // devices_per_node,
		5*TB, // disksize)
	)
	tests.Assert(t, err == nil)

	// Create a volume
	v := createSampleVolumeEntry(100)
	tests.Assert(t, v != nil)
	err = v.Create(app.db, app.executor, app.allocator)
	tests.Assert(t, err == nil)

	// Delete the volume
	req, err := http.NewRequest("DELETE", ts.URL+"/volumes/"+v.Info.Id, nil)
	tests.Assert(t, err == nil)
	r, err := http.DefaultClient.Do(req)
	tests.Assert(t, err == nil)
	tests.Assert(t, r.StatusCode == http.StatusAccepted)
	location, err := r.Location()
	tests.Assert(t, err == nil)

	// Query queue until finished
	for {
		r, err = http.Get(location.String())
		tests.Assert(t, err == nil)
		if r.Header.Get("X-Pending") == "true" {
			tests.Assert(t, r.StatusCode == http.StatusOK)
			time.Sleep(time.Millisecond * 10)
			continue
		} else {
			tests.Assert(t, r.StatusCode == http.StatusNoContent)
			tests.Assert(t, err == nil)
			break
		}
	}

	// Check it is not there
	r, err = http.Get(ts.URL + "/volumes/" + v.Info.Id)
	tests.Assert(t, r.StatusCode == http.StatusNotFound)
	tests.Assert(t, err == nil)
}
Example #11
0
func TestVolumeList(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Create the app
	app := NewTestApp(tmpfile)
	defer app.Close()
	router := mux.NewRouter()
	app.SetRoutes(router)

	// Setup the server
	ts := httptest.NewServer(router)
	defer ts.Close()

	// Create some volumes
	numvolumes := 1000
	err := app.db.Update(func(tx *bolt.Tx) error {

		for i := 0; i < numvolumes; i++ {
			v := createSampleVolumeEntry(100)
			err := v.Save(tx)
			if err != nil {
				return err
			}
		}

		return nil

	})
	tests.Assert(t, err == nil)

	// Get volumes, there should be none
	r, err := http.Get(ts.URL + "/volumes")
	tests.Assert(t, r.StatusCode == http.StatusOK)
	tests.Assert(t, err == nil)
	tests.Assert(t, r.Header.Get("Content-Type") == "application/json; charset=UTF-8")

	// Read response
	var msg VolumeListResponse
	err = utils.GetJsonFromResponse(r, &msg)
	tests.Assert(t, err == nil)
	tests.Assert(t, len(msg.Volumes) == numvolumes)

	// Check that all the volumes are in the database
	err = app.db.View(func(tx *bolt.Tx) error {
		for _, id := range msg.Volumes {
			_, err := NewVolumeEntryFromId(tx, id)
			if err != nil {
				return err
			}
		}

		return nil
	})
	tests.Assert(t, err == nil)

}
Example #12
0
func TestVolumeCreateBadDispersionValues(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Create the app
	app := NewTestApp(tmpfile)
	defer app.Close()
	router := mux.NewRouter()
	app.SetRoutes(router)

	// Setup the server
	ts := httptest.NewServer(router)
	defer ts.Close()

	// VolumeCreate JSON Request
	request := []byte(`{
        "size" : 100,
        "durability": {
        	"type": "disperse",
        	"disperse": {
            	"data" : 8,
            	"redundancy" : 1
        	}
    	}
    }`)

	// Send request
	r, err := http.Post(ts.URL+"/volumes", "application/json", bytes.NewBuffer(request))
	tests.Assert(t, err == nil)
	tests.Assert(t, r.StatusCode == http.StatusBadRequest)
	body, err := ioutil.ReadAll(io.LimitReader(r.Body, r.ContentLength))
	tests.Assert(t, err == nil)
	r.Body.Close()
	tests.Assert(t, strings.Contains(string(body), "Invalid dispersion combination"))

	// VolumeCreate JSON Request
	request = []byte(`{
        "size" : 100,
        "durability": {
        	"type": "disperse",
        	"disperse": {
            	"data" : 4,
            	"redundancy" : 3
        	}
    	}
    }`)

	// Send request
	r, err = http.Post(ts.URL+"/volumes", "application/json", bytes.NewBuffer(request))
	tests.Assert(t, err == nil)
	tests.Assert(t, r.StatusCode == http.StatusBadRequest)
	body, err = ioutil.ReadAll(io.LimitReader(r.Body, r.ContentLength))
	tests.Assert(t, err == nil)
	r.Body.Close()
	tests.Assert(t, strings.Contains(string(body), "Invalid dispersion combination"))
}
Example #13
0
func TestDeviceAddBadRequests(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Patch dbfilename so that it is restored at the end of the tests
	defer tests.Patch(&dbfilename, tmpfile).Restore()

	// Create the app
	app := NewApp()
	defer app.Close()
	router := mux.NewRouter()
	app.SetRoutes(router)

	// Setup the server
	ts := httptest.NewServer(router)
	defer ts.Close()

	// ClusterCreate JSON Request
	request := []byte(`{
        bad json
    }`)

	// Post bad JSON
	r, err := http.Post(ts.URL+"/devices", "application/json", bytes.NewBuffer(request))
	tests.Assert(t, err == nil)
	tests.Assert(t, r.StatusCode == 422)

	// Make a request with no devices
	request = []byte(`{
        "node" : "123",
        "devices" : []
    }`)

	// Post bad JSON
	r, err = http.Post(ts.URL+"/devices", "application/json", bytes.NewBuffer(request))
	tests.Assert(t, err == nil)
	tests.Assert(t, r.StatusCode == http.StatusBadRequest)

	// Make a request with unknown node
	request = []byte(`{
        "node" : "123",
        "devices" : [
            {
                "name" : "/dev/fake",
                "weight" : 20
            }
        ]
    }`)

	// Post bad JSON
	r, err = http.Post(ts.URL+"/devices", "application/json", bytes.NewBuffer(request))
	tests.Assert(t, err == nil)
	tests.Assert(t, r.StatusCode == http.StatusNotFound)

}
Example #14
0
func TestNewNodeEntryNewInfoResponse(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Patch dbfilename so that it is restored at the end of the tests
	defer tests.Patch(&dbfilename, tmpfile).Restore()

	// Create the app
	app := NewApp()
	defer app.Close()

	// Create a node
	req := &NodeAddRequest{
		ClusterId: "123",
		Hostnames: HostAddresses{
			Manage:  []string{"manage"},
			Storage: []string{"storage"},
		},
		Zone: 99,
	}

	n := NewNodeEntryFromRequest(req)

	// Save element in database
	err := app.db.Update(func(tx *bolt.Tx) error {
		return n.Save(tx)
	})
	tests.Assert(t, err == nil)

	var info *NodeInfoResponse
	err = app.db.View(func(tx *bolt.Tx) error {
		node, err := NewNodeEntryFromId(tx, n.Info.Id)
		if err != nil {
			return err
		}

		info, err = node.NewInfoReponse(tx)
		if err != nil {
			return err
		}

		return nil

	})
	tests.Assert(t, err == nil)

	tests.Assert(t, info.ClusterId == n.Info.ClusterId)
	tests.Assert(t, info.Id == n.Info.Id)
	tests.Assert(t, info.Zone == n.Info.Zone)
	tests.Assert(t, len(info.Hostnames.Manage) == 1)
	tests.Assert(t, len(info.Hostnames.Storage) == 1)
	tests.Assert(t, reflect.DeepEqual(info.Hostnames.Manage, n.Info.Hostnames.Manage))
	tests.Assert(t, reflect.DeepEqual(info.Hostnames.Storage, n.Info.Hostnames.Storage))
}
Example #15
0
func TestVolumeInfo(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Create the app
	app := NewTestApp(tmpfile)
	defer app.Close()
	router := mux.NewRouter()
	app.SetRoutes(router)

	// Setup the server
	ts := httptest.NewServer(router)
	defer ts.Close()

	// Setup database
	err := setupSampleDbWithTopology(app,
		1,    // clusters
		10,   // nodes_per_cluster
		10,   // devices_per_node,
		5*TB, // disksize)
	)
	tests.Assert(t, err == nil)

	// Create a volume
	req := &VolumeCreateRequest{}
	req.Size = 100
	req.Durability.Type = DURABILITY_STRING_EC
	v := NewVolumeEntryFromRequest(req)
	tests.Assert(t, v != nil)
	err = v.Create(app.db, app.executor, app.allocator)
	tests.Assert(t, err == nil)

	// Now that we have some data in the database, we can
	// make a request for the clutser list
	r, err := http.Get(ts.URL + "/volumes/" + v.Info.Id)
	tests.Assert(t, r.StatusCode == http.StatusOK)
	tests.Assert(t, err == nil)
	tests.Assert(t, r.Header.Get("Content-Type") == "application/json; charset=UTF-8")

	// Read response
	var msg VolumeInfoResponse
	err = utils.GetJsonFromResponse(r, &msg)
	tests.Assert(t, err == nil)

	tests.Assert(t, msg.Id == v.Info.Id)
	tests.Assert(t, msg.Cluster == v.Info.Cluster)
	tests.Assert(t, msg.Name == v.Info.Name)
	tests.Assert(t, msg.Size == v.Info.Size)
	tests.Assert(t, reflect.DeepEqual(msg.Durability, v.Info.Durability))
	tests.Assert(t, reflect.DeepEqual(msg.Snapshot, v.Info.Snapshot))
	for _, brick := range msg.Bricks {
		tests.Assert(t, utils.SortedStringHas(v.Bricks, brick.Id))
	}
}
Example #16
0
func TestVolumeEntryCreateBrickCreationFailure(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Create the app
	app := NewTestApp(tmpfile)
	defer app.Close()

	// Lots of nodes with little drives
	err := setupSampleDbWithTopology(app,
		1,      // clusters
		4,      // nodes_per_cluster
		4,      // devices_per_node,
		500*GB, // disksize)
	)
	tests.Assert(t, err == nil)

	// Cause a brick creation failure
	mockerror := errors.New("MOCK")
	app.xo.MockBrickCreate = func(host string, brick *executors.BrickRequest) (*executors.BrickInfo, error) {
		return nil, mockerror
	}

	// Create a volume with a snapshot factor of 1.5
	// For a 200G vol, it would get a brick size of 100G, with a thin pool
	// size of 100G * 1.5 = 150GB.
	v := createSampleVolumeEntry(200)
	err = v.Create(app.db, app.executor, app.allocator)
	tests.Assert(t, err == mockerror)

	// Check database is still clean. No bricks and No volumes
	err = app.db.View(func(tx *bolt.Tx) error {
		volumes, err := VolumeList(tx)
		tests.Assert(t, err == nil)
		tests.Assert(t, len(volumes) == 0)

		bricks, err := BrickList(tx)
		tests.Assert(t, err == nil)
		tests.Assert(t, len(bricks) == 0)

		clusters, err := ClusterList(tx)
		tests.Assert(t, err == nil)
		tests.Assert(t, len(clusters) == 1)

		cluster, err := NewClusterEntryFromId(tx, clusters[0])
		tests.Assert(t, err == nil)
		tests.Assert(t, len(cluster.Info.Volumes) == 0)

		return nil

	})
	tests.Assert(t, err == nil)
}
Example #17
0
func TestNewDeviceEntryNewInfoResponse(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Patch dbfilename so that it is restored at the end of the tests
	defer tests.Patch(&dbfilename, tmpfile).Restore()

	// Create the app
	app := NewApp()
	defer app.Close()

	// Create a device
	req := &Device{
		Name:   "dev",
		Weight: 123,
	}
	nodeid := "abc"

	d := NewDeviceEntryFromRequest(req, nodeid)
	d.Info.Storage.Free = 10
	d.Info.Storage.Total = 100
	d.Info.Storage.Used = 1000
	d.BrickAdd("abc")
	d.BrickAdd("def")

	// Save element in database
	err := app.db.Update(func(tx *bolt.Tx) error {
		return d.Save(tx)
	})
	tests.Assert(t, err == nil)

	var info *DeviceInfoResponse
	err = app.db.View(func(tx *bolt.Tx) error {
		device, err := NewDeviceEntryFromId(tx, d.Info.Id)
		if err != nil {
			return err
		}

		info, err = device.NewInfoResponse(tx)
		if err != nil {
			return err
		}

		return nil

	})
	tests.Assert(t, err == nil)
	tests.Assert(t, info.Id == d.Info.Id)
	tests.Assert(t, info.Name == d.Info.Name)
	tests.Assert(t, info.Weight == d.Info.Weight)
	tests.Assert(t, reflect.DeepEqual(info.Storage, d.Info.Storage))
	tests.Assert(t, len(info.Bricks) == 0)
}
Example #18
0
func TestClusterCreate(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Patch dbfilename so that it is restored at the end of the tests
	defer tests.Patch(&dbfilename, tmpfile).Restore()

	// Create the app
	app := NewApp()
	defer app.Close()
	router := mux.NewRouter()
	app.SetRoutes(router)

	// Setup the server
	ts := httptest.NewServer(router)
	defer ts.Close()

	// ClusterCreate JSON Request
	request := []byte(`{
    }`)

	// Post nothing
	r, err := http.Post(ts.URL+"/clusters", "application/json", bytes.NewBuffer(request))
	tests.Assert(t, err == nil)
	tests.Assert(t, r.StatusCode == http.StatusCreated)

	// Read JSON
	var msg ClusterInfoResponse
	err = utils.GetJsonFromResponse(r, &msg)
	tests.Assert(t, err == nil)

	// Test JSON
	tests.Assert(t, len(msg.Nodes) == 0)
	tests.Assert(t, len(msg.Volumes) == 0)

	// Check that the data on the database is recorded correctly
	var entry ClusterEntry
	err = app.db.View(func(tx *bolt.Tx) error {
		return entry.Unmarshal(
			tx.Bucket([]byte(BOLTDB_BUCKET_CLUSTER)).
				Get([]byte(msg.Id)))
	})
	tests.Assert(t, err == nil)

	// Make sure they entries are euqal
	tests.Assert(t, entry.Info.Id == msg.Id)
	tests.Assert(t, len(entry.Info.Volumes) == 0)
	tests.Assert(t, len(entry.Info.Nodes) == 0)
}
Example #19
0
func TestVolumeEntryCreateMaxBrickSize(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Create the app
	app := NewTestApp(tmpfile)
	defer app.Close()

	// Create 500TB of storage
	err := setupSampleDbWithTopology(app,
		1,    // clusters
		10,   // nodes_per_cluster
		10,   // devices_per_node,
		5*TB, // disksize)
	)
	tests.Assert(t, err == nil)

	// Create a volume whose bricks must be at most BRICK_MAX_SIZE
	v := createSampleVolumeEntry(int(BRICK_MAX_SIZE / GB * 4))
	err = v.Create(app.db, app.executor, app.allocator)
	tests.Assert(t, err == nil)

	// Get volume information
	var info *VolumeInfoResponse
	err = app.db.View(func(tx *bolt.Tx) error {
		entry, err := NewVolumeEntryFromId(tx, v.Info.Id)
		if err != nil {
			return err
		}

		info, err = entry.NewInfoResponse(tx)
		if err != nil {
			return err
		}

		return nil

	})
	tests.Assert(t, err == nil)

	// Check the size of the bricks are not bigger than BRICK_MAX_SIZE
	tests.Assert(t, len(info.Bricks) == 8)
	for b := 1; b < len(info.Bricks); b++ {
		tests.Assert(t, info.Bricks[b].Size <= BRICK_MAX_SIZE)
	}
	tests.Assert(t, info.Cluster == v.Info.Cluster)

}
Example #20
0
func TestVolumeEntrySaveDelete(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Create the app
	app := NewTestApp(tmpfile)
	defer app.Close()

	// Create a volume entry
	v := createSampleVolumeEntry(1024)

	// Save in database
	err := app.db.Update(func(tx *bolt.Tx) error {
		return v.Save(tx)
	})
	tests.Assert(t, err == nil)

	// Delete entry which has devices
	var entry *VolumeEntry
	err = app.db.Update(func(tx *bolt.Tx) error {
		var err error
		entry, err = NewVolumeEntryFromId(tx, v.Info.Id)
		if err != nil {
			return err
		}

		err = entry.Delete(tx)
		if err != nil {
			return err
		}

		return nil

	})
	tests.Assert(t, err == nil)

	// Check volume has been deleted and is not in db
	err = app.db.View(func(tx *bolt.Tx) error {
		var err error
		entry, err = NewVolumeEntryFromId(tx, v.Info.Id)
		if err != nil {
			return err
		}
		return nil

	})
	tests.Assert(t, err == ErrNotFound)
}
Example #21
0
func TestDeviceInfo(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Patch dbfilename so that it is restored at the end of the tests
	defer tests.Patch(&dbfilename, tmpfile).Restore()

	// Create the app
	app := NewApp()
	defer app.Close()
	router := mux.NewRouter()
	app.SetRoutes(router)

	// Setup the server
	ts := httptest.NewServer(router)
	defer ts.Close()

	// Create a device to save in the db
	device := NewDeviceEntry()
	device.Info.Id = "abc"
	device.Info.Name = "/dev/fake1"
	device.Info.Weight = 101
	device.NodeId = "def"
	device.StorageSet(10000)
	device.StorageAllocate(1000)

	// Save device in the db
	err := app.db.Update(func(tx *bolt.Tx) error {
		return device.Save(tx)
	})
	tests.Assert(t, err == nil)

	// Get device information
	r, err := http.Get(ts.URL + "/devices/" + device.Info.Id)
	tests.Assert(t, err == nil)
	tests.Assert(t, r.StatusCode == http.StatusOK)
	tests.Assert(t, r.Header.Get("Content-Type") == "application/json; charset=UTF-8")

	var info DeviceInfoResponse
	err = utils.GetJsonFromResponse(r, &info)
	tests.Assert(t, info.Id == device.Info.Id)
	tests.Assert(t, info.Name == device.Info.Name)
	tests.Assert(t, info.Weight == device.Info.Weight)
	tests.Assert(t, info.Storage.Free == device.Info.Storage.Free)
	tests.Assert(t, info.Storage.Used == device.Info.Storage.Used)
	tests.Assert(t, info.Storage.Total == device.Info.Storage.Total)

}
Example #22
0
func TestDeviceDeleteErrors(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Patch dbfilename so that it is restored at the end of the tests
	defer tests.Patch(&dbfilename, tmpfile).Restore()

	// Create the app
	app := NewApp()
	defer app.Close()
	router := mux.NewRouter()
	app.SetRoutes(router)

	// Setup the server
	ts := httptest.NewServer(router)
	defer ts.Close()

	// Create a device to save in the db
	device := NewDeviceEntry()
	device.Info.Id = "abc"
	device.Info.Name = "/dev/fake1"
	device.Info.Weight = 101
	device.NodeId = "def"
	device.StorageSet(10000)
	device.StorageAllocate(1000)

	// Save device in the db
	err := app.db.Update(func(tx *bolt.Tx) error {
		return device.Save(tx)
	})
	tests.Assert(t, err == nil)

	// Delete unknown id
	req, err := http.NewRequest("DELETE", ts.URL+"/devices/123", nil)
	tests.Assert(t, err == nil)
	r, err := http.DefaultClient.Do(req)
	tests.Assert(t, err == nil)
	tests.Assert(t, r.StatusCode == http.StatusNotFound)

	// Delete device without a node there.. that's probably a really
	// bad situation
	req, err = http.NewRequest("DELETE", ts.URL+"/devices/"+device.Info.Id, nil)
	tests.Assert(t, err == nil)
	r, err = http.DefaultClient.Do(req)
	tests.Assert(t, err == nil)
	tests.Assert(t, r.StatusCode == http.StatusInternalServerError)

}
Example #23
0
func TestSimpleAllocatorInitFromDb(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Setup database
	app := NewTestApp(tmpfile)
	defer app.Close()

	// Create large cluster
	err := setupSampleDbWithTopology(app,
		1,      // clusters
		10,     // nodes_per_cluster
		20,     // devices_per_node,
		600*GB, // disksize)
	)
	tests.Assert(t, err == nil)

	// Get the cluster list
	var clusterId string
	err = app.db.View(func(tx *bolt.Tx) error {
		clusters, err := ClusterList(tx)
		if err != nil {
			return err
		}
		tests.Assert(t, len(clusters) == 1)
		clusterId = clusters[0]

		return nil
	})
	tests.Assert(t, err == nil)

	// Create an allocator and initialize it from the DB
	a := NewSimpleAllocatorFromDb(app.db)
	tests.Assert(t, a != nil)

	// Get the nodes from the ring
	ch, _, errc := a.GetNodes(clusterId, utils.GenUUID())

	var devices int
	for d := range ch {
		devices++
		tests.Assert(t, d != "")
	}
	err = <-errc
	tests.Assert(t, devices == 10*20)
	tests.Assert(t, err == nil)

}
Example #24
0
func TestNewClusterEntryFromIdNotFound(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Create the app
	app := NewTestApp(tmpfile)
	defer app.Close()

	// Test for ID not found
	err := app.db.View(func(tx *bolt.Tx) error {
		_, err := NewClusterEntryFromId(tx, "123")
		return err
	})
	tests.Assert(t, err == ErrNotFound)

}
Example #25
0
func TestVolumeEntryExpandCreateBricksFailure(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Create the app
	app := NewTestApp(tmpfile)
	defer app.Close()

	// Create large cluster
	err := setupSampleDbWithTopology(app,
		10,     // clusters
		10,     // nodes_per_cluster
		20,     // devices_per_node,
		600*GB, // disksize)
	)
	tests.Assert(t, err == nil)

	// Create volume
	v := createSampleVolumeEntry(100)
	err = v.Create(app.db, app.executor, app.allocator)
	tests.Assert(t, err == nil)

	// Save a copy of the volume before expansion
	vcopy := &VolumeEntry{}
	*vcopy = *v

	// Mock create bricks to fail
	ErrMock := errors.New("MOCK")
	app.xo.MockBrickCreate = func(host string, brick *executors.BrickRequest) (*executors.BrickInfo, error) {
		return nil, ErrMock
	}

	// Expand volume
	err = v.Expand(app.db, app.executor, app.allocator, 500)
	tests.Assert(t, err == ErrMock)

	// Check db is the same as before expansion
	var entry *VolumeEntry
	err = app.db.View(func(tx *bolt.Tx) error {
		var err error
		entry, err = NewVolumeEntryFromId(tx, v.Info.Id)

		return err
	})
	tests.Assert(t, err == nil)
	tests.Assert(t, reflect.DeepEqual(vcopy, entry))
}
Example #26
0
func TestNodeDeleteErrors(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Patch dbfilename so that it is restored at the end of the tests
	defer tests.Patch(&dbfilename, tmpfile).Restore()

	// Create the app
	app := NewApp()
	defer app.Close()
	router := mux.NewRouter()
	app.SetRoutes(router)

	// Setup the server
	ts := httptest.NewServer(router)
	defer ts.Close()

	// Create a node to save in the db
	node := NewNodeEntry()
	node.Info.Id = "abc"
	node.Info.ClusterId = "123"
	node.Info.Hostnames.Manage = sort.StringSlice{"manage.system"}
	node.Info.Hostnames.Storage = sort.StringSlice{"storage.system"}
	node.Info.Zone = 10

	// Save node in the db
	err := app.db.Update(func(tx *bolt.Tx) error {
		return node.Save(tx)
	})
	tests.Assert(t, err == nil)

	// Delete unknown id
	req, err := http.NewRequest("DELETE", ts.URL+"/nodes/123", nil)
	tests.Assert(t, err == nil)
	r, err := http.DefaultClient.Do(req)
	tests.Assert(t, err == nil)
	tests.Assert(t, r.StatusCode == http.StatusNotFound)

	// Delete node without a cluster there.. that's probably a really
	// bad situation
	req, err = http.NewRequest("DELETE", ts.URL+"/nodes/"+node.Info.Id, nil)
	tests.Assert(t, err == nil)
	r, err = http.DefaultClient.Do(req)
	tests.Assert(t, err == nil)
	tests.Assert(t, r.StatusCode == http.StatusInternalServerError)

}
Example #27
0
func TestNodeInfo(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Patch dbfilename so that it is restored at the end of the tests
	defer tests.Patch(&dbfilename, tmpfile).Restore()

	// Create the app
	app := NewApp()
	defer app.Close()
	router := mux.NewRouter()
	app.SetRoutes(router)

	// Setup the server
	ts := httptest.NewServer(router)
	defer ts.Close()

	// Create a node to save in the db
	node := NewNodeEntry()
	node.Info.Id = "abc"
	node.Info.ClusterId = "123"
	node.Info.Hostnames.Manage = sort.StringSlice{"manage.system"}
	node.Info.Hostnames.Storage = sort.StringSlice{"storage.system"}
	node.Info.Zone = 10

	// Save node in the db
	err := app.db.Update(func(tx *bolt.Tx) error {
		return node.Save(tx)
	})
	tests.Assert(t, err == nil)

	// Get unknown node id
	r, err := http.Get(ts.URL + "/nodes/" + node.Info.Id)
	tests.Assert(t, err == nil)
	tests.Assert(t, r.StatusCode == http.StatusOK)
	tests.Assert(t, r.Header.Get("Content-Type") == "application/json; charset=UTF-8")

	var info NodeInfoResponse
	err = utils.GetJsonFromResponse(r, &info)
	tests.Assert(t, info.Id == node.Info.Id)
	tests.Assert(t, info.Hostnames.Manage[0] == node.Info.Hostnames.Manage[0])
	tests.Assert(t, len(info.Hostnames.Manage) == len(node.Info.Hostnames.Manage))
	tests.Assert(t, info.Hostnames.Storage[0] == node.Info.Hostnames.Storage[0])
	tests.Assert(t, len(info.Hostnames.Storage) == len(node.Info.Hostnames.Storage))
	tests.Assert(t, info.Zone == node.Info.Zone)

}
Example #28
0
func TestVolumeEntryCreateRunOutOfSpaceMaxBrickLimit(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Create the app
	app := NewTestApp(tmpfile)
	defer app.Close()

	// Lots of nodes with little drives
	err := setupSampleDbWithTopology(app,
		1,  // clusters
		20, // nodes_per_cluster
		40, // devices_per_node,

		// Must be larger than the brick min size
		BRICK_MIN_SIZE*2, // disksize
	)
	tests.Assert(t, err == nil)

	// Create a volume who will be broken down to
	// Shouldn't be able to break it down enough to allocate volume
	v := createSampleVolumeEntry(BRICK_MAX_NUM * 2 * int(BRICK_MIN_SIZE/GB))
	err = v.Create(app.db, app.executor, app.allocator)
	tests.Assert(t, err == ErrNoSpace)

	// Check database volume does not exist
	err = app.db.View(func(tx *bolt.Tx) error {
		_, err := NewVolumeEntryFromId(tx, v.Info.Id)
		return err
	})
	tests.Assert(t, err == ErrNotFound)

	// Check no bricks or volumes exist
	var bricks []string
	var volumes []string
	err = app.db.View(func(tx *bolt.Tx) error {
		bricks = EntryKeys(tx, BOLTDB_BUCKET_BRICK)

		volumes = EntryKeys(tx, BOLTDB_BUCKET_VOLUME)
		return nil
	})
	tests.Assert(t, len(bricks) == 0)
	tests.Assert(t, len(volumes) == 0)

}
Example #29
0
func TestNewDeviceEntryNewInfoResponseBadBrickIds(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Create the app
	app := NewTestApp(tmpfile)
	defer app.Close()

	// Create a device
	req := &DeviceAddRequest{}
	req.NodeId = "abc"
	req.Name = "/dev/" + utils.GenUUID()
	req.Weight = 123

	// Add bad brick ids
	d := NewDeviceEntryFromRequest(req)
	d.Info.Storage.Free = 10
	d.Info.Storage.Total = 100
	d.Info.Storage.Used = 1000
	d.BrickAdd("abc")
	d.BrickAdd("def")

	// Save element in database
	err := app.db.Update(func(tx *bolt.Tx) error {
		return d.Save(tx)
	})
	tests.Assert(t, err == nil)

	var info *DeviceInfoResponse
	err = app.db.View(func(tx *bolt.Tx) error {
		device, err := NewDeviceEntryFromId(tx, d.Info.Id)
		if err != nil {
			return err
		}

		info, err = device.NewInfoResponse(tx)
		if err != nil {
			return err
		}

		return nil

	})
	tests.Assert(t, err == ErrNotFound)
}
Example #30
0
func TestNewNodeEntryFromId(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Patch dbfilename so that it is restored at the end of the tests
	defer tests.Patch(&dbfilename, tmpfile).Restore()

	// Create the app
	app := NewApp()
	defer app.Close()

	// Create a node
	req := &NodeAddRequest{
		ClusterId: "123",
		Hostnames: HostAddresses{
			Manage:  []string{"manage"},
			Storage: []string{"storage"},
		},
		Zone: 99,
	}

	n := NewNodeEntryFromRequest(req)
	n.DeviceAdd("abc")
	n.DeviceAdd("def")

	// Save element in database
	err := app.db.Update(func(tx *bolt.Tx) error {
		return n.Save(tx)
	})
	tests.Assert(t, err == nil)

	var node *NodeEntry
	err = app.db.View(func(tx *bolt.Tx) error {
		var err error
		node, err = NewNodeEntryFromId(tx, n.Info.Id)
		if err != nil {
			return err
		}
		return nil

	})
	tests.Assert(t, err == nil)
	tests.Assert(t, reflect.DeepEqual(node, n))

}