adding device protocl and type to the. Adding class for parsing `smartctl --scan` json output, for device detection. added an example/test file for `smartctl -x -j` added a placeholder settings panel. moved dashboard & details compoonent out of "Admin" directory.

pull/28/head
Jason Kulatunga 4 years ago
parent 98415e625d
commit 5101a37964

@ -23,6 +23,18 @@ type BaseCollector struct {
func (c *BaseCollector) DetectStorageDevices() ([]models.Device, error) {
//availableDisksJson, err := c.ExecCmd("smartctl", []string{"-j", "--scan"}, "", os.Environ())
//if err != nil {
// c.logger.Errorf("Error getting block storage info: %v", err)
// return nil, err
//}
//
//var smartctlScan models.Scan
//err = json.Unmarshal([]byte(availableDisksJson), &smartctlScan)
//if err != nil {
// return nil, err
//}
block, err := ghw.Block()
if err != nil {
c.logger.Errorf("Error getting block storage info: %v", err)
@ -83,7 +95,6 @@ func (c *BaseCollector) DetectStorageDevices() ([]models.Device, error) {
approvedDisks = append(approvedDisks, diskModel)
}
return approvedDisks, nil
}

@ -14,6 +14,8 @@ type Device struct {
Capacity int64 `json:"capacity"`
FormFactor string `json:"form_factor"`
SmartSupport bool `json:"smart_support"`
DeviceProtocol string `json:"device_protocol"` //protocol determines which smart attribute types are available (ATA, NVMe, SCSI)
DeviceType string `json:"device_type"` //device type is used for querying with -d/t flag, should only be used by collector.
}
type DeviceWrapper struct {

@ -0,0 +1,19 @@
package models
type Scan struct {
JSONFormatVersion []int `json:"json_format_version"`
Smartctl struct {
Version []int `json:"version"`
SvnRevision string `json:"svn_revision"`
PlatformInfo string `json:"platform_info"`
BuildInfo string `json:"build_info"`
Argv []string `json:"argv"`
ExitStatus int `json:"exit_status"`
} `json:"smartctl"`
Devices []struct {
Name string `json:"name"`
InfoName string `json:"info_name"`
Type string `json:"type"`
Protocol string `json:"protocol"`
} `json:"devices"`
}

@ -34,7 +34,6 @@ disks:
# - /dev/sdb
notify:
level: 'warn' # 'warn' or 'error'
urls:
- "discord://token@channel"
- "telegram://token@telegram?channels=channel-1[,channel-2,...]"
@ -52,6 +51,21 @@ notify:
- "script:///file/path/on/disk"
- "https://www.example.com/path"
limits:
ata:
critical:
error: 10
standard:
error: 20
warn: 10
scsi:
critical: true
standard: true
nvme:
critical: true
standard: true
collect:
metric:
enable: true

@ -34,8 +34,8 @@ type Device struct {
Capacity int64 `json:"capacity"`
FormFactor string `json:"form_factor"`
SmartSupport bool `json:"smart_support"`
DeviceProtocol string `json:"device_protocol"`
DeviceType string `json:"device_type"` //device type is used for querying with -d/t flag
DeviceProtocol string `json:"device_protocol"` //protocol determines which smart attribute types are available (ATA, NVMe, SCSI)
DeviceType string `json:"device_type"` //device type is used for querying with -d/t flag, should only be used by collector.
SmartResults []Smart `gorm:"foreignkey:DeviceWWN" json:"smart_results"`
}

File diff suppressed because it is too large Load Diff

@ -26,8 +26,8 @@ export const appRoutes: Route[] = [
children : [
// Example
{path: 'dashboard', loadChildren: () => import('app/modules/admin/dashboard/dashboard.module').then(m => m.DashboardModule)},
{path: 'device/:wwn', loadChildren: () => import('app/modules/admin/detail/detail.module').then(m => m.DetailModule)}
{path: 'dashboard', loadChildren: () => import('app/modules/dashboard/dashboard.module').then(m => m.DashboardModule)},
{path: 'device/:wwn', loadChildren: () => import('app/modules/detail/detail.module').then(m => m.DetailModule)}
// 404 & Catch all
// {path: '404-not-found', pathMatch: 'full', loadChildren: () => import('app/modules/admin/pages/errors/error-404/error-404.module').then(m => m.Error404Module)},

@ -0,0 +1,82 @@
<h2 mat-dialog-title>Scrutiny Settings</h2>
<mat-dialog-content class="mat-typography">
<form class="flex flex-col p-8 pb-0 overflow-hidden">
<div class="flex flex-col gt-xs:flex-row">
<mat-form-field class="flex-auto gt-xs:pr-3">
<mat-label>Sort By</mat-label>
<mat-select>
<mat-option value="option1">Status</mat-option>
<mat-option value="option2" disabled>Name</mat-option>
<mat-option value="option3" disabled>Label</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="flex">
<mat-tab-group mat-align-tabs="start">
<mat-tab label="Ata">
<div class="flex flex-col mt-5 gt-md:flex-row">
<mat-form-field class="flex-auto gt-md:pr-3">
<mat-label>Critical Error Threshold</mat-label>
<input matInput>
</mat-form-field>
<mat-form-field class="flex-auto gt-md:pl-3">
<mat-label>Critical Warning Threshold</mat-label>
<input matInput>
</mat-form-field>
</div>
<div class="flex flex-col gt-md:flex-row">
<mat-form-field class="flex-auto gt-md:pr-3">
<mat-label>Error Threshold</mat-label>
<input matInput>
</mat-form-field>
<mat-form-field class="flex-auto gt-md:pl-3">
<mat-label>Warning Threshold</mat-label>
<input matInput>
</mat-form-field>
</div>
</mat-tab>
<mat-tab label="NVMe">
<div class="flex flex-col mt-5 gt-md:flex-row">
<mat-form-field class="flex-auto gt-md:pr-3">
<mat-label>Critical Error Threshold</mat-label>
<input matInput>
</mat-form-field>
<mat-form-field class="flex-auto gt-md:pl-3">
<mat-label>Critical Warning Threshold</mat-label>
<input matInput>
</mat-form-field>
</div>
</mat-tab>
<mat-tab label="SCSI">
<div class="flex flex-col mt-5 gt-md:flex-row">
<mat-form-field class="flex-auto gt-md:pr-3">
<mat-label>Critical Error Threshold</mat-label>
<input matInput>
</mat-form-field>
<mat-form-field class="flex-auto gt-md:pl-3">
<mat-label>Critical Warning Threshold</mat-label>
<input matInput>
</mat-form-field>
</div>
</mat-tab>
</mat-tab-group>
</div>
</form>
</mat-dialog-content>
<mat-dialog-actions align="end">
<button mat-button mat-dialog-close>Cancel</button>
<button mat-button [mat-dialog-close]="true" cdkFocusInitial>Save</button>
</mat-dialog-actions>
<!-- Copyright 2020 Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license -->

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DashboardSettingsComponent } from './dashboard-settings.component';
describe('DashboardSettingsComponent', () => {
let component: DashboardSettingsComponent;
let fixture: ComponentFixture<DashboardSettingsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ DashboardSettingsComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(DashboardSettingsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

@ -0,0 +1,17 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-dashboard-settings',
templateUrl: './dashboard-settings.component.html',
styleUrls: ['./dashboard-settings.component.scss']
})
export class DashboardSettingsComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
formatLabel(value: number) {
return value;
}
}

@ -0,0 +1,44 @@
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { Overlay } from '@angular/cdk/overlay';
import { MAT_AUTOCOMPLETE_SCROLL_STRATEGY, MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatButtonModule } from '@angular/material/button';
import { MatSelectModule } from '@angular/material/select';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { SharedModule } from 'app/shared/shared.module';
import {DashboardSettingsComponent} from 'app/layout/common/dashboard-settings/dashboard-settings.component'
import { MatDialogModule } from "@angular/material/dialog";
import { MatButtonToggleModule} from "@angular/material/button-toggle";
import {MatTabsModule} from "@angular/material/tabs";
import {MatSliderModule} from "@angular/material/slider";
import {MatSlideToggleModule} from "@angular/material/slide-toggle";
@NgModule({
declarations: [
DashboardSettingsComponent
],
imports : [
RouterModule.forChild([]),
MatAutocompleteModule,
MatDialogModule,
MatButtonModule,
MatSelectModule,
MatFormFieldModule,
MatIconModule,
MatInputModule,
MatButtonToggleModule,
MatTabsModule,
MatSliderModule,
MatSlideToggleModule,
SharedModule
],
exports : [
DashboardSettingsComponent
],
providers : []
})
export class DashboardSettingsModule
{
}

@ -10,15 +10,13 @@
</div>
<!-- Action buttons -->
<div class="flex items-center">
<button class="xs:hidden"
matTooltip="not yet implemented"
mat-stroked-button>
<button matTooltip="not yet implemented" class="xs:hidden" mat-stroked-button>
<mat-icon class="icon-size-20"
[svgIcon]="'save'"></mat-icon>
<span class="ml-2">Export</span>
</button>
<button class="ml-2 xs:hidden"
matTooltip="not yet implemented"
(click)="openDialog()"
mat-stroked-button>
<mat-icon class="icon-size-20 rotate-90 mirror"
[svgIcon]="'tune'"></mat-icon>
@ -38,8 +36,7 @@
[svgIcon]="'save'"></mat-icon>
<span class="ml-2">Export</span>
</button>
<button mat-menu-item
matTooltip="not yet implemented">
<button mat-menu-item (click)="openDialog()">
<mat-icon class="icon-size-20 rotate-90 mirror"
[svgIcon]="'tune'"></mat-icon>
<span class="ml-2">Settings</span>

@ -4,8 +4,10 @@ import { MatTableDataSource } from '@angular/material/table';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { ApexOptions } from 'ng-apexcharts';
import { DashboardService } from 'app/modules/admin/dashboard/dashboard.service';
import { DashboardService } from 'app/modules/dashboard/dashboard.service';
import * as moment from "moment";
import {MatDialog} from '@angular/material/dialog';
import { DashboardSettingsComponent } from 'app/layout/common/dashboard-settings/dashboard-settings.component';
@Component({
selector : 'example',
@ -28,7 +30,8 @@ export class DashboardComponent implements OnInit, AfterViewInit, OnDestroy
* @param {SmartService} _smartService
*/
constructor(
private _smartService: DashboardService
private _smartService: DashboardService,
public dialog: MatDialog
)
{
// Set the private defaults
@ -153,6 +156,14 @@ export class DashboardComponent implements OnInit, AfterViewInit, OnDestroy
// @ Public methods
// -----------------------------------------------------------------------------------------------------
openDialog() {
const dialogRef = this.dialog.open(DashboardSettingsComponent);
dialogRef.afterClosed().subscribe(result => {
console.log(`Dialog result: ${result}`);
});
}
/**
* Track by function for ngFor loops
*

@ -1,8 +1,8 @@
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { SharedModule } from 'app/shared/shared.module';
import { DashboardComponent } from 'app/modules/admin/dashboard/dashboard.component';
import { dashboardRoutes } from 'app/modules/admin/dashboard/dashboard.routing';
import { DashboardComponent } from 'app/modules/dashboard/dashboard.component';
import { dashboardRoutes } from 'app/modules/dashboard/dashboard.routing';
import { MatButtonModule } from '@angular/material/button';
import { MatDividerModule } from '@angular/material/divider';
import { MatIconModule } from '@angular/material/icon';
@ -12,6 +12,7 @@ import { MatSortModule } from '@angular/material/sort';
import { MatTableModule } from '@angular/material/table';
import { NgApexchartsModule } from 'ng-apexcharts';
import { MatTooltipModule } from '@angular/material/tooltip'
import { DashboardSettingsModule } from "app/layout/common/dashboard-settings/dashboard-settings.module";
@NgModule({
declarations: [
@ -28,7 +29,8 @@ import { MatTooltipModule } from '@angular/material/tooltip'
MatSortModule,
MatTableModule,
NgApexchartsModule,
SharedModule
SharedModule,
DashboardSettingsModule
]
})
export class DashboardModule

@ -1,7 +1,7 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { DashboardService } from 'app/modules/admin/dashboard/dashboard.service';
import { DashboardService } from 'app/modules/dashboard/dashboard.service';
@Injectable({
providedIn: 'root'

@ -1,5 +1,5 @@
import { Route } from '@angular/router';
import { DashboardComponent } from 'app/modules/admin/dashboard/dashboard.component';
import { DashboardComponent } from 'app/modules/dashboard/dashboard.component';
import {DashboardResolver} from "./dashboard.resolvers";
export const dashboardRoutes: Route[] = [

@ -3,9 +3,9 @@ import {ApexOptions} from "ng-apexcharts";
import {MatTableDataSource} from "@angular/material/table";
import {MatSort} from "@angular/material/sort";
import {Subject} from "rxjs";
import {DetailService} from "../detail/detail.service";
import {DetailService} from "./detail.service";
import {takeUntil} from "rxjs/operators";
import {fadeOut} from "../../../../@treo/animations/fade";
import {fadeOut} from "../../../@treo/animations/fade";
@Component({
selector: 'detail',

@ -1,8 +1,8 @@
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { SharedModule } from 'app/shared/shared.module';
import { DetailComponent } from 'app/modules/admin/detail/detail.component';
import { detailRoutes } from 'app/modules/admin/detail/detail.routing';
import { DetailComponent } from 'app/modules/detail/detail.component';
import { detailRoutes } from 'app/modules/detail/detail.routing';
import { MatButtonModule } from '@angular/material/button';
import { MatDividerModule } from '@angular/material/divider';
import { MatIconModule } from '@angular/material/icon';

@ -1,7 +1,7 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { DetailService } from 'app/modules/admin/detail/detail.service';
import { DetailService } from 'app/modules/detail/detail.service';
@Injectable({
providedIn: 'root'

@ -1,5 +1,5 @@
import { Route } from '@angular/router';
import { DetailComponent } from 'app/modules/admin/detail/detail.component';
import { DetailComponent } from 'app/modules/detail/detail.component';
import {DetailResolver} from "./detail.resolvers";
export const detailRoutes: Route[] = [
Loading…
Cancel
Save