member_webapp/@overflow/discovery/component/discovery-infra-tree.component.ts
crusader 09f98c885c ing
2018-06-21 20:17:07 +09:00

407 lines
11 KiB
TypeScript

import {
Component,
Input,
OnChanges,
SimpleChanges,
} from '@angular/core';
import { Host, Service } from '@overflow/commons-typescript/model/discovery';
import { TreeNode, Message } from 'primeng/primeng';
import { ProbeHost } from '@overflow/commons-typescript/model/probe';
import { Anim } from './animation';
import { TargetService } from '@overflow/target/service/target.service';
import { InfraService, InfraHost, Infra, MetaInfraTypeEnum, toMetaInfraType, InfraZone, Target, Page, PageParams } from '@overflow/commons-typescript';
import { InfraService as InfraManageService } from '../../infra/service/infra.service';
import { Observable, of } from 'rxjs';
import { catchError, map, tap, take } from 'rxjs/operators';
@Component({
selector: 'of-discovery-infra-tree',
templateUrl: './discovery-infra-tree.component.html',
animations: Anim,
providers: [
TargetService,
InfraManageService
]
})
export class DiscoveryInfraTreeComponent implements OnChanges {
@Input() probeHost: ProbeHost;
@Input() filterWord: string;
@Input() filterServices: Map<string, boolean>;
targets: Target[];
infraZones: InfraZone[];
infraHosts: InfraHost[];
infraServices: InfraService[];
zoneNode: TreeNode[];
hostNode: TreeNode[];
selectedItems: TreeNode[] = [];
msgs: Message[];
savedInfras: Infra[];
discoveredHosts: Host[] = [];
discoveredServices: Service[] = [];
infraSaved: boolean;
targetSaved: boolean;
pending$: Observable<boolean>;
error$: Observable<any>;
constructor(
private infraManageService: InfraManageService,
private targetService: TargetService
) {
}
ngOnChanges(changes: SimpleChanges) {
if (changes['probeHost']) {
this.getTargets();
}
}
getInfras() {
this.infraManageService.readAllByProbeID(this.probeHost.probe.id)
.pipe(
tap(() => {
this.pending$ = of(true);
}),
map((infras: Infra[]) => {
this.generateTree(infras);
}),
catchError(error => {
this.error$ = of(error);
return of();
}),
tap(() => {
this.pending$ = of(false);
}),
take(1),
).subscribe();
}
getTargets() {
this.targetService.readAllByProbeID(this.probeHost.probe.id)
.pipe(
tap(() => {
this.pending$ = of(true);
}),
map((targets: Target[]) => {
this.targets = targets;
this.getInfras();
}),
catchError(error => {
this.error$ = of(error);
return of();
}),
tap(() => {
this.pending$ = of(false);
}),
take(1),
).subscribe();
}
generateTree(infras: Infra[]) {
this.zoneNode = [];
this.hostNode = [];
this.infraZones = [];
this.infraHosts = [];
this.infraServices = [];
for (const infra of infras) {
if (infra.metaInfraType.key === toMetaInfraType(MetaInfraTypeEnum.ZONE).key) {
this.infraZones.push(infra);
} else if (infra.metaInfraType.key === toMetaInfraType(MetaInfraTypeEnum.HOST).key) {
this.infraHosts.push(infra);
} else if (infra.metaInfraType.key === toMetaInfraType(MetaInfraTypeEnum.SERVICE).key) {
this.infraServices.push(infra);
}
}
this.infraZones.forEach(infraZone => {
this.addInfraZone(infraZone);
});
this.infraHosts.forEach(infraHost => {
this.addInfraHost(infraHost);
});
this.infraServices.forEach(infraService => {
this.addInfraService(infraService);
});
}
addInfraZone(infraZone: InfraZone) {
const target: Target = this.checkAlreadyTarget(infraZone.id);
this.zoneNode.push({
label: this.probeHost.probe.cidr,
type: 'ZONE',
data: {
target: target,
date: infraZone.createDate,
object: infraZone,
infraID: infraZone.id,
},
children: this.hostNode,
expanded: true
});
}
addInfraHost(infraHost: InfraHost) {
const target: Target = this.checkAlreadyTarget(infraHost.id);
const ip = infraHost.infraHostIPs[0].address;
const idx = this.findHostIndex(ip);
this.hostNode.splice(idx, 0, {
type: 'HOST',
label: ip,
data: {
target: target,
date: infraHost.createDate,
ip: this.convertIPtoNumber(ip),
object: infraHost,
infraID: infraHost.id,
},
expanded: true,
children: []
});
}
addInfraService(infraService: InfraService) {
const target: Target = this.checkAlreadyTarget(infraService.id);
const targetHostNode = this.findHostNodeByService(infraService.infraHostPort.infraHostIP.address);
const idx = this.findServiceIndex(targetHostNode.children, infraService.metaTargetServiceType.name);
targetHostNode.children.splice(idx, 0, {
type: 'SERVICE',
label: infraService.metaTargetServiceType.name + ' (' + infraService.infraHostPort.port + ')',
data: {
target: target,
date: infraService.createDate,
portType: infraService.infraHostPort.metaPortType.name,
portNumber: infraService.infraHostPort.port,
object: infraService,
infraID: infraService.id,
name: infraService.metaTargetServiceType.name
},
});
}
checkAlreadyTarget(infraID: number): Target {
return this.targets.find(target => target.infra.id === infraID);
}
discoveryStarted(startedAt: Date) {
console.log('Discovery Started at: ' + startedAt);
this.pending$ = of(true);
}
discoveryStopped(stoppedAt: Date) {
console.log('Discovery Stopped at: ' + stoppedAt);
this.saveDiscoveredInfras();
this.pending$ = of(false);
}
saveDiscoveredInfras() {
this.infraManageService.registDiscoverd(
this.probeHost.probe.id,
this.discoveredHosts,
this.discoveredServices)
.pipe(
tap(() => {
this.infraSaved = false;
this.pending$ = of(true);
}),
map((infras: Infra[]) => {
if (infras) {
this.savedInfras = infras;
this.msgs = [];
this.msgs.push({
severity: 'success',
summary: infras.length + '개의 Infra가 새로 저장되었습니다. 모니터링 대상(들)을 선택 후 저장하세요.',
});
}
this.pending$ = of(false);
}),
catchError(error => {
this.error$ = of(error);
return of();
}),
tap(() => {
this.infraSaved = true;
}),
take(1),
).subscribe();
}
addHost(host: Host) {
let exist = false;
this.infraHosts.forEach(infraHost => {
if (infraHost.infraHostIPs[0].address === host.address) {
exist = true;
return;
}
});
if (exist) {
return;
}
const idx = this.findHostIndex(host.address);
this.hostNode.splice(idx, 0, {
type: 'HOST',
label: host.address,
data: {
target: null,
date: null,
ip: this.convertIPtoNumber(host.address),
object: host,
infraID: null,
},
expanded: true,
children: []
});
this.discoveredHosts.push(host);
}
addService(service: Service) {
let exist = false;
this.infraServices.forEach(infraService => {
if (infraService.metaTargetServiceType.name === service.key &&
infraService.infraHostPort.port === service.port.portNumber &&
infraService.infraHostPort.infraHostIP.address === service.port.host.address
) {
exist = true;
return;
}
});
if (exist) {
return;
}
const targetHostNode = this.findHostNodeByService(service.port.host.address);
const idx = this.findServiceIndex(targetHostNode.children, service.key);
targetHostNode.children.splice(idx, 0, {
type: 'SERVICE',
label: service.key + ' (' + service.port.portNumber + ')',
data: {
target: null,
date: null,
portType: service.port.metaPortType.name,
portNumber: service.port.portNumber,
object: service,
InfraID: null,
name: service.key
},
});
this.discoveredServices.push(service);
}
findHostIndex(hostIP: string): number {
let index = 0;
this.hostNode.forEach(node => {
if (node.data.ip < this.convertIPtoNumber(hostIP)) {
index++;
}
});
return index;
}
findServiceIndex(serviceNodes: TreeNode[], serviceName: string): number {
let index = 0;
serviceNodes.forEach(node => {
if (node.data.name.toUpperCase().localeCompare(serviceName.toUpperCase()) === -1) {
index++;
}
});
return index;
}
findHostNodeByService(serviceAddress: string): TreeNode {
let targetHost = null;
this.hostNode.forEach((value, i) => {
if (value.data.ip === this.convertIPtoNumber(serviceAddress)) {
targetHost = value;
return;
}
});
return targetHost;
}
convertIPtoNumber(ip: string): number {
return ip.split('.').map((octet, index, array) => {
return parseInt(octet) * Math.pow(256, (array.length - index - 1));
}).reduce((prev, curr) => {
return prev + curr;
});
}
checkHighlight(label: string, type: number) {
let highlight = true;
if (this.filterWord && (label.toUpperCase().indexOf(this.filterWord.toUpperCase()) < 0)) {
highlight = false;
}
if (type === 1 && this.filterServices[label] === false) {
highlight = false;
}
return highlight;
}
onTargetSelect(e, node: TreeNode) {
if (e.checked) {
this.selectedItems.push(node);
} else {
const index = this.selectedItems.indexOf(node);
this.selectedItems.splice(index, 1);
}
}
saveTargets() {
const targets: Target[] = [];
this.selectedItems.forEach(node => {
let infraID = node.data.infraID;
if (null === infraID) { // 새로 발견된 Host or Service
for (const infra of this.savedInfras) {
if (infra.metaInfraType.key === toMetaInfraType(MetaInfraTypeEnum.HOST).key) {
const infraHost: InfraHost = infra;
const host: Host = node.data.object;
if (infraHost.infraHostIPs[0].address === host.address) {
infraID = infraHost.id;
}
} else if (infra.metaInfraType.key === toMetaInfraType(MetaInfraTypeEnum.SERVICE).key) {
const infraService: InfraService = infra;
const service: Service = node.data.object;
if (infraService.metaTargetServiceType.name === service.key &&
infraService.infraHostPort.infraHostIP.address === service.port.host.address) {
infraID = infraService.id;
}
}
}
}
const target: Target = {
infra: {
id: infraID
},
name: node.label,
sensorCount: 0,
};
targets.push(target);
});
this.targetService.registAll(targets, this.probeHost.probe.id)
.pipe(
tap(() => {
}),
map((targets: Target[]) => {
if (targets) {
this.targetSaved = true;
}
}),
catchError(error => {
this.error$ = of(error);
return of();
}),
tap(() => {
}),
take(1),
).subscribe();
}
}