Update scenario load ios

This commit is contained in:
nguyentrungthat 2025-12-30 16:04:24 +07:00
parent e55951d42c
commit ef1ba4ac99
4 changed files with 428 additions and 109 deletions

View File

@ -26,6 +26,7 @@ import Line from '#models/line'
import { ErrorRow, TestResult } from '../ultils/types.js' import { ErrorRow, TestResult } from '../ultils/types.js'
import momentTZ from 'moment-timezone' import momentTZ from 'moment-timezone'
import { PhysicalPortTest } from './physical_test_service.js' import { PhysicalPortTest } from './physical_test_service.js'
import Station from '#models/station'
type Inventory = { type Inventory = {
pid: string pid: string
@ -377,6 +378,7 @@ export default class LineConnection {
this.breakSpam() this.breakSpam()
} }
} }
const now = Date.now() const now = Date.now()
this.outputScenario += `\n\n---start-scenarios---${now}---${userName}---${script?.title}---\n---scenario---${script?.title}---${now}---\n` this.outputScenario += `\n\n---start-scenarios---${now}---${userName}---${script?.title}---\n---scenario---${script?.title}---${now}---\n`
appendLog( appendLog(
@ -393,46 +395,54 @@ export default class LineConnection {
const steps = typeof script?.body === 'string' ? JSON.parse(script?.body) : [] const steps = typeof script?.body === 'string' ? JSON.parse(script?.body) : []
let stepIndex = 0 let stepIndex = 0
return new Promise((resolve, reject) => { // Create a timeout
const timeoutTimer = setTimeout( let timeoutTimer: NodeJS.Timeout | null = null
() => { const timeoutNumber = script.timeout ? Number(script.timeout) * 1000 : 300000
this.config.runningScenario = '' const onTimeout = () => {
this.socketIO.emit('running_scenario', { this.config.runningScenario = ''
stationId: this.config.stationId, this.socketIO.emit('running_scenario', {
lineId: this.config.id, stationId: this.config.stationId,
title: '', lineId: this.config.id,
}) title: '',
this.outputBuffer = '' })
this.outputScenario = '' this.outputBuffer = ''
this.config.output += 'Timeout run scenario' this.outputScenario = ''
this.dataDPELP = { this.config.output += 'Timeout run scenario'
line: this.config.lineNumber, this.dataDPELP = {
pid: '', line: this.config.lineNumber,
vid: '', pid: '',
sn: '', vid: '',
ios: '', sn: '',
mac: '', ios: '',
license: [], mac: '',
issues: ['No data'], license: [],
summary: '', issues: ['No data'],
} summary: '',
this.socketIO.emit('line_output', { }
stationId: this.config.stationId, this.socketIO.emit('line_output', {
lineId: this.config.id, stationId: this.config.stationId,
data: 'Timeout run scenario', lineId: this.config.id,
}) data: 'Timeout run scenario',
this.outputScenario += `\n---end-scenarios---${now}---${userName}---\n` })
appendLog( this.outputScenario += `\n---end-scenarios---${now}---${userName}---\n`
`\n---end-scenarios---${now}---${userName}---\n`, appendLog(
this.config.stationId, `\n---end-scenarios---${now}---${userName}---\n`,
this.config.stationName, this.config.stationId,
this.config.stationIp, this.config.stationName,
this.config.lineNumber this.config.stationIp,
) this.config.lineNumber
// reject(new Error('Script timeout'))
},
script.timeout ? Number(script.timeout) * 1000 : 300000
) )
// reject(new Error('Script timeout'))
}
const resetTimeout = () => {
// console.log('resetTimeout', timeoutNumber)
// this.outputBuffer = ''
if (timeoutTimer) clearTimeout(timeoutTimer)
timeoutTimer = setTimeout(onTimeout, timeoutNumber)
}
return new Promise((resolve, reject) => {
timeoutTimer = setTimeout(onTimeout, timeoutNumber)
const runStep = async (index: number) => { const runStep = async (index: number) => {
if (index >= steps.length) { if (index >= steps.length) {
@ -442,7 +452,7 @@ export default class LineConnection {
runStep(index) runStep(index)
}, 5000) }, 5000)
return return
} else clearTimeout(timeoutTimer) } else if (timeoutTimer) clearTimeout(timeoutTimer)
this.outputScenario += `\n---end-scenarios---${now}---${userName}---\n` this.outputScenario += `\n---end-scenarios---${now}---${userName}---\n`
this.outputBuffer = '' this.outputBuffer = ''
this.config.runningScenario = '' this.config.runningScenario = ''
@ -536,8 +546,6 @@ export default class LineConnection {
} catch (error) { } catch (error) {
console.log(error) console.log(error)
} }
// this.outputBuffer = ''
// this.outputScenario += `\n---end-scenarios---${now}---${userName}---\n`
appendLog( appendLog(
`\n---end-scenarios---${now}---${userName}---\n`, `\n---end-scenarios---${now}---${userName}---\n`,
this.config.stationId, this.config.stationId,
@ -548,19 +556,20 @@ export default class LineConnection {
this.listScenarios = [] this.listScenarios = []
resolve(true) resolve(true)
return return
} } else resetTimeout()
const step = steps[index] const step = steps[index]
let repeatCount = Number(step.repeat) || 1 let repeatCount = Number(step.repeat) || 1
const delay = step?.delay ? Number(step?.delay) * 1000 : 1000 const delay = step?.delay ? Number(step?.delay) * 1000 : 1000
const sendCommand = async () => { const sendCommand = async () => {
if (repeatCount <= 0) { // if (repeatCount <= 0) {
// Done → next step // // Done → next step
stepIndex++ // stepIndex++
return runStep(stepIndex) // return runStep(stepIndex)
} // }
if (typeof step.send !== 'undefined') { if (typeof step.send !== 'undefined') {
console.log(Date.now() - now, (step?.send ?? '[ENTER]').toString())
this.outputScenario += `\n---send-command---"${(step?.send ?? '[ENTER]').toString().replace(/\r/g, '\\r').replace(/\n/g, '\\n')}"---${now}---\n` this.outputScenario += `\n---send-command---"${(step?.send ?? '[ENTER]').toString().replace(/\r/g, '\\r').replace(/\n/g, '\\n')}"---${now}---\n`
appendLog( appendLog(
`\n---send-command---"${(step?.send ?? '[ENTER]').toString().replace(/\r/g, '\\r').replace(/\n/g, '\\n')}"---${now}---\n`, `\n---send-command---"${(step?.send ?? '[ENTER]').toString().replace(/\r/g, '\\r').replace(/\n/g, '\\n')}"---${now}---\n`,
@ -573,7 +582,11 @@ export default class LineConnection {
} }
repeatCount-- repeatCount--
setTimeout(() => sendCommand(), delay) if (repeatCount <= 0) {
// Done → next step
stepIndex++
return runStep(stepIndex)
} else setTimeout(() => sendCommand(), delay)
} }
// Nếu expect rỗng → gửi ngay // Nếu expect rỗng → gửi ngay
@ -1043,4 +1056,279 @@ export default class LineConnection {
formReport formReport
) )
} }
async loadIosRouter(nameIos: string, userName: string) {
const station = await Station.find(this.config.stationId)
if (!station) return
const network = station?.gateway || '172.25.1.1'
const [a, b] = network.split('.').map(Number)
const body = [
{
expect: '',
send: `IP_ADDRESS=${a}.${b}.100.${this.config.id < 254 ? this.config.id : 254 - this.config.id}`,
delay: '1',
repeat: '1',
note: '',
},
{
expect: 'rommon',
send: `IP_SUBNET_MASK=255.255.0.0`,
delay: '1',
repeat: '1',
note: '',
},
{
expect: 'rommon',
send: `DEFAULT_GATEWAY=${station?.gateway ? station?.gateway : '0.0.0.0'}`,
delay: '1',
repeat: '1',
note: '',
},
{
expect: 'rommon',
send: `TFTP_SERVER=${station?.tftp_ip}`,
delay: '1',
repeat: '1',
note: '',
},
{
expect: 'rommon',
send: `TFTP_FILE=ios/${nameIos}`,
delay: '1',
repeat: '1',
note: '',
},
{
expect: 'rommon',
send: `tftpdnld`,
delay: '1',
repeat: '1',
note: '',
},
{
expect: 'y/n',
send: `y`,
delay: '2',
repeat: '1',
note: '',
},
{
expect: 'rommon',
send: `boot usbflash0:${nameIos}`,
delay: '1',
repeat: '1',
note: '',
},
{
expect: 'Press RETURN to get started',
send: ``,
delay: '1',
repeat: '1',
note: '',
},
{
expect: '',
send: ``,
delay: '1',
repeat: '1',
note: '',
},
{
expect: '',
send: `enable`,
delay: '1',
repeat: '1',
note: '',
},
{
expect: '#',
send: `configure terminal`,
delay: '1',
repeat: '1',
note: '',
},
{
expect: '',
send: `boot system usbflash0:${nameIos}`,
delay: '1',
repeat: '1',
note: '',
},
{
expect: '',
send: `end`,
delay: '1',
repeat: '1',
note: '',
},
{
expect: '',
send: `write memory`,
delay: '1',
repeat: '1',
note: '',
},
{
expect: '',
send: ``,
delay: '1',
repeat: '1',
note: '',
},
]
const script = {
id: 0,
isReboot: true,
sendResult: false,
send_result: false,
title: 'Load IOS Router',
timeout: 1000000,
body: JSON.stringify(body),
}
this.runScript(script as any, userName)
}
async loadIosSwitch(nameIos: string, userName: string) {
const station = await Station.find(this.config.stationId)
if (!station) return
const network = station?.gateway || '172.25.1.1'
const [a, b] = network.split('.').map(Number)
const body = [
{
expect: '',
send: ``,
delay: '1',
repeat: '1',
note: '',
},
{
expect: '',
send: `IP_ADDRESS=${a}.${b}.100.${this.config.id < 254 ? this.config.id : 254 - this.config.id}`,
delay: '1',
repeat: '1',
note: '',
},
{
expect: 'switch:',
send: `IP_SUBNET_MASK=255.255.0.0`,
delay: '1',
repeat: '1',
note: '',
},
{
expect: 'switch:',
send: `DEFAULT_GATEWAY=${station?.gateway ? station?.gateway : '0.0.0.0'}`,
delay: '1',
repeat: '1',
note: '',
},
{
expect: 'switch:',
send: `TFTP_SERVER=${station?.tftp_ip}`,
delay: '1',
repeat: '1',
note: '',
},
{
expect: 'switch:',
send: `TFTP_FILE=ios/${nameIos}`,
delay: '1',
repeat: '1',
note: '',
},
{
expect: 'switch:',
send: `tftpdnld`,
delay: '1',
repeat: '1',
note: '',
},
{
expect: 'y/n',
send: `y`,
delay: '2',
repeat: '1',
note: '',
},
{
expect: 'switch:',
send: `boot flash:${nameIos}`,
delay: '1',
repeat: '1',
note: '',
},
{
expect: 'Press RETURN to get started',
send: ``,
delay: '1',
repeat: '1',
note: '',
},
{
expect: '',
send: ``,
delay: '1',
repeat: '1',
note: '',
},
{
expect: '',
send: `enable`,
delay: '1',
repeat: '1',
note: '',
},
{
expect: '#',
send: `configure terminal`,
delay: '1',
repeat: '1',
note: '',
},
{
expect: '',
send: `boot system usbflash0:${nameIos}`,
delay: '1',
repeat: '1',
note: '',
},
{
expect: '',
send: `end`,
delay: '1',
repeat: '1',
note: '',
},
{
expect: '',
send: `write memory`,
delay: '1',
repeat: '1',
note: '',
},
{
expect: '',
send: ``,
delay: '1',
repeat: '1',
note: '',
},
]
const script = {
id: 0,
isReboot: false,
sendResult: false,
send_result: false,
title: 'Load IOS Switch',
timeout: 1000000,
body: JSON.stringify(body),
}
this.runScript(script as any, userName)
}
} }

View File

@ -8,8 +8,8 @@ import axios from 'axios'
import moment from 'moment' import moment from 'moment'
const mailTo = 'andrew.ng@apactech.io' const mailTo = 'andrew.ng@apactech.io'
// const mailCC = ['ips@ipsupply.com.au', 'kay@ipsupply.com.au', 'joseph@apactech.io'] const mailCC = ['ips@ipsupply.com.au', 'kay@ipsupply.com.au', 'joseph@apactech.io']
const mailCC = '' // const mailCC = ''
type DetectAI = { type DetectAI = {
status: string[] status: string[]

View File

@ -339,57 +339,62 @@ export class WebSocketIo {
}) })
socket.on('control_apc', async (data) => { socket.on('control_apc', async (data) => {
const { outletNumbers, action, station, apcName } = data try {
if (action === 'reconnect') { const { outletNumbers, action, station, apcName } = data
if (!station) return if (action === 'reconnect') {
const apcIp = (station as any)[`${apcName}_ip`] as string
const apc = this.apcsControl.get(apcIp)
if (apc) {
await apc.reconnect()
this.keepConnectAPC(apcIp, io)
} else await this.connectApc(io, apcName, station)
} else {
for (const outletNumber of outletNumbers) {
if (!outletNumber || outletNumber < 0) return
if (!station) return if (!station) return
// find line from station by apcName and outletNumber
const lines = await Line.query()
.where('station_id', station.id)
.andWhere('apc_name', apcName)
.andWhere('outlet', outletNumber)
if (lines.length > 0) {
const line = this.lineMap.get(lines[0].id)
if (line) this.setTimeoutConnect(lines[0].id, line)
}
const apcIp = (station as any)[`${apcName}_ip`] as string const apcIp = (station as any)[`${apcName}_ip`] as string
const apc = this.apcsControl.get(apcIp) const apc = this.apcsControl.get(apcIp)
if (apc && apc.status !== 'CONNECTED') { if (apc) {
await apc.reconnect() await apc.reconnect()
this.keepConnectAPC(apcIp, io) this.keepConnectAPC(apcIp, io)
} } else await this.connectApc(io, apcName, station)
if (apc) { } else {
switch (action) { for (const outletNumber of outletNumbers) {
case 'on': if (!outletNumber || outletNumber < 0) return
await apc?.turnOnOutlet(outletNumber) if (!station) return
break // find line from station by apcName and outletNumber
case 'off': const lines = await Line.query()
await apc?.turnOffOutlet(outletNumber) .where('station_id', station.id)
break .andWhere('apc_name', apcName)
case 'restart': .andWhere('outlet', outletNumber)
await apc?.restartOutlet(outletNumber) if (lines.length > 0) {
break const line = this.lineMap.get(lines[0].id)
case 'reconnect': if (line) this.setTimeoutConnect(lines[0].id, line)
await apc?.reconnect() }
break
default: const apcIp = (station as any)[`${apcName}_ip`] as string
break if (!this.apcsControl.get(apcIp)) await this.connectApc(io, apcName, station)
const apc = this.apcsControl.get(apcIp)
if (apc && apc.status !== 'CONNECTED') {
await apc.reconnect()
this.keepConnectAPC(apcIp, io)
}
if (apc) {
switch (action) {
case 'on':
await apc?.turnOnOutlet(outletNumber)
break
case 'off':
await apc?.turnOffOutlet(outletNumber)
break
case 'restart':
await apc?.restartOutlet(outletNumber)
break
case 'reconnect':
await apc?.reconnect()
break
default:
break
}
setTimeout(() => {
apc?.navigateToOutlets()
}, 10000)
} }
setTimeout(() => {
apc?.navigateToOutlets()
}, 10000)
} }
} }
} catch (e) {
console.log('control_apc', e)
} }
}) })
@ -636,6 +641,32 @@ export class WebSocketIo {
{} {}
) )
}) })
socket.on('load_ios_router', async (data) => {
const { stationId, lineId, iosName } = data
await this.handleLineOperation(
io,
stationId,
[lineId],
async (lineCon) => {
lineCon.loadIosRouter(iosName, userName)
},
{}
)
})
socket.on('load_ios_switch', async (data) => {
const { stationId, lineId, iosName } = data
await this.handleLineOperation(
io,
stationId,
[lineId],
async (lineCon) => {
lineCon.loadIosSwitch(iosName, userName)
},
{}
)
})
}) })
socketServer.listen(SOCKET_IO_PORT, () => { socketServer.listen(SOCKET_IO_PORT, () => {

View File

@ -42,105 +42,105 @@ export const ButtonDPELP = ({
{ {
expect: "", expect: "",
send: "", send: "",
delay: "1000", delay: "1",
repeat: "1", repeat: "1",
note: "", note: "",
}, },
{ {
expect: "", expect: "",
send: " no", send: " no",
delay: "1000", delay: "1",
repeat: "1", repeat: "1",
note: "", note: "",
}, },
{ {
expect: "", expect: "",
send: "\r\n", send: "\r\n",
delay: "1000", delay: "1",
repeat: "1", repeat: "1",
note: "", note: "",
}, },
{ {
expect: "", expect: "",
send: "\r\n", send: "\r\n",
delay: "2000", delay: "2",
repeat: "1", repeat: "1",
note: "", note: "",
}, },
// { // {
// expect: "", // expect: "",
// send: " terminal length 0", // send: " terminal length 0",
// delay: "3000", // delay: "3",
// repeat: "1", // repeat: "1",
// note: "", // note: "",
// }, // },
{ {
expect: "", expect: "",
send: "enable", send: "enable",
delay: "3000", delay: "3",
repeat: "1", repeat: "1",
note: "", note: "",
}, },
{ {
expect: "", expect: "",
send: "show inventory", send: "show inventory",
delay: "3000", delay: "3",
repeat: "1", repeat: "1",
note: "", note: "",
}, },
{ {
expect: "", expect: "",
send: "show version | include License", send: "show version | include License",
delay: "1000", delay: "1",
repeat: "1", repeat: "1",
note: "", note: "",
}, },
{ {
expect: "", expect: "",
send: "show version", send: "show version",
delay: "1000", delay: "1",
repeat: "1", repeat: "1",
note: "", note: "",
}, },
{ {
expect: "", expect: "",
send: "show diag", send: "show diag",
delay: "3000", delay: "3",
repeat: "1", repeat: "1",
note: "", note: "",
}, },
{ {
expect: "", expect: "",
send: "show post", send: "show post",
delay: "3000", delay: "3",
repeat: "1", repeat: "1",
note: "", note: "",
}, },
{ {
expect: "", expect: "",
send: "show env all", send: "show env all",
delay: "3000", delay: "3",
repeat: "1", repeat: "1",
note: "", note: "",
}, },
{ {
expect: "", expect: "",
send: "show license", send: "show license",
delay: "3000", delay: "3",
repeat: "1", repeat: "1",
note: "", note: "",
}, },
{ {
expect: "", expect: "",
send: "show log", send: "show log",
delay: "3000", delay: "3",
repeat: "1", repeat: "1",
note: "", note: "",
}, },
{ {
expect: "", expect: "",
send: "show platform", send: "show platform",
delay: "3000", delay: "3",
repeat: "1", repeat: "1",
note: "", note: "",
}, },