Update load license
This commit is contained in:
parent
9266b63823
commit
5586f8f930
|
|
@ -19,7 +19,7 @@ export default class IosLicenseController {
|
|||
|
||||
async getIos() {
|
||||
const smbPath = '/ipsteamSMB/IOS/i'
|
||||
const localPath = 'storage/ios'
|
||||
const localPath = 'storage/i'
|
||||
|
||||
const targetPath = fs.existsSync(smbPath) ? smbPath : localPath
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ export default class IosLicenseController {
|
|||
|
||||
async getLicense() {
|
||||
const smbPath = '/ipsteamSMB/IOS/License'
|
||||
const localPath = 'storage/license'
|
||||
const localPath = 'storage/License'
|
||||
|
||||
const targetPath = fs.existsSync(smbPath) ? smbPath : localPath
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { textfsmResults } from './../ultils/templates/index.js'
|
|||
import net from 'node:net'
|
||||
import {
|
||||
appendLog,
|
||||
applyRules,
|
||||
buildBody,
|
||||
classifyLog,
|
||||
cleanData,
|
||||
detectScenarioByModel,
|
||||
|
|
@ -1135,127 +1135,14 @@ export default class LineConnection {
|
|||
const [a, b] = network.split('.').map(Number)
|
||||
const timeZone = process.env.TIME_ZONE || 'Australia/Sydney'
|
||||
const startTime = momentTZ().tz(timeZone).format('YYYY/MM/DD, HH:mm:ss')
|
||||
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=${tftpIp}`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: 'rommon',
|
||||
send: `TFTP_FILE=i/${nameIos}`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: 'rommon',
|
||||
send: this.listDeviceIos?.includes(nameIos) ? '' : `tftpdnld`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: this.listDeviceIos?.includes(nameIos) ? '' : 'y/n',
|
||||
send: this.listDeviceIos?.includes(nameIos) ? '' : `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: `show version`,
|
||||
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 body = buildBody(
|
||||
'ROUTER_IOS',
|
||||
tftpIp,
|
||||
nameIos,
|
||||
`${a}.${b}.100.${this.config.id < 254 ? this.config.id : 254 - this.config.id}`,
|
||||
`${station?.gateway ? station?.gateway : '0.0.0.0'}`,
|
||||
this.listDeviceIos
|
||||
)
|
||||
|
||||
const script = {
|
||||
id: 0,
|
||||
|
|
@ -1285,190 +1172,14 @@ export default class LineConnection {
|
|||
const startTime = momentTZ().tz(timeZone).format('YYYY/MM/DD, HH:mm:ss')
|
||||
await this.backupIos(nameIos)
|
||||
|
||||
const body = [
|
||||
{
|
||||
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: `interface vlan 1`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `ip address ${a}.${b}.100.${this.config.id < 254 ? this.config.id : 254 - this.config.id} 255.255.0.0`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `no shutdown`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `exit`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `ip default-gateway ${station?.gateway ? station?.gateway : '0.0.0.0'}`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `end`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: ``,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: this.listDeviceIos?.includes(nameIos) ? '' : `copy tftp: flash:`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '',
|
||||
send: this.listDeviceIos?.includes(nameIos) ? '' : `${tftpIp}`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '',
|
||||
send: this.listDeviceIos?.includes(nameIos) ? '' : `i/${nameIos}`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '',
|
||||
send: ``,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '',
|
||||
send: ``,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: ``,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `configure terminal`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `boot system flash:${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: `reload`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '',
|
||||
send: ``,
|
||||
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: '3',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `show version`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
]
|
||||
const body = buildBody(
|
||||
'SWITCH_IOS',
|
||||
tftpIp,
|
||||
nameIos,
|
||||
`${a}.${b}.100.${this.config.id < 254 ? this.config.id : 254 - this.config.id}`,
|
||||
`${station?.gateway ? station?.gateway : '0.0.0.0'}`,
|
||||
this.listDeviceIos
|
||||
)
|
||||
|
||||
const script = {
|
||||
id: 0,
|
||||
|
|
@ -1507,6 +1218,29 @@ export default class LineConnection {
|
|||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Send mail report after load license
|
||||
*/
|
||||
async sendEmailLoadLicense(nameLicense: string, startTime: string) {
|
||||
const timeZone = process.env.TIME_ZONE || 'Australia/Sydney'
|
||||
const dataFormat = momentTZ().tz(timeZone).format('YYYY/MM/DD, HH:mm:ss')
|
||||
const body = `
|
||||
Load IOS Report<br/>
|
||||
────────────────────────────────<br/>
|
||||
Station : <b>${this.config.stationName}</b><br/>
|
||||
Line : <b>${this.config.lineNumber}</b><br/>
|
||||
License : <b>${nameLicense}</b> <br/>
|
||||
Started At : ${startTime}<br/>
|
||||
Finished At : ${dataFormat}<br/>
|
||||
────────────────────────────────<br/>
|
||||
`.trim()
|
||||
|
||||
await sendMessageToMail(
|
||||
`[ATC] - [${this.config.stationName} - Line: ${this.config.lineNumber}] - Load IOS Report`,
|
||||
body
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check list ios exist on flash
|
||||
*/
|
||||
|
|
@ -1631,4 +1365,84 @@ export default class LineConnection {
|
|||
this.config.runningScenario = ''
|
||||
await sleep(1000)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle load License for switch
|
||||
* Assumes traditional licensing (PAK/file-based) via TFTP
|
||||
*/
|
||||
async loadLicenseSwitch(licenseFileName: string, userName: string) {
|
||||
const station = await Station.find(this.config.stationId)
|
||||
if (!station) return
|
||||
|
||||
// Setup network variables (giống hệt logic load IOS để đảm bảo thông mạng)
|
||||
const network = station?.gateway || '172.25.1.1'
|
||||
const tftpIp = station?.tftp_ip || '172.16.7.69'
|
||||
const [a, b] = network.split('.').map(Number)
|
||||
|
||||
// Setup time/logging
|
||||
const timeZone = process.env.TIME_ZONE || 'Australia/Sydney'
|
||||
const startTime = momentTZ().tz(timeZone).format('YYYY/MM/DD, HH:mm:ss')
|
||||
|
||||
const body = buildBody(
|
||||
'ROUTER_IOS',
|
||||
tftpIp,
|
||||
licenseFileName,
|
||||
`${a}.${b}.100.${this.config.id < 254 ? this.config.id : 254 - this.config.id}`,
|
||||
`${station?.gateway ? station?.gateway : '0.0.0.0'}`,
|
||||
this.listDeviceIos
|
||||
)
|
||||
|
||||
const script = {
|
||||
id: 0, // Hoặc ID khác tuỳ logic DB
|
||||
isReboot: true, // License thường cần reboot
|
||||
sendResult: false,
|
||||
send_result: false,
|
||||
title: 'Load License Switch',
|
||||
timeout: 1000, // Tăng timeout nếu cần vì lệnh install có thể lâu
|
||||
body: JSON.stringify(body),
|
||||
}
|
||||
|
||||
await this.runScript(script as any, userName)
|
||||
await this.sendEmailLoadLicense(licenseFileName, startTime) // Nếu bạn có hàm gửi mail báo cáo
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle load License for Router
|
||||
*/
|
||||
async loadLicenseRouter(licenseFileName: string, userName: string) {
|
||||
const station = await Station.find(this.config.stationId)
|
||||
if (!station) return
|
||||
|
||||
const network = station?.gateway || '172.25.1.1'
|
||||
const tftpIp = station?.tftp_ip || '172.16.7.69'
|
||||
const [a, b] = network.split('.').map(Number)
|
||||
|
||||
// Tên Interface dùng để load (Cần sửa nếu router dùng 0/0/0 hoặc tên khác)
|
||||
const mgmtInterface = 'GigabitEthernet0/0'
|
||||
|
||||
const timeZone = process.env.TIME_ZONE || 'Australia/Sydney'
|
||||
const startTime = momentTZ().tz(timeZone).format('YYYY/MM/DD, HH:mm:ss')
|
||||
|
||||
const body = buildBody(
|
||||
'ROUTER_IOS',
|
||||
tftpIp,
|
||||
licenseFileName,
|
||||
`${a}.${b}.100.${this.config.id < 254 ? this.config.id : 254 - this.config.id}`,
|
||||
`${station?.gateway ? station?.gateway : '0.0.0.0'}`,
|
||||
this.listDeviceIos
|
||||
)
|
||||
|
||||
const script = {
|
||||
id: 0,
|
||||
isReboot: true,
|
||||
sendResult: false,
|
||||
send_result: false,
|
||||
title: 'Load License Router',
|
||||
timeout: 1000,
|
||||
body: JSON.stringify(body),
|
||||
}
|
||||
|
||||
await this.runScript(script as any, userName)
|
||||
await this.sendEmailLoadLicense(licenseFileName, startTime)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -675,3 +675,608 @@ export function normalizeInterface(name: string): string {
|
|||
.replace(/^Hu(?=\d)/, 'HundredGigE')
|
||||
.replace(/^Eth(?=\d)/, 'Ethernet')
|
||||
}
|
||||
|
||||
type BodyType = 'ROUTER_IOS' | 'SWITCH_IOS' | 'SWITCH_LICENSE' | 'ROUTER_LICENSE'
|
||||
|
||||
export function buildBody(
|
||||
type: BodyType,
|
||||
tftpIp: string,
|
||||
fileName: string,
|
||||
address: string,
|
||||
gateway: string,
|
||||
listDeviceIos: string[]
|
||||
) {
|
||||
switch (type) {
|
||||
/* ================= ROUTER LOAD IOS ================= */
|
||||
case 'ROUTER_IOS':
|
||||
return [
|
||||
{
|
||||
expect: '',
|
||||
send: `IP_ADDRESS=${address}`,
|
||||
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=${gateway}`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: 'rommon',
|
||||
send: `TFTP_SERVER=${tftpIp}`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: 'rommon',
|
||||
send: `TFTP_FILE=i/${fileName}`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: 'rommon',
|
||||
send: listDeviceIos?.includes(fileName) ? '' : `tftpdnld`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: listDeviceIos?.includes(fileName) ? '' : 'y/n',
|
||||
send: listDeviceIos?.includes(fileName) ? '' : `y`,
|
||||
delay: '2',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: 'rommon',
|
||||
send: `boot usbflash0:${fileName}`,
|
||||
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: `show inventory`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `show version`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `configure terminal`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '',
|
||||
send: `boot system usbflash0:${fileName}`,
|
||||
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: '',
|
||||
},
|
||||
]
|
||||
|
||||
/* ================= SWITCH LOAD IOS ================= */
|
||||
case 'SWITCH_IOS':
|
||||
return [
|
||||
{
|
||||
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: `interface vlan 1`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `ip address ${address} 255.255.0.0`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `no shutdown`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `exit`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `ip default-gateway ${gateway}`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `end`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{ expect: '', send: ``, delay: '1', repeat: '1', note: '' },
|
||||
{
|
||||
expect: '#',
|
||||
send: listDeviceIos?.includes(fileName) ? '' : `copy tftp: flash:`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '',
|
||||
send: listDeviceIos?.includes(fileName) ? '' : `${tftpIp}`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '',
|
||||
send: listDeviceIos?.includes(fileName) ? '' : `i/${fileName}`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{ expect: '', send: ``, delay: '1', repeat: '1', note: '' },
|
||||
{ expect: '', send: ``, delay: '1', repeat: '1', note: '' },
|
||||
{ expect: '#', send: ``, delay: '1', repeat: '1', note: '' },
|
||||
{
|
||||
expect: '#',
|
||||
send: `configure terminal`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `boot system flash:${fileName}`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '',
|
||||
send: `end`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '',
|
||||
send: `write memory`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '',
|
||||
send: `reload`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '', // Router thường hỏi câu này
|
||||
send: ``, // Enter confirm
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Confirm reload',
|
||||
},
|
||||
{
|
||||
expect: '',
|
||||
send: ``,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Waiting for reboot...',
|
||||
},
|
||||
// --- PHẦN 4: VERIFY ---
|
||||
{
|
||||
expect: 'Press RETURN to get started!',
|
||||
send: ``,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Router is back online',
|
||||
},
|
||||
{
|
||||
expect: '',
|
||||
send: `enable`,
|
||||
delay: '3',
|
||||
repeat: '1',
|
||||
note: 'Enable again',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `show inventory`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `show license`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Verify license status',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `show version`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Verify version info',
|
||||
},
|
||||
]
|
||||
|
||||
/* ================= SWITCH LICENSE ================= */
|
||||
case 'SWITCH_LICENSE':
|
||||
return [
|
||||
{
|
||||
expect: '',
|
||||
send: ``,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Start session',
|
||||
},
|
||||
{
|
||||
expect: '',
|
||||
send: `enable`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Enter Enable mode',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `configure terminal`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Enter Config mode',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `interface vlan 1`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Select Interface Vlan 1',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `ip address ${address} 255.255.0.0`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Set IP Address',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `no shutdown`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Up interface',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `exit`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Exit interface',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `ip default-gateway ${gateway}`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Set Gateway',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `end`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'End config',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `license install tftp://${tftpIp}/License/${fileName}`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Install license',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `write memory`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Save config',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `reload`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Reload switch',
|
||||
},
|
||||
{
|
||||
expect: '', // Router thường hỏi câu này
|
||||
send: ``, // Enter confirm
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Confirm reload',
|
||||
},
|
||||
{
|
||||
expect: '',
|
||||
send: ``,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Waiting for reboot...',
|
||||
},
|
||||
|
||||
// --- PHẦN 4: VERIFY ---
|
||||
{
|
||||
expect: 'Press RETURN to get started!',
|
||||
send: ``,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Router is back online',
|
||||
},
|
||||
{
|
||||
expect: '',
|
||||
send: `enable`,
|
||||
delay: '3',
|
||||
repeat: '1',
|
||||
note: 'Enable again',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `show inventory`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `show license`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Verify license status',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `show version`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Verify version info',
|
||||
},
|
||||
]
|
||||
|
||||
/* ================= ROUTER LICENSE ================= */
|
||||
case 'ROUTER_LICENSE':
|
||||
return [
|
||||
{
|
||||
expect: '',
|
||||
send: ``,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Start session',
|
||||
},
|
||||
{
|
||||
expect: '',
|
||||
send: `enable`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Enter Enable mode',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `configure terminal`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Enter Config mode',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `interface GigabitEthernet0/0`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Select management interface',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `ip address ${address} 255.255.0.0`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Set IP Address',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `no shutdown`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Up interface',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `exit`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Exit interface',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `ip route 0.0.0.0 0.0.0.0 ${gateway}`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Set default route',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `end`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'End config',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `license install tftp://${tftpIp}/License/${fileName}`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Install license',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `write memory`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Save config',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `reload`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Reload router',
|
||||
},
|
||||
{
|
||||
expect: '', // Router thường hỏi câu này
|
||||
send: ``, // Enter confirm
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Confirm reload',
|
||||
},
|
||||
{
|
||||
expect: '',
|
||||
send: ``,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Waiting for reboot...',
|
||||
},
|
||||
|
||||
// --- PHẦN 4: VERIFY ---
|
||||
{
|
||||
expect: 'Press RETURN to get started!',
|
||||
send: ``,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Router is back online',
|
||||
},
|
||||
{
|
||||
expect: '',
|
||||
send: `enable`,
|
||||
delay: '3',
|
||||
repeat: '1',
|
||||
note: 'Enable again',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `show inventory`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: '',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `show license`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Verify license status',
|
||||
},
|
||||
{
|
||||
expect: '#',
|
||||
send: `show version`,
|
||||
delay: '1',
|
||||
repeat: '1',
|
||||
note: 'Verify version info',
|
||||
},
|
||||
]
|
||||
|
||||
default:
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,11 +109,6 @@ router
|
|||
router
|
||||
.group(() => {
|
||||
router.get('/ios', '#controllers/ios_license_controller.getIos')
|
||||
router.post('/ios/upload', '#controllers/ios_license_controller.uploadIos')
|
||||
router.get('/ios/download/:filename', '#controllers/ios_license_controller.downloadIos')
|
||||
|
||||
router.get('/license', '#controllers/ios_license_controller.getLicense')
|
||||
router.post('/license/upload', '#controllers/ios_license_controller.uploadLicense')
|
||||
router.get('/license/download/:filename', '#controllers/ios_license_controller.downloadLicense')
|
||||
})
|
||||
.prefix('/api')
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ function App() {
|
|||
const [listBrands, setListBrands] = useState<TBrands[]>([]);
|
||||
const [listCategories, setListCategories] = useState<TCategories[]>([]);
|
||||
const [listIos, setListIos] = useState<string[]>([]);
|
||||
const [listLicense, setListLicense] = useState<string[]>([]);
|
||||
|
||||
const connectApcSwitch = (station: TStation) => {
|
||||
if (station?.apc_1_ip && station?.apc_1_port) {
|
||||
|
|
@ -202,6 +203,18 @@ function App() {
|
|||
}
|
||||
};
|
||||
|
||||
// function get list license
|
||||
const getListLicense = async () => {
|
||||
try {
|
||||
const response = await axios.get(apiUrl + "api/license");
|
||||
if (response.data && Array.isArray(response.data)) {
|
||||
setListLicense(response.data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("Error get ios", error);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!socket) return;
|
||||
getStation();
|
||||
|
|
@ -209,6 +222,7 @@ function App() {
|
|||
getBrands();
|
||||
getCategories();
|
||||
getListIos();
|
||||
getListLicense();
|
||||
}, [socket]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -871,6 +885,7 @@ function App() {
|
|||
stationItem={stations.find((el) => el.id === Number(activeTab))}
|
||||
scenarios={scenarios}
|
||||
listIos={listIos}
|
||||
listLicense={listLicense}
|
||||
/>
|
||||
|
||||
{/* <ModalConfirmRunScenario
|
||||
|
|
|
|||
|
|
@ -0,0 +1,141 @@
|
|||
import {
|
||||
Button,
|
||||
Flex,
|
||||
Modal,
|
||||
ScrollArea,
|
||||
Table,
|
||||
Text,
|
||||
TextInput,
|
||||
} from "@mantine/core";
|
||||
import type { Socket } from "socket.io-client";
|
||||
import type { TLine, TStation } from "../../untils/types";
|
||||
import { IconPlayerPlay, IconX } from "@tabler/icons-react";
|
||||
import { useState } from "react";
|
||||
|
||||
const ModalSelectLicense = ({
|
||||
socket,
|
||||
station,
|
||||
listLicense,
|
||||
opened,
|
||||
close,
|
||||
line,
|
||||
}: {
|
||||
socket: Socket | null;
|
||||
station: TStation | undefined;
|
||||
listLicense: string[];
|
||||
opened: boolean;
|
||||
close: () => void;
|
||||
line: TLine | undefined;
|
||||
}) => {
|
||||
const [inputSearch, setInputSearch] = useState<string>("");
|
||||
|
||||
const filterLicense = () => {
|
||||
return listLicense.filter((ios) =>
|
||||
ios.toLowerCase().includes(inputSearch.toLowerCase())
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
style={{ position: "absolute", left: 0 }}
|
||||
opened={opened}
|
||||
onClose={() => {
|
||||
close();
|
||||
setInputSearch("");
|
||||
}}
|
||||
title={
|
||||
<Text fz={"lg"} fw={"bolder"}>
|
||||
Select License
|
||||
</Text>
|
||||
}
|
||||
size="xl"
|
||||
>
|
||||
<Flex justify={"space-between"} align={"center"} mt={"xs"}>
|
||||
<TextInput
|
||||
style={{ width: "350px" }}
|
||||
placeholder="Search file name"
|
||||
value={inputSearch}
|
||||
onChange={(event) => setInputSearch(event.currentTarget.value)}
|
||||
rightSection={
|
||||
inputSearch ? (
|
||||
<IconX
|
||||
size={14}
|
||||
style={{ cursor: "pointer" }}
|
||||
onClick={() => setInputSearch("")}
|
||||
/>
|
||||
) : null
|
||||
}
|
||||
rightSectionPointerEvents="auto"
|
||||
size="xs"
|
||||
/>
|
||||
</Flex>
|
||||
<ScrollArea h={"70vh"} style={{ marginTop: "15px" }}>
|
||||
<Table
|
||||
stickyHeader
|
||||
striped
|
||||
highlightOnHover
|
||||
withRowBorders={true}
|
||||
withTableBorder={true}
|
||||
withColumnBorders={true}
|
||||
>
|
||||
<Table.Thead
|
||||
style={{
|
||||
top: 1,
|
||||
}}
|
||||
>
|
||||
<Table.Tr>
|
||||
<Table.Th
|
||||
style={{
|
||||
backgroundColor: "#94c6ff",
|
||||
}}
|
||||
>
|
||||
Name
|
||||
</Table.Th>
|
||||
<Table.Th
|
||||
style={{
|
||||
width: "200px",
|
||||
textAlign: "center",
|
||||
backgroundColor: "#94c6ff",
|
||||
}}
|
||||
>
|
||||
Action
|
||||
</Table.Th>
|
||||
</Table.Tr>
|
||||
</Table.Thead>
|
||||
<Table.Tbody>
|
||||
{filterLicense()?.map((ios, i) => (
|
||||
<Table.Tr key={i}>
|
||||
<Table.Td>{ios || ""}</Table.Td>
|
||||
<Table.Td
|
||||
style={{
|
||||
textAlign: "center",
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
style={{ width: "100px" }}
|
||||
variant="light"
|
||||
color="green"
|
||||
size="sm"
|
||||
leftSection={<IconPlayerPlay size={16} />}
|
||||
onClick={() => {
|
||||
socket?.emit("load_ios_switch", {
|
||||
stationId: Number(station?.id),
|
||||
lineId: Number(line?.id),
|
||||
iosName: ios,
|
||||
});
|
||||
close();
|
||||
}}
|
||||
>
|
||||
Run
|
||||
</Button>
|
||||
</Table.Td>
|
||||
</Table.Tr>
|
||||
))}
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
</ScrollArea>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default ModalSelectLicense;
|
||||
|
|
@ -44,6 +44,7 @@ import classes from "../Component.module.css";
|
|||
import { listBaudDefault } from "../../untils/constanst";
|
||||
import { motion } from "motion/react";
|
||||
import ModalSelectIOS from "./ModalSelectIOS";
|
||||
import ModalSelectLicense from "./ModalSelectLicense";
|
||||
const apiUrl = import.meta.env.VITE_BACKEND_URL;
|
||||
|
||||
const INIT_TICKET = {
|
||||
|
|
@ -64,6 +65,7 @@ const ModalTerminal = ({
|
|||
scenarios,
|
||||
selectedLines,
|
||||
listIos,
|
||||
listLicense,
|
||||
}: {
|
||||
opened: boolean;
|
||||
onClose: () => void;
|
||||
|
|
@ -73,6 +75,7 @@ const ModalTerminal = ({
|
|||
scenarios: IScenario[];
|
||||
selectedLines: TLine[];
|
||||
listIos: string[];
|
||||
listLicense: string[];
|
||||
}) => {
|
||||
const user = useMemo(() => {
|
||||
return localStorage.getItem("user") &&
|
||||
|
|
@ -92,6 +95,7 @@ const ModalTerminal = ({
|
|||
const [isClearKeepScrollBack, setIsClearKeepScrollBack] =
|
||||
useState<boolean>(false);
|
||||
const [openSelectIos, setOpenSelectIos] = useState<boolean>(false);
|
||||
const [openSelectLicense, setOpenSelectLicense] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (opened && line?.tickets && line?.tickets?.length > 0) {
|
||||
|
|
@ -1214,9 +1218,11 @@ const ModalTerminal = ({
|
|||
disabled={true}
|
||||
fw={400}
|
||||
variant="outline"
|
||||
color="green"
|
||||
color="yellow"
|
||||
size="xs"
|
||||
onClick={() => {}}
|
||||
onClick={() => {
|
||||
setOpenSelectLicense(true);
|
||||
}}
|
||||
>
|
||||
Select License
|
||||
</Button>
|
||||
|
|
@ -1498,6 +1504,17 @@ const ModalTerminal = ({
|
|||
listIos={listIos}
|
||||
line={line}
|
||||
/>
|
||||
|
||||
<ModalSelectLicense
|
||||
close={() => {
|
||||
setOpenSelectLicense(false);
|
||||
}}
|
||||
opened={openSelectLicense}
|
||||
socket={socket}
|
||||
station={stationItem}
|
||||
listLicense={listLicense}
|
||||
line={line}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue