public void canExportADisk() { clearAll(); FreeNASWithCaching foo = new FreeNASWithCaching(nashostname, nasusername, naspassword); string testPrefix = Guid.NewGuid().ToString(); // Make a test datastore to export using (SSHExecutor exec = new SSHExecutor(nashostname, nasusername, naspassword)) { exec.startExecutable("zfs", "create -V 10MB test/" + testPrefix); } // Add an extent and watch the time taken var newExtent = foo.addISCSIExtent(new iscsiExtent() { iscsi_target_extent_name = testPrefix, iscsi_target_extent_type = "Disk", iscsi_target_extent_path = "/dev/zvol/test/" + testPrefix }); iscsiTarget newTarget = foo.addISCSITarget(new iscsiTarget() { targetName = testPrefix }); foo.addISCSITargetToExtent(newTarget.id, newExtent); foo.createTargetGroup(foo.getPortals()[0], newTarget); foo.waitUntilISCSIConfigFlushed(); }
public void canCloneSnapshots() { string testPrefix = Guid.NewGuid().ToString(); FreeNASWithCaching foo = new FreeNASWithCaching(nashostname, nasusername, naspassword); // Make a test datastore to export using (SSHExecutor exec = new SSHExecutor(nashostname, nasusername, naspassword)) { exec.startExecutable("zfs", "create -V 10MB test/" + testPrefix); } snapshot snap = foo.createSnapshot("test/" + testPrefix, "snapshot-of-" + testPrefix); Assert.AreEqual(1, foo.getSnapshots().Count(x => x.id == snap.id)); foo.cloneSnapshot(snap, "test/clone-of-" + testPrefix); }
public void canInvalidateThings() { // Here, we use a second FreeNAS instance to modify data on the server. We then invalidate the first, and ensure that // the differences are seen. string testPrefix = Guid.NewGuid().ToString(); FreeNASWithCaching uut = new FreeNASWithCaching(nashostname, nasusername, naspassword); FreeNAS directNAS = new FreeNAS(nashostname, nasusername, naspassword); // Make a test file to export using (SSHExecutor exec = new SSHExecutor(nashostname, nasusername, naspassword)) { exec.startExecutable("touch", nastempspace + "/testfile"); } // Add a targets, extents, and target-to-extents iscsiTarget tgt = directNAS.addISCSITarget(new iscsiTarget() { targetName = testPrefix, targetAlias = "idk lol" }); directNAS.createTargetGroup(directNAS.getPortals()[0], tgt); iscsiExtent ext = directNAS.addISCSIExtent(new iscsiExtent() { iscsi_target_extent_name = testPrefix, iscsi_target_extent_type = "File", iscsi_target_extent_path = nastempspace + "/testfile" }); directNAS.addISCSITargetToExtent(tgt.id, ext); directNAS.waitUntilISCSIConfigFlushed(); // The uut should now be out-of-date Assert.AreNotEqual(uut.getExtents().Count, directNAS.getExtents().Count); Assert.AreNotEqual(uut.getISCSITargets().Count, directNAS.getISCSITargets().Count); Assert.AreNotEqual(uut.getTargetToExtents().Count, directNAS.getTargetToExtents().Count); // Invalidate the uut and check that it is then up-to-date. uut.invalidateExtents(); Assert.AreEqual(uut.getExtents().Count, directNAS.getExtents().Count); uut.invalidateTargets(); Assert.AreEqual(uut.getISCSITargets().Count, directNAS.getISCSITargets().Count); uut.invalidateTargetToExtents(); Assert.AreEqual(uut.getTargetToExtents().Count, directNAS.getTargetToExtents().Count); }
public void extentDeletionImpliesTTEDeletion() { string testPrefix = Guid.NewGuid().ToString(); FreeNASWithCaching foo = new FreeNASWithCaching(nashostname, nasusername, naspassword); int origExtentCount = foo.getExtents().Count; int origTargetCount = foo.getISCSITargets().Count; int origTTECount = foo.getTargetToExtents().Count; // Make a test file to export string filePath = nastempspace + "/" + testPrefix; using (SSHExecutor exec = new SSHExecutor(nashostname, nasusername, naspassword)) { exec.startExecutable("touch", filePath); } iscsiTarget tgt1 = foo.addISCSITarget(new iscsiTarget() { targetName = testPrefix }); iscsiExtent ext1 = foo.addISCSIExtent(new iscsiExtent() { iscsi_target_extent_name = testPrefix, iscsi_target_extent_type = "File", iscsi_target_extent_path = filePath }); iscsiTargetToExtentMapping tte1 = foo.addISCSITargetToExtent(tgt1.id, ext1); foo.waitUntilISCSIConfigFlushed(); foo.deleteISCSIExtent(ext1); Assert.AreEqual(origTTECount, foo.getTargetToExtents().Count()); Assert.AreEqual(origTargetCount + 1, foo.getISCSITargets().Count()); Assert.AreEqual(origExtentCount, foo.getExtents().Count()); }
public void canExportAFile() { string testPrefix = Guid.NewGuid().ToString(); FreeNASWithCaching foo = new FreeNASWithCaching(nashostname, nasusername, naspassword); // Make a test file to export using (SSHExecutor exec = new SSHExecutor(nashostname, nasusername, naspassword)) { exec.startExecutable("touch", nastempspace + "/testfile"); } // Add some targets, extents, target-to-extents, and watch the time taken. iscsiTarget tgt = foo.addISCSITarget(new iscsiTarget() { targetName = testPrefix, targetAlias = testPrefix }); foo.createTargetGroup(foo.getPortals()[0], tgt); iscsiExtent ext = foo.addISCSIExtent(new iscsiExtent() { iscsi_target_extent_name = testPrefix, iscsi_target_extent_type = "File", iscsi_target_extent_path = nastempspace + "/testfile" }); foo.addISCSITargetToExtent(tgt.id, ext); foo.waitUntilISCSIConfigFlushed(); // Check that ctld has exported the file as we asked using (SSHExecutor exec = new SSHExecutor(nashostname, nasusername, naspassword)) { executionResult res = exec.startExecutable("ctladm", "portlist"); Assert.AreEqual(0, res.resultCode); string[] lines = res.stdout.Split('\n'); Assert.AreEqual(1, lines.Count(x => x.Contains(testPrefix + ","))); } }
public void willAllowManyExportsAtOnce() { clearAll(); FreeNASWithCaching foo = new FreeNASWithCaching(nashostname, nasusername, naspassword); // // Here we export many files (targets/extents/ttes) from ctld. Eventually, the kernel will hit CTL_MAX_PORTS and things // will fail. We ensure that this number is high enough that we are unlikely to have any problems. // // Make some test files to export string testPrefix = Guid.NewGuid().ToString(); int maxfiles = 10000; int maxFilesPossible = 0; List <string> uncheckedExports = new List <string>(10); using (SSHExecutor exec = new SSHExecutor(nashostname, nasusername, naspassword)) { exec.startExecutable("/bin/sh", string.Format("-c " + "'for a in `seq 0 {0}`; do touch {1}/testfile_${{a}}; done'", maxfiles, nastempspace)); // Add some targets, extents, target-to-extents, and see how many we add before they stop working. // This is likely to be 256 for a 'factory' image, or 2048 for an XDL-customised image. Note, though, // that if you're using a small root partition on the FreeNAS box (which you should be, imo, because // a large amount of space encourages issues like this one to go unnoticed until they subtly degrade // performance later - and wear out the media, if root is on sdcard, which it is on store.xd.lan), // you may run out of space if collectd is not stopped. You can confirm this by observing that // collectd's dir in /var/db/collectd/rrd is huge. int preExisting = foo.getTargetToExtents().Count; for (int i = preExisting; i < maxfiles; i++) { iscsiTarget tgt = foo.addISCSITarget(new iscsiTarget() { targetName = testPrefix + "-" + i }); foo.createTargetGroup(foo.getPortals()[0], tgt); iscsiExtent ext = foo.addISCSIExtent(new iscsiExtent() { iscsi_target_extent_name = testPrefix + "_" + i, iscsi_target_extent_type = "File", iscsi_target_extent_path = nastempspace + "/testfile_" + i }); foo.addISCSITargetToExtent(tgt.id, ext); uncheckedExports.Add(tgt.targetName); if (i % 100 == 0) { // Every hundred, we reload and see if each has been exported correctly. Stopwatch watch = new Stopwatch(); watch.Start(); bool limitReached = false; try { foo.waitUntilISCSIConfigFlushed(); } catch (nasServerFullException) { // ok cool, we've reached our limit. limitReached = true; } //Thread.Sleep(1000 + (i * 10)); watch.Stop(); Debug.WriteLine("Flush after adding " + i + " exports: took " + watch.ElapsedMilliseconds + " ms"); executionResult res = exec.startExecutable("ctladm", "portlist -f iscsi"); Assert.AreEqual(0, res.resultCode); // Each of our unchecked testfiles should appear exactly once in this list. // If not, we know we've reached the limit of what the kernel can support. string[] lines = res.stdout.Split('\n'); for (int uncheckedIndex = 0; uncheckedIndex < uncheckedExports.Count; uncheckedIndex++) { var exportToCheck = uncheckedExports[uncheckedIndex]; if (lines.Count(x => x.Contains(exportToCheck + ",")) != 1) { // Oh, we've failed to export something! maxFilesPossible = i - uncheckedIndex; maxFilesPossible -= 2; i = maxfiles; break; } } if (limitReached) { maxFilesPossible = i; break; } uncheckedExports.Clear(); } } } // Our XDL build has CTL_MAX_PORTS set to 2048, so this should be very high. Assert.IsTrue(maxFilesPossible >= 2048, "maxFilesPossible is " + maxFilesPossible + " which is less than 2048"); }
public TimeSpan canExportNewFilesQuickly(string testPrefix, int newExportsCount) { // FIXME: use testprefix for filenames Stopwatch timer = new Stopwatch(); timer.Start(); FreeNASWithCaching foo = new FreeNASWithCaching(nashostname, nasusername, naspassword); timer.Stop(); Debug.WriteLine("Instantiation took " + timer.ElapsedMilliseconds + " ms"); // Make some test files to export using (SSHExecutor exec = new SSHExecutor(nashostname, nasusername, naspassword)) { for (int i = 0; i < newExportsCount; i++) { exec.startExecutable("touch", nastempspace + "/testfile_" + i); } } // Add some targets, extents, target-to-extents, and watch the time taken. timer.Restart(); int flushesBefore = foo.flushCount; for (int i = 0; i < newExportsCount; i++) { iscsiTarget tgt = foo.addISCSITarget(new iscsiTarget() { targetName = testPrefix + "-" + i }); foo.createTargetGroup(foo.getPortals()[0], tgt); iscsiExtent ext = foo.addISCSIExtent(new iscsiExtent() { iscsi_target_extent_name = testPrefix + "_" + i, iscsi_target_extent_type = "File", iscsi_target_extent_path = nastempspace + "/testfile_" + i }); foo.addISCSITargetToExtent(tgt.id, ext); } timer.Stop(); int flushesAfter = foo.flushCount; Debug.WriteLine("Adding " + newExportsCount + " target, extents, and target-to-extent records took " + timer.ElapsedMilliseconds + " ms and required " + (flushesAfter - flushesBefore) + " flushes"); Assert.IsTrue(timer.Elapsed < TimeSpan.FromSeconds(15)); timer.Restart(); foo.waitUntilISCSIConfigFlushed(); timer.Stop(); // Check that ctld has exported the files as we asked using (SSHExecutor exec = new SSHExecutor(nashostname, nasusername, naspassword)) { executionResult res = exec.startExecutable("ctladm", "portlist"); Assert.AreEqual(0, res.resultCode); // Each of our testfiles should appear exactly once in this list. string[] lines = res.stdout.Split('\n'); for (int i = 0; i < newExportsCount; i++) { try { Assert.AreEqual(1, lines.Count(x => x.Contains(testPrefix + "-" + i + ","))); } catch (AssertFailedException) { Debug.Write(res.stdout); Debug.Write(res.stderr); throw; } } } return(timer.Elapsed); }
public void canAddExtentsAndTargetsQuickly() { Stopwatch timer = new Stopwatch(); timer.Start(); FreeNASWithCaching foo = new FreeNASWithCaching(nashostname, nasusername, naspassword); timer.Stop(); Debug.WriteLine("Instantiation took " + timer.ElapsedMilliseconds + " ms"); string testPrefix = Guid.NewGuid().ToString(); // Make some test files to export int extentcount = 50; using (SSHExecutor exec = new SSHExecutor(nashostname, nasusername, naspassword)) { for (int i = 0; i < extentcount; i++) { exec.startExecutable("touch", nastempspace + "testfile_" + i); } } // Add some extents and watch the time taken timer.Restart(); int flushesBefore = foo.flushCount; iscsiExtent[] extentsAdded = new iscsiExtent[extentcount]; for (int i = 0; i < extentcount; i++) { extentsAdded[i] = foo.addISCSIExtent(new iscsiExtent() { iscsi_target_extent_name = testPrefix + "_" + i, iscsi_target_extent_type = "File", iscsi_target_extent_path = nastempspace + "/testfile_" + i }); iscsiTarget newTarget = foo.addISCSITarget(new iscsiTarget() { targetName = testPrefix + "-" + i }); foo.addISCSITargetToExtent(newTarget.id, extentsAdded[i]); foo.createTargetGroup(foo.getPortals()[0], newTarget); } timer.Stop(); int flushesAfter = foo.flushCount; Debug.WriteLine("Adding " + extentcount + " extents/targets/TTE took " + timer.ElapsedMilliseconds + " ms and required " + (flushesAfter - flushesBefore) + " flushes"); Assert.IsTrue(timer.Elapsed < TimeSpan.FromSeconds(10)); // Each should be unique by these properties foreach (iscsiExtent ext in extentsAdded) { Assert.AreEqual(1, extentsAdded.Count(x => x.id == ext.id)); Assert.AreEqual(1, extentsAdded.Count(x => x.iscsi_target_extent_path == ext.iscsi_target_extent_path)); Assert.AreEqual(1, extentsAdded.Count(x => x.iscsi_target_extent_name == ext.iscsi_target_extent_name)); } timer.Restart(); foo.waitUntilISCSIConfigFlushed(); timer.Stop(); Debug.WriteLine("Reloading config took " + timer.ElapsedMilliseconds + " ms"); Assert.IsTrue(timer.Elapsed < TimeSpan.FromSeconds(7)); }