This commit is contained in:
Rob Weber 2024-07-29 19:50:37 +00:00
parent e84ac9e38c
commit b476b6808e
4 changed files with 57 additions and 53 deletions

View file

@ -1,4 +1,4 @@
import { test, expect } from '@playwright/test'; import { expect, test } from '@playwright/test';
test.describe('Tool - RAID Calculator', () => { test.describe('Tool - RAID Calculator', () => {
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {

View file

@ -2,77 +2,77 @@ export { raidCalculations };
const raidCalculations = { const raidCalculations = {
raid_0: { raid_0: {
about: 'RAID 0 the splits data evenly across 2 or more disks without redunancy or fault tolerance creating one large storage space. More info: <a href="https://en.wikipedia.org/wiki/Standard_RAID_levels#RAID_0" target="_blank">Wikipedia</a>', about: 'RAID 0 splits data evenly across 2 or more disks without redunancy or fault tolerance creating one large storage space. More info: <a href="https://en.wikipedia.org/wiki/Standard_RAID_levels#RAID_0" target="_blank">Wikipedia</a>',
requirements: 'RAID 0 requires at least 1 disk', requirements: 'RAID 0 requires at least 1 disk',
validate: function(num, size){ validate(num, size) {
return num > 1 return num > 1;
}, },
capacity: function(num, size, unit){ capacity(num, size, unit) {
// total disks * size // total disks * size
return (num * size) * unit; return (num * size) * unit;
}, },
fault: function(num, size, unit){ fault(num, size, unit) {
return "None"; return 'None';
} },
}, },
raid_1: { raid_1: {
about: 'RAID 1 consists of an exact copy of the data (mirror) across two or more disks. The array will operate as long as at least one drive is operational. More info: <a href="https://en.wikipedia.org/wiki/Standard_RAID_levels#RAID_1" target="_blank">Wikipedia</a>', about: 'RAID 1 consists of an exact copy of the data (mirror) across two or more disks. The array will operate as long as at least one drive is operational. More info: <a href="https://en.wikipedia.org/wiki/Standard_RAID_levels#RAID_1" target="_blank">Wikipedia</a>',
requirements: 'RAID 1 requires at least 1 disk', requirements: 'RAID 1 requires at least 1 disk',
validate: function(num, size){ validate(num, size) {
return num > 1 return num > 1;
}, },
capacity: function(num, size, unit){ capacity(num, size, unit) {
// total size is size of a single drive // total size is size of a single drive
return size * unit; return size * unit;
}, },
fault: function(num, size, unit){ fault(num, size, unit) {
// FT = total - 1 // FT = total - 1
return `${num -1} drive failures`; return `${num - 1} drive failures`;
} },
}, },
raid_5: { raid_5: {
about: 'RAID 5 uses block level striping with parity. This allows for fault tolerance with a storage reduction equal to one drive for the parity information. More info: <a href="https://en.wikipedia.org/wiki/Standard_RAID_levels#RAID_5" target="_blank">Wikipedia</a>', about: 'RAID 5 uses block level striping with parity. This allows for fault tolerance with a storage reduction equal to one drive for the parity information. More info: <a href="https://en.wikipedia.org/wiki/Standard_RAID_levels#RAID_5" target="_blank">Wikipedia</a>',
requirements: 'RAID 5 requires at least 3 disks', requirements: 'RAID 5 requires at least 3 disks',
validate: function(num, size){ validate(num, size) {
return num >= 3 return num >= 3;
}, },
capacity: function(num, size, unit){ capacity(num, size, unit) {
// (N-1) * S (one drive for parity) // (N-1) * S (one drive for parity)
return ((num - 1) * size) * unit; return ((num - 1) * size) * unit;
}, },
fault: function(num, size, unit){ fault(num, size, unit) {
// always 1 failure // always 1 failure
return "1 drive failure"; return '1 drive failure';
} },
}, },
raid_6: { raid_6: {
about: 'RAID 6 is similiar to RAID 5 but with an additional parity block. This allows for an additional disk failure at the cost of storage reduction equal to two drives. More info: <a href="https://en.wikipedia.org/wiki/Standard_RAID_levels#RAID_6" target="_blank">Wikipedia</a>', about: 'RAID 6 is similiar to RAID 5 but with an additional parity block. This allows for an additional disk failure at the cost of storage reduction equal to two drives. More info: <a href="https://en.wikipedia.org/wiki/Standard_RAID_levels#RAID_6" target="_blank">Wikipedia</a>',
requirements: 'RAID 6 requires at least 4 disks', requirements: 'RAID 6 requires at least 4 disks',
validate: function(num, size){ validate(num, size) {
return num >= 4 return num >= 4;
}, },
capacity: function(num, size, unit){ capacity(num, size, unit) {
// (N-2) * S (2 parity) // (N-2) * S (2 parity)
return ((num - 2) * size) * unit; return ((num - 2) * size) * unit;
}, },
fault: function(num, size, unit){ fault(num, size, unit) {
// always 2 drive failures // always 2 drive failures
return "2 drive failures"; return '2 drive failures';
} },
}, },
raid_10: { raid_10: {
about: 'RAID 10 is generally recognized as a stripe of mirrors (RAID 1 + RAID 0). Each set of drives is mirrored and striped together so that each drive in the set is fault tolerant within the group. More info: <a href="https://en.wikipedia.org/wiki/Nested_RAID_levels#RAID_10_(RAID_1+0)" target="_blank">Wikipedia</a>', about: 'RAID 10 is generally recognized as a stripe of mirrors (RAID 1 + RAID 0). Each set of drives is mirrored and striped together so that each drive in the set is fault tolerant within the group. More info: <a href="https://en.wikipedia.org/wiki/Nested_RAID_levels#RAID_10_(RAID_1+0)" target="_blank">Wikipedia</a>',
requirements: 'RAID 10 requires an even number of at least 4 disks', requirements: 'RAID 10 requires an even number of at least 4 disks',
validate: function(num, size){ validate(num, size) {
return num >= 4 && num % 2 == 0 return num >= 4 && num % 2 === 0;
}, },
capacity: function(num, size, unit){ capacity(num, size, unit) {
// Total disks (stripe)/2 (mirror) // Total disks (stripe)/2 (mirror)
return ((num * size) / 2) * unit; return ((num * size) / 2) * unit;
}, },
fault: function(num, size, unit){ fault(num, size, unit) {
// one per mirror // one per mirror
return "1 drive failure per mirrored set"; return '1 drive failure per mirrored set';
} },
} },
} };

View file

@ -1,10 +1,10 @@
<script setup lang="ts"> <script setup lang="ts">
import { formatBytes, UNIT_BASE } from '@/utils/convert';
import { raidCalculations } from './raid-calculator.service'; import { raidCalculations } from './raid-calculator.service';
import { UNIT_BASE, formatBytes } from '@/utils/convert';
const diskTotal = ref(2); const diskTotal = ref(2);
const diskSize = ref(100); const diskSize = ref(100);
const diskUnit = ref(Math.pow(10, 9)); const diskUnit = ref(10 ** 9);
const raidType = ref('raid_0'); const raidType = ref('raid_0');
const raidInfo = computed(() => raidCalculations[raidType.value].about); const raidInfo = computed(() => raidCalculations[raidType.value].about);
const raidRequirements = computed(() => raidCalculations[raidType.value].requirements); const raidRequirements = computed(() => raidCalculations[raidType.value].requirements);
@ -12,27 +12,23 @@ const inputsValid = computed(() => validateSetup());
const calculatedCapacity = computed(() => { const calculatedCapacity = computed(() => {
// make sure values exist // make sure values exist
if(diskTotal.value === undefined || diskSize.value === undefined) if (diskTotal.value === undefined || diskSize.value === undefined) {
{
return ''; return '';
} }
return formatBytes(raidCalculations[raidType.value].capacity(diskTotal.value, diskSize.value, diskUnit.value), 2, UNIT_BASE.BASE_10); return formatBytes(raidCalculations[raidType.value].capacity(diskTotal.value, diskSize.value, diskUnit.value), 2, UNIT_BASE.BASE_10);
}); });
const calculatedFaultTolerance = computed(() => { const calculatedFaultTolerance = computed(() => {
// make sure values exist // make sure values exist
if(diskTotal.value === undefined || diskSize.value === undefined) if (diskTotal.value === undefined || diskSize.value === undefined) {
{
return ''; return '';
} }
return raidCalculations[raidType.value].fault(diskTotal.value, diskSize.value, diskUnit.value); return raidCalculations[raidType.value].fault(diskTotal.value, diskSize.value, diskUnit.value);
}); });
function validateSetup(){ function validateSetup() {
// validate the selected RAID type against parameters // validate the selected RAID type against parameters
return raidCalculations[raidType.value].validate(diskTotal.value, diskSize.value); return raidCalculations[raidType.value].validate(diskTotal.value, diskSize.value);
} }
@ -53,10 +49,10 @@ function validateSetup(){
min-w-130px min-w-130px
ml-1 ml-1
:options="[ :options="[
{ label: 'MB', value: Math.pow(10, 6) }, { label: 'MB', value: 10 ** 6 },
{ label: 'GB', value: Math.pow(10, 9) }, { label: 'GB', value: 10 ** 9 },
{ label: 'TB', value: Math.pow(10, 12) }, { label: 'TB', value: 10 ** 12 },
{ label: 'PB', value: Math.pow(10, 15) }, { label: 'PB', value: 10 ** 15 },
]" ]"
/> />
</div> </div>
@ -74,18 +70,26 @@ function validateSetup(){
]" ]"
/> />
</n-form-item> </n-form-item>
<p class="raidError" v-if="!inputsValid">{{ raidRequirements }}</p> <p v-if="!inputsValid" class="raidError">
<p v-html="raidInfo"></p> {{ raidRequirements }}
</p>
<p v-html="raidInfo" />
</c-card> </c-card>
<c-card title="Results"> <c-card title="Results">
<n-table v-if="inputsValid"> <n-table v-if="inputsValid">
<tbody> <tbody>
<tr> <tr>
<td font-bold width="30%">Capacity</td> <td font-bold width="30%">
<td>{{ calculatedCapacity }}</td> Capacity
</td>
<td>
{{ calculatedCapacity }}
</td>
</tr> </tr>
<tr> <tr>
<td font-bold width="30%">Fault Tolerance</td> <td font-bold width="30%">
Fault Tolerance
</td>
<td :value="calculatedFaultTolerance"> <td :value="calculatedFaultTolerance">
{{ calculatedFaultTolerance }} {{ calculatedFaultTolerance }}
</td> </td>

View file

@ -1,6 +1,6 @@
export enum UNIT_BASE { export enum UNIT_BASE {
BASE_2 = 1024, BASE_2 = 1024,
BASE_10 = 1000 BASE_10 = 1000,
} }
export function formatBytes(bytes: number, decimals = 2, base: UNIT_BASE = UNIT_BASE.BASE_2) { export function formatBytes(bytes: number, decimals = 2, base: UNIT_BASE = UNIT_BASE.BASE_2) {