diff --git a/config/etc/default/sshsvc.yaml b/config/etc/default/sshsvc.yaml index 715a323c..c2b93bfd 100644 --- a/config/etc/default/sshsvc.yaml +++ b/config/etc/default/sshsvc.yaml @@ -32,7 +32,7 @@ sshd: userName: manager password: pass123 authType: local - tagNE: hlr + tagNE: omc # authType: local/omc telnetServer: @@ -45,7 +45,7 @@ telnetServer: userName: manager password: pass123 authType: local - tagNE: hlr + tagNE: omc # authproto: NoAuth/MD5/SHA # privProto: NoPriv/DES/AES/AES192/AES256 @@ -63,7 +63,7 @@ snmpServer: trapBool: false trapTick: 60 timeOut: 5 - trapTarget: "2001:db8::9219" + trapTarget: "" database: type: mysql diff --git a/database/common/mml_http_map.sql b/database/common/mml_http_map.sql index 92c47b2f..6f34500b 100644 --- a/database/common/mml_http_map.sql +++ b/database/common/mml_http_map.sql @@ -41,20 +41,20 @@ CREATE TABLE `mml_http_map` ( -- Records of mml_http_map -- ---------------------------- INSERT INTO `mml_http_map` VALUES (1, 'OMC', 'dsp', 'sysinfo', 'Get', '/api/rest/systemManagement/v1/sysInfo', '/%s', NULL, NULL, '{}', '{\r\n \"retFmt\": \"GetNF\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"title\": \"NE System Information\",\r\n \"singleList\": true,\r\n \"sepSpaceNum\": 2,\r\n \"alignmentM\": \"Left\",\r\n \"alignmentSN\": \"Right\",\r\n \"alignmentSV\": \"Left\",\r\n \"cols\": [\r\n {\r\n \"name\": \"neType\",\r\n \"display\": \"NE type\",\r\n \"length\": 10\r\n },\r\n {\r\n \"name\": \"neId\",\r\n \"display\": \"NE ID\",\r\n \"length\": 28\r\n }, \r\n {\r\n \"name\": \"hostName\",\r\n \"display\": \"Host name\",\r\n \"length\": 16\r\n },\r\n {\r\n \"name\": \"osInfo\",\r\n \"display\": \"OS information\",\r\n \"length\": 128\r\n },\r\n {\r\n \"name\": \"dbInfo\",\r\n \"display\": \"Database information\",\r\n \"length\": 80\r\n },\r\n {\r\n \"name\": \"version\",\r\n \"display\": \"Software version\",\r\n \"length\": 12\r\n },\r\n {\r\n \"name\": \"ipAddr\",\r\n \"display\": \"IP address\",\r\n \"length\": 20\r\n },\r\n {\r\n \"name\": \"port\",\r\n \"display\": \"Port\",\r\n \"length\": 6\r\n },\r\n {\r\n \"name\": \"cpus\",\r\n \"display\": \"CPUs\",\r\n \"length\": 4\r\n },\r\n {\r\n \"name\": \"totalMem\",\r\n \"display\": \"Total memory(KB)\",\r\n \"length\": 11\r\n } \r\n ],\r\n \"end\": \"(Number of results = %d)\\n\\n\"\r\n}'); -INSERT INTO `mml_http_map` VALUES (2, 'OMC', 'lst', 'memap', 'Get', '/api/rest/dataManagement/v1/tenants_db/ne_info', NULL, NULL, '?loc=', '{}', '{\r\n \"retFmt\": \"GetDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"title\": \"Managed Element Map\",\r\n \"singleList\": true,\r\n \"sepSpaceNum\": 2,\r\n \"alignmentM\": \"Left\",\r\n \"alignmentSN\": \"Right\",\r\n \"alignmentSV\": \"Left\",\r\n \"cols\": [\r\n {\r\n \"name\": \"rm_uid\",\r\n \"display\": \"Resource management UID\",\r\n \"length\": 28\r\n },\r\n {\r\n \"name\": \"ne_name\",\r\n \"display\": \"NE name\",\r\n \"length\": 28\r\n }\r\n ],\r\n \"end\": \"(Number of results = %d)\\n\\n\"\r\n}'); -INSERT INTO `mml_http_map` VALUES (3, 'OMC', 'lst', 'neinfo', 'Get', '/api/rest/dataManagement/v1/tenants_db/ne_info', NULL, NULL, '?loc=', '{}', '{\r\n \"retFmt\": \"GetDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"title\": \"Network element information\",\r\n \"singleList\": true,\r\n \"sepSpaceNum\": 2,\r\n \"alignmentM\": \"Left\",\r\n \"alignmentSN\": \"Right\",\r\n \"alignmentSV\": \"Left\",\r\n \"cols\": [\r\n {\r\n \"name\": \"ne_type\",\r\n \"display\": \"NE type\",\r\n \"length\": 10\r\n },\r\n {\r\n \"name\": \"ne_id\",\r\n \"display\": \"NE ID\",\r\n \"length\": 16\r\n },\r\n {\r\n \"name\": \"rm_uid\",\r\n \"display\": \"Resource management UID\",\r\n \"length\": 28\r\n },\r\n {\r\n \"name\": \"ne_name\",\r\n \"display\": \"NE name\",\r\n \"length\": 28\r\n },\r\n {\r\n \"name\": \"pv_flag\",\r\n \"display\": \"PV flag\",\r\n \"length\": 10\r\n },\r\n {\r\n \"name\": \"ip\",\r\n \"display\": \"IP address\",\r\n \"length\": 32\r\n },\r\n {\r\n \"name\": \"port\",\r\n \"display\": \"Port\",\r\n \"length\": 6\r\n },\r\n {\r\n \"name\": \"status\",\r\n \"display\": \"Status\",\r\n \"length\": 10,\r\n \"alias\": [\r\n \"online\",\r\n \"offline\",\r\n \"standby\",\r\n \"maintain\"\r\n ]\r\n }\r\n ],\r\n \"end\": \"(Number of results = %d)\\n\\n\"\r\n}\r\n'); -INSERT INTO `mml_http_map` VALUES (4, 'OMC', 'add', 'neinfo', 'Post', '/api/rest/dataManagement/v1/tenants_db/ne_info', NULL, NULL, '', '{\"bodyFmt\":\"PostDB\", \"bodyKey\":\"ne_info\"}', '{\r\n \"retFmt\": \"PostDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"cols\": [\r\n {\r\n \"name\": \"affectedRows\",\r\n \"display\": \"Affected rows\",\r\n \"length\": 11\r\n }\r\n ]\r\n}\r\n'); -INSERT INTO `mml_http_map` VALUES (5, 'OMC', 'del', 'neinfo', 'Delete', '/api/rest/dataManagement/v1/tenants_db/ne_info', NULL, NULL, '?loc=', '{}', '{\r\n \"retFmt\": \"DeleteDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"cols\": [\r\n {\r\n \"name\": \"affectedRows\",\r\n \"display\": \"Affected rows\",\r\n \"length\": 11\r\n }\r\n ]\r\n}'); -INSERT INTO `mml_http_map` VALUES (6, 'OMC', 'mod', 'neinfo', 'Put', '/api/rest/dataManagement/v1/tenants_db/ne_info', NULL, NULL, '?loc=', '{\"bodyFmt\":\"PutDB\", \"bodyKey\":\"ne_info\"}', '{\r\n \"retFmt\": \"PutDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"cols\": [\r\n {\r\n \"name\": \"affectedRows\",\r\n \"display\": \"Affected rows\",\r\n \"length\": 11\r\n }\r\n ]\r\n}'); -INSERT INTO `mml_http_map` VALUES (7, 'OMC', 'dsp', 'alarm', 'Get', '/api/rest/dataManagement/v1/tenants_db/alarm', NULL, NULL, '?loc=', '{}', '{\r\n \"retFmt\": \"GetDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"title\": \"Alarm Information\",\r\n \"singleList\": true,\r\n \"sepSpaceNum\": 2,\r\n \"alignmentM\": \"Left\",\r\n \"alignmentSN\": \"Right\",\r\n \"alignmentSV\": \"Left\",\r\n \"cols\": [\r\n {\r\n \"name\": \"ne_type\",\r\n \"display\": \"NE type\",\r\n \"length\": 10\r\n },\r\n {\r\n \"name\": \"ne_id\",\r\n \"display\": \"NE UID\",\r\n \"length\": 28\r\n },\r\n {\r\n \"name\": \"ne_name\",\r\n \"display\": \"NE name\",\r\n \"length\": 28\r\n },\r\n {\r\n \"name\": \"alarm_seq\",\r\n \"display\": \"Alarm sequence\",\r\n \"length\": 11\r\n },\r\n {\r\n \"name\": \"alarm_title\",\r\n \"display\": \"Alarm title\",\r\n \"length\": 30\r\n }, \r\n {\r\n \"name\": \"orig_severity\",\r\n \"display\": \"Original severity\",\r\n \"length\": 11 \r\n },\r\n {\r\n \"name\": \"pv_flag\",\r\n \"display\": \"PV flag\",\r\n \"length\": 10\r\n },\r\n {\r\n \"name\": \"event_time\",\r\n \"display\": \"Event time\",\r\n \"length\": 20\r\n }\r\n ],\r\n \"end\": \"(Number of results = %d)\\n\\n\"\r\n}'); -INSERT INTO `mml_http_map` VALUES (8, 'OMC', 'lst', 'measuretask', 'Get', '/api/rest/dataManagement/v1/tenants_db/measure_task', NULL, NULL, '?loc=', '{}', '{\r\n \"retFmt\": \"GetDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"title\": \"Performance Task Information\",\r\n \"singleList\": true,\r\n \"sepSpaceNum\": 2,\r\n \"alignmentM\": \"Left\",\r\n \"alignmentSN\": \"Right\",\r\n \"alignmentSV\": \"Left\",\r\n \"cols\": [\r\n {\r\n \"name\": \"id\",\r\n \"display\": \"Task ID\",\r\n \"length\": 11\r\n },\r\n {\r\n \"name\": \"ne_type\",\r\n \"display\": \"NE type\",\r\n \"length\": 10\r\n },\r\n {\r\n \"name\": \"ne_ids\",\r\n \"display\": \"NE ID Set\",\r\n \"length\": 28\r\n },\r\n {\r\n \"name\": \"granul_option\",\r\n \"display\": \"Time granulity\",\r\n \"length\": 5\r\n },\r\n {\r\n \"name\": \"kpi_set\",\r\n \"display\": \"KPI set\",\r\n \"length\": 60\r\n },\r\n {\r\n \"name\": \"start_time\",\r\n \"display\": \"Start time\",\r\n \"length\": 20\r\n },\r\n {\r\n \"name\": \"end_time\",\r\n \"display\": \"End time\",\r\n \"length\": 20\r\n },\r\n {\r\n \"name\": \"status\",\r\n \"display\": \"Status\",\r\n \"length\": 8\r\n }\r\n ],\r\n \"end\": \"(Number of results = %d)\\n\\n\"\r\n}'); -INSERT INTO `mml_http_map` VALUES (9, 'OMC', 'add', 'measuretask', 'Post', '/api/rest/dataManagement/v1/tenants_db/measure_task', NULL, NULL, '', '{\"bodyFmt\":\"PostDB\", \"bodyKey\":\"measure_task\"}', '{\r\n \"retFmt\": \"PostDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"cols\": [\r\n {\r\n \"name\": \"affectedRows\",\r\n \"display\": \"Affected rows\",\r\n \"length\": 11\r\n }\r\n ]\r\n}\r\n'); -INSERT INTO `mml_http_map` VALUES (10, 'OMC', 'del', 'measuretask', 'Delete', '/api/rest/dataManagement/v1/tenants_db/measure_task', NULL, NULL, '?loc=', '{}', '{\r\n \"retFmt\": \"DeleteDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"cols\": [\r\n {\r\n \"name\": \"affectedRows\",\r\n \"display\": \"Affected rows\",\r\n \"length\": 11\r\n }\r\n ]\r\n}'); -INSERT INTO `mml_http_map` VALUES (11, 'OMC', 'mod', 'measuretask', 'Put', '/api/rest/dataManagement/v1/tenants_db/measure_task', NULL, NULL, '?loc=', '{\"bodyFmt\":\"PutDB\", \"bodyKey\":\"measure_task\"}', '{\r\n \"retFmt\": \"PutDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"cols\": [\r\n {\r\n \"name\": \"affectedRows\",\r\n \"display\": \"Affected rows\",\r\n \"length\": 11\r\n }\r\n ]\r\n}'); -INSERT INTO `mml_http_map` VALUES (12, 'OMC', 'lst', 'measuredata', 'Get', '/api/rest/dataManagement/v1/tenants_db/measure_data', NULL, NULL, '?loc=', '{}', '{\r\n \"retFmt\": \"GetDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"title\": \"Performance Measure Data\",\r\n \"singleList\": true,\r\n \"sepSpaceNum\": 2,\r\n \"alignmentM\": \"Left\",\r\n \"alignmentSN\": \"Right\",\r\n \"alignmentSV\": \"Left\",\r\n \"cols\": [\r\n {\r\n \"name\": \"task_id\",\r\n \"display\": \"Task ID\",\r\n \"length\": 11\r\n },\r\n {\r\n \"name\": \"ne_type\",\r\n \"display\": \"NE type\",\r\n \"length\": 10\r\n },\r\n {\r\n \"name\": \"rm_uid\",\r\n \"display\": \"Resource management UID\",\r\n \"length\": 28\r\n },\r\n {\r\n \"name\": \"ne_name\",\r\n \"display\": \"NE name\",\r\n \"length\": 28\r\n }, \r\n {\r\n \"name\": \"granul_option\",\r\n \"display\": \"Time granulity\",\r\n \"length\": 5\r\n },\r\n {\r\n \"name\": \"kpi_id\",\r\n \"display\": \"KPI ID\",\r\n \"length\": 32\r\n },\r\n {\r\n \"name\": \"start_time\",\r\n \"display\": \"Start time\",\r\n \"length\": 20\r\n },\r\n {\r\n \"name\": \"end_time\",\r\n \"display\": \"End time\",\r\n \"length\": 20\r\n },\r\n {\r\n \"name\": \"value\",\r\n \"display\": \"value\",\r\n \"length\": 11\r\n }\r\n ],\r\n \"end\": \"(Number of results = %d)\\n\\n\"\r\n}'); -INSERT INTO `mml_http_map` VALUES (13, 'OMC', 'lst', 'operationlog', 'Get', '/api/rest/dataManagement/v1/tenants_db/operation_log', NULL, NULL, '?loc=', '{}', '{\r\n \"retFmt\": \"GetDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"title\": \"Operation Log\",\r\n \"singleList\": true,\r\n \"sepSpaceNum\": 2,\r\n \"alignmentM\": \"Left\",\r\n \"alignmentSN\": \"Right\",\r\n \"alignmentSV\": \"Left\",\r\n \"cols\": [\r\n {\r\n \"name\": \"account_name\",\r\n \"display\": \"Account ID\",\r\n \"length\": 10\r\n },\r\n {\r\n \"name\": \"op_ip\",\r\n \"display\": \"Source IP address\",\r\n \"length\": 20\r\n },\r\n {\r\n \"name\": \"op_type\",\r\n \"display\": \"Opration type\",\r\n \"length\": 12\r\n },\r\n {\r\n \"name\": \"op_content\",\r\n \"display\": \"Operation content\",\r\n \"length\": 50\r\n },\r\n {\r\n \"name\": \"op_result\",\r\n \"display\": \"Operation result\",\r\n \"length\": 20\r\n },\r\n {\r\n \"name\": \"log_time\",\r\n \"display\": \"Log time\",\r\n \"length\": 20\r\n }\r\n ],\r\n \"end\": \"(Number of results = %d)\\n\\n\"\r\n}'); -INSERT INTO `mml_http_map` VALUES (14, 'OMC', 'lst', 'securitylog', 'Get', '/api/rest/dataManagement/v1/tenants_db/security_log', NULL, NULL, '?loc=', '{}', '{\r\n \"retFmt\": \"GetDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"title\": \"Security Log\",\r\n \"singleList\": true,\r\n \"sepSpaceNum\": 2,\r\n \"alignmentM\": \"Left\",\r\n \"alignmentSN\": \"Right\",\r\n \"alignmentSV\": \"Left\",\r\n \"cols\": [\r\n {\r\n \"name\": \"account_name\",\r\n \"display\": \"Account ID\",\r\n \"length\": 10\r\n },\r\n {\r\n \"name\": \"op_ip\",\r\n \"display\": \"Source IP address\",\r\n \"length\": 20\r\n },\r\n {\r\n \"name\": \"op_type\",\r\n \"display\": \"Opration type\",\r\n \"length\": 12\r\n },\r\n {\r\n \"name\": \"op_content\",\r\n \"display\": \"Operation content\",\r\n \"length\": 50\r\n },\r\n {\r\n \"name\": \"op_result\",\r\n \"display\": \"Operation result\",\r\n \"length\": 20\r\n },\r\n {\r\n \"name\": \"op_time\",\r\n \"display\": \"Operation log time\",\r\n \"length\": 20\r\n }\r\n ],\r\n \"end\": \"(Number of results = %d)\\n\\n\"\r\n}'); -INSERT INTO `mml_http_map` VALUES (15, 'OMC', 'lst', 'alarmlog', 'Get', '/api/rest/dataManagement/v1/tenants_db/alarm_log', NULL, NULL, '?loc=', '{}', '{\r\n \"retFmt\": \"GetDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"title\": \"Alarm Log\",\r\n \"singleList\": true,\r\n \"sepSpaceNum\": 2,\r\n \"alignmentM\": \"Left\",\r\n \"alignmentSN\": \"Right\",\r\n \"alignmentSV\": \"Left\",\r\n \"cols\": [\r\n {\r\n \"name\": \"ne_type\",\r\n \"display\": \"NE type\",\r\n \"length\": 8\r\n },\r\n {\r\n \"name\": \"ne_id\",\r\n \"display\": \"NE UID\",\r\n \"length\": 28\r\n },\r\n {\r\n \"name\": \"alarm_seq\",\r\n \"display\": \"Alarm sequence\",\r\n \"length\": 12\r\n },\r\n {\r\n \"name\": \"alarm_id\",\r\n \"display\": \"Alarm ID\",\r\n \"length\": 20\r\n }, \r\n {\r\n \"name\": \"event_time\",\r\n \"display\": \"Alarm event time\",\r\n \"length\": 20\r\n },\r\n {\r\n \"name\": \"log_time\",\r\n \"display\": \"Log time\",\r\n \"length\": 20\r\n }\r\n ],\r\n \"end\": \"(Number of results = %d)\\n\\n\"\r\n}'); +INSERT INTO `mml_http_map` VALUES (2, 'OMC', 'lst', 'memap', 'Get', '/api/rest/dataManagement/v1/omc_db/ne_info', NULL, NULL, '?loc=', '{}', '{\r\n \"retFmt\": \"GetDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"title\": \"Managed Element Map\",\r\n \"singleList\": true,\r\n \"sepSpaceNum\": 2,\r\n \"alignmentM\": \"Left\",\r\n \"alignmentSN\": \"Right\",\r\n \"alignmentSV\": \"Left\",\r\n \"cols\": [\r\n {\r\n \"name\": \"rm_uid\",\r\n \"display\": \"Resource management UID\",\r\n \"length\": 28\r\n },\r\n {\r\n \"name\": \"ne_name\",\r\n \"display\": \"NE name\",\r\n \"length\": 28\r\n }\r\n ],\r\n \"end\": \"(Number of results = %d)\\n\\n\"\r\n}'); +INSERT INTO `mml_http_map` VALUES (3, 'OMC', 'lst', 'neinfo', 'Get', '/api/rest/dataManagement/v1/omc_db/ne_info', NULL, NULL, '?loc=', '{}', '{\r\n \"retFmt\": \"GetDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"title\": \"Network element information\",\r\n \"singleList\": true,\r\n \"sepSpaceNum\": 2,\r\n \"alignmentM\": \"Left\",\r\n \"alignmentSN\": \"Right\",\r\n \"alignmentSV\": \"Left\",\r\n \"cols\": [\r\n {\r\n \"name\": \"ne_type\",\r\n \"display\": \"NE type\",\r\n \"length\": 10\r\n },\r\n {\r\n \"name\": \"ne_id\",\r\n \"display\": \"NE ID\",\r\n \"length\": 16\r\n },\r\n {\r\n \"name\": \"rm_uid\",\r\n \"display\": \"Resource management UID\",\r\n \"length\": 28\r\n },\r\n {\r\n \"name\": \"ne_name\",\r\n \"display\": \"NE name\",\r\n \"length\": 28\r\n },\r\n {\r\n \"name\": \"pv_flag\",\r\n \"display\": \"PV flag\",\r\n \"length\": 10\r\n },\r\n {\r\n \"name\": \"ip\",\r\n \"display\": \"IP address\",\r\n \"length\": 32\r\n },\r\n {\r\n \"name\": \"port\",\r\n \"display\": \"Port\",\r\n \"length\": 6\r\n },\r\n {\r\n \"name\": \"status\",\r\n \"display\": \"Status\",\r\n \"length\": 10,\r\n \"alias\": [\r\n \"offline\",\r\n \"online\",\r\n \"standby\",\r\n \"maintain\"\r\n ]\r\n }\r\n ],\r\n \"end\": \"(Number of results = %d)\\n\\n\"\r\n}\r\n'); +INSERT INTO `mml_http_map` VALUES (4, 'OMC', 'add', 'neinfo', 'Post', '/api/rest/dataManagement/v1/omc_db/ne_info', NULL, NULL, '', '{\"bodyFmt\":\"PostDB\", \"bodyKey\":\"ne_info\"}', '{\r\n \"retFmt\": \"PostDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"cols\": [\r\n {\r\n \"name\": \"affectedRows\",\r\n \"display\": \"Affected rows\",\r\n \"length\": 11\r\n }\r\n ]\r\n}\r\n'); +INSERT INTO `mml_http_map` VALUES (5, 'OMC', 'del', 'neinfo', 'Delete', '/api/rest/dataManagement/v1/omc_db/ne_info', NULL, NULL, '?loc=', '{}', '{\r\n \"retFmt\": \"DeleteDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"cols\": [\r\n {\r\n \"name\": \"affectedRows\",\r\n \"display\": \"Affected rows\",\r\n \"length\": 11\r\n }\r\n ]\r\n}'); +INSERT INTO `mml_http_map` VALUES (6, 'OMC', 'mod', 'neinfo', 'Put', '/api/rest/dataManagement/v1/omc_db/ne_info', NULL, NULL, '?loc=', '{\"bodyFmt\":\"PutDB\", \"bodyKey\":\"ne_info\"}', '{\r\n \"retFmt\": \"PutDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"cols\": [\r\n {\r\n \"name\": \"affectedRows\",\r\n \"display\": \"Affected rows\",\r\n \"length\": 11\r\n }\r\n ]\r\n}'); +INSERT INTO `mml_http_map` VALUES (7, 'OMC', 'dsp', 'alarm', 'Get', '/api/rest/dataManagement/v1/omc_db/alarm', NULL, NULL, '?loc=', '{}', '{\r\n \"retFmt\": \"GetDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"title\": \"Alarm Information\",\r\n \"singleList\": true,\r\n \"sepSpaceNum\": 2,\r\n \"alignmentM\": \"Left\",\r\n \"alignmentSN\": \"Right\",\r\n \"alignmentSV\": \"Left\",\r\n \"cols\": [\r\n {\r\n \"name\": \"ne_type\",\r\n \"display\": \"NE type\",\r\n \"length\": 10\r\n },\r\n {\r\n \"name\": \"ne_id\",\r\n \"display\": \"NE UID\",\r\n \"length\": 28\r\n },\r\n {\r\n \"name\": \"ne_name\",\r\n \"display\": \"NE name\",\r\n \"length\": 28\r\n },\r\n {\r\n \"name\": \"alarm_seq\",\r\n \"display\": \"Alarm sequence\",\r\n \"length\": 11\r\n },\r\n {\r\n \"name\": \"alarm_title\",\r\n \"display\": \"Alarm title\",\r\n \"length\": 30\r\n }, \r\n {\r\n \"name\": \"orig_severity\",\r\n \"display\": \"Original severity\",\r\n \"length\": 11 \r\n },\r\n {\r\n \"name\": \"pv_flag\",\r\n \"display\": \"PV flag\",\r\n \"length\": 10\r\n },\r\n {\r\n \"name\": \"event_time\",\r\n \"display\": \"Event time\",\r\n \"length\": 20\r\n }\r\n ],\r\n \"end\": \"(Number of results = %d)\\n\\n\"\r\n}'); +INSERT INTO `mml_http_map` VALUES (8, 'OMC', 'lst', 'measuretask', 'Get', '/api/rest/dataManagement/v1/omc_db/measure_task', NULL, NULL, '?loc=', '{}', '{\r\n \"retFmt\": \"GetDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"title\": \"Performance Task Information\",\r\n \"singleList\": true,\r\n \"sepSpaceNum\": 2,\r\n \"alignmentM\": \"Left\",\r\n \"alignmentSN\": \"Right\",\r\n \"alignmentSV\": \"Left\",\r\n \"cols\": [\r\n {\r\n \"name\": \"id\",\r\n \"display\": \"Task ID\",\r\n \"length\": 11\r\n },\r\n {\r\n \"name\": \"ne_type\",\r\n \"display\": \"NE type\",\r\n \"length\": 10\r\n },\r\n {\r\n \"name\": \"ne_ids\",\r\n \"display\": \"NE ID Set\",\r\n \"length\": 28\r\n },\r\n {\r\n \"name\": \"granul_option\",\r\n \"display\": \"Time granulity\",\r\n \"length\": 5\r\n },\r\n {\r\n \"name\": \"kpi_set\",\r\n \"display\": \"KPI set\",\r\n \"length\": 60\r\n },\r\n {\r\n \"name\": \"start_time\",\r\n \"display\": \"Start time\",\r\n \"length\": 20\r\n },\r\n {\r\n \"name\": \"end_time\",\r\n \"display\": \"End time\",\r\n \"length\": 20\r\n },\r\n {\r\n \"name\": \"status\",\r\n \"display\": \"Status\",\r\n \"length\": 8\r\n }\r\n ],\r\n \"end\": \"(Number of results = %d)\\n\\n\"\r\n}'); +INSERT INTO `mml_http_map` VALUES (9, 'OMC', 'add', 'measuretask', 'Post', '/api/rest/dataManagement/v1/omc_db/measure_task', NULL, NULL, '', '{\"bodyFmt\":\"PostDB\", \"bodyKey\":\"measure_task\"}', '{\r\n \"retFmt\": \"PostDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"cols\": [\r\n {\r\n \"name\": \"affectedRows\",\r\n \"display\": \"Affected rows\",\r\n \"length\": 11\r\n }\r\n ]\r\n}\r\n'); +INSERT INTO `mml_http_map` VALUES (10, 'OMC', 'del', 'measuretask', 'Delete', '/api/rest/dataManagement/v1/omc_db/measure_task', NULL, NULL, '?loc=', '{}', '{\r\n \"retFmt\": \"DeleteDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"cols\": [\r\n {\r\n \"name\": \"affectedRows\",\r\n \"display\": \"Affected rows\",\r\n \"length\": 11\r\n }\r\n ]\r\n}'); +INSERT INTO `mml_http_map` VALUES (11, 'OMC', 'mod', 'measuretask', 'Put', '/api/rest/dataManagement/v1/omc_db/measure_task', NULL, NULL, '?loc=', '{\"bodyFmt\":\"PutDB\", \"bodyKey\":\"measure_task\"}', '{\r\n \"retFmt\": \"PutDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"cols\": [\r\n {\r\n \"name\": \"affectedRows\",\r\n \"display\": \"Affected rows\",\r\n \"length\": 11\r\n }\r\n ]\r\n}'); +INSERT INTO `mml_http_map` VALUES (12, 'OMC', 'lst', 'measuredata', 'Get', '/api/rest/dataManagement/v1/omc_db/measure_data', NULL, NULL, '?loc=', '{}', '{\r\n \"retFmt\": \"GetDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"title\": \"Performance Measure Data\",\r\n \"singleList\": true,\r\n \"sepSpaceNum\": 2,\r\n \"alignmentM\": \"Left\",\r\n \"alignmentSN\": \"Right\",\r\n \"alignmentSV\": \"Left\",\r\n \"cols\": [\r\n {\r\n \"name\": \"task_id\",\r\n \"display\": \"Task ID\",\r\n \"length\": 11\r\n },\r\n {\r\n \"name\": \"ne_type\",\r\n \"display\": \"NE type\",\r\n \"length\": 10\r\n },\r\n {\r\n \"name\": \"rm_uid\",\r\n \"display\": \"Resource management UID\",\r\n \"length\": 28\r\n },\r\n {\r\n \"name\": \"ne_name\",\r\n \"display\": \"NE name\",\r\n \"length\": 28\r\n }, \r\n {\r\n \"name\": \"granul_option\",\r\n \"display\": \"Time granulity\",\r\n \"length\": 5\r\n },\r\n {\r\n \"name\": \"kpi_id\",\r\n \"display\": \"KPI ID\",\r\n \"length\": 32\r\n },\r\n {\r\n \"name\": \"start_time\",\r\n \"display\": \"Start time\",\r\n \"length\": 20\r\n },\r\n {\r\n \"name\": \"end_time\",\r\n \"display\": \"End time\",\r\n \"length\": 20\r\n },\r\n {\r\n \"name\": \"value\",\r\n \"display\": \"value\",\r\n \"length\": 11\r\n }\r\n ],\r\n \"end\": \"(Number of results = %d)\\n\\n\"\r\n}'); +INSERT INTO `mml_http_map` VALUES (13, 'OMC', 'lst', 'operationlog', 'Get', '/api/rest/dataManagement/v1/omc_db/operation_log', NULL, NULL, '?loc=', '{}', '{\r\n \"retFmt\": \"GetDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"title\": \"Operation Log\",\r\n \"singleList\": true,\r\n \"sepSpaceNum\": 2,\r\n \"alignmentM\": \"Left\",\r\n \"alignmentSN\": \"Right\",\r\n \"alignmentSV\": \"Left\",\r\n \"cols\": [\r\n {\r\n \"name\": \"account_name\",\r\n \"display\": \"Account ID\",\r\n \"length\": 10\r\n },\r\n {\r\n \"name\": \"op_ip\",\r\n \"display\": \"Source IP address\",\r\n \"length\": 20\r\n },\r\n {\r\n \"name\": \"op_type\",\r\n \"display\": \"Opration type\",\r\n \"length\": 12\r\n },\r\n {\r\n \"name\": \"op_content\",\r\n \"display\": \"Operation content\",\r\n \"length\": 50\r\n },\r\n {\r\n \"name\": \"op_result\",\r\n \"display\": \"Operation result\",\r\n \"length\": 20\r\n },\r\n {\r\n \"name\": \"log_time\",\r\n \"display\": \"Log time\",\r\n \"length\": 20\r\n }\r\n ],\r\n \"end\": \"(Number of results = %d)\\n\\n\"\r\n}'); +INSERT INTO `mml_http_map` VALUES (14, 'OMC', 'lst', 'securitylog', 'Get', '/api/rest/dataManagement/v1/omc_db/security_log', NULL, NULL, '?loc=', '{}', '{\r\n \"retFmt\": \"GetDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"title\": \"Security Log\",\r\n \"singleList\": true,\r\n \"sepSpaceNum\": 2,\r\n \"alignmentM\": \"Left\",\r\n \"alignmentSN\": \"Right\",\r\n \"alignmentSV\": \"Left\",\r\n \"cols\": [\r\n {\r\n \"name\": \"account_name\",\r\n \"display\": \"Account ID\",\r\n \"length\": 10\r\n },\r\n {\r\n \"name\": \"op_ip\",\r\n \"display\": \"Source IP address\",\r\n \"length\": 20\r\n },\r\n {\r\n \"name\": \"op_type\",\r\n \"display\": \"Opration type\",\r\n \"length\": 12\r\n },\r\n {\r\n \"name\": \"op_content\",\r\n \"display\": \"Operation content\",\r\n \"length\": 50\r\n },\r\n {\r\n \"name\": \"op_result\",\r\n \"display\": \"Operation result\",\r\n \"length\": 20\r\n },\r\n {\r\n \"name\": \"op_time\",\r\n \"display\": \"Operation log time\",\r\n \"length\": 20\r\n }\r\n ],\r\n \"end\": \"(Number of results = %d)\\n\\n\"\r\n}'); +INSERT INTO `mml_http_map` VALUES (15, 'OMC', 'lst', 'alarmlog', 'Get', '/api/rest/dataManagement/v1/omc_db/alarm_log', NULL, NULL, '?loc=', '{}', '{\r\n \"retFmt\": \"GetDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"title\": \"Alarm Log\",\r\n \"singleList\": true,\r\n \"sepSpaceNum\": 2,\r\n \"alignmentM\": \"Left\",\r\n \"alignmentSN\": \"Right\",\r\n \"alignmentSV\": \"Left\",\r\n \"cols\": [\r\n {\r\n \"name\": \"ne_type\",\r\n \"display\": \"NE type\",\r\n \"length\": 8\r\n },\r\n {\r\n \"name\": \"ne_id\",\r\n \"display\": \"NE UID\",\r\n \"length\": 28\r\n },\r\n {\r\n \"name\": \"alarm_seq\",\r\n \"display\": \"Alarm sequence\",\r\n \"length\": 12\r\n },\r\n {\r\n \"name\": \"alarm_id\",\r\n \"display\": \"Alarm ID\",\r\n \"length\": 20\r\n }, \r\n {\r\n \"name\": \"event_time\",\r\n \"display\": \"Alarm event time\",\r\n \"length\": 20\r\n },\r\n {\r\n \"name\": \"log_time\",\r\n \"display\": \"Log time\",\r\n \"length\": 20\r\n }\r\n ],\r\n \"end\": \"(Number of results = %d)\\n\\n\"\r\n}'); INSERT INTO `mml_http_map` VALUES (16, 'OMC', 'dsp', 'licenseinfo', 'Get', '/api/rest/systemManagement/v1/licenseInfo', '/%s', NULL, NULL, '{}', '{\r\n \"retFmt\": \"GetNF\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"title\": \"NE License Information\",\r\n \"singleList\": true,\r\n \"sepSpaceNum\": 2,\r\n \"alignmentM\": \"Left\",\r\n \"alignmentSN\": \"Right\",\r\n \"alignmentSV\": \"Left\",\r\n \"cols\": [\r\n {\r\n \"name\": \"neType\",\r\n \"display\": \"NE type\",\r\n \"length\": 10\r\n },\r\n {\r\n \"name\": \"neId\",\r\n \"display\": \"NE ID\",\r\n \"length\": 20\r\n },\r\n {\r\n \"name\": \"serialNum\",\r\n \"display\": \"Serial No\",\r\n \"length\": 12\r\n },\r\n {\r\n \"name\": \"capability\",\r\n \"display\": \"License capability\",\r\n \"length\": 11\r\n },\r\n {\r\n \"name\": \"capUsed\",\r\n \"display\": \"License used\",\r\n \"length\": 11\r\n }, \r\n {\r\n \"name\": \"featureEnabled\",\r\n \"display\": \"Feature enabled\",\r\n \"length\": 28\r\n },\r\n {\r\n \"name\": \"expiryDate\",\r\n \"display\": \"License expiry date\",\r\n \"length\": 20\r\n }\r\n ],\r\n \"end\": \"(Number of results = %d)\\n\\n\"\r\n}'); INSERT INTO `mml_http_map` VALUES (17, 'OMC', 'lst', 'systemlog', 'Get', '/api/rest/dataManagement/v1/tenants_db/system_log', NULL, NULL, '?loc=', '{}', '{\r\n \"retFmt\": \"GetDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"title\": \"System Log\",\r\n \"singleList\": true,\r\n \"sepSpaceNum\": 2,\r\n \"alignmentM\": \"Left\",\r\n \"alignmentSN\": \"Right\",\r\n \"alignmentSV\": \"Left\",\r\n \"cols\": [\r\n {\r\n \"name\": \"process_type\",\r\n \"display\": \"Process type\",\r\n \"length\": 10\r\n },\r\n {\r\n \"name\": \"process_name\",\r\n \"display\": \"Process name\",\r\n \"length\": 28\r\n },\r\n {\r\n \"name\": \"user_name\",\r\n \"display\": \"User name\",\r\n \"length\": 12\r\n },\r\n {\r\n \"name\": \"process_id\",\r\n \"display\": \"Process ID\",\r\n \"length\": 12\r\n },\r\n {\r\n \"name\": \"event\",\r\n \"display\": \"Event\",\r\n \"length\": 20\r\n },\r\n {\r\n \"name\": \"start_time\",\r\n \"display\": \"Start time\",\r\n \"length\": 20\r\n },\r\n {\r\n \"name\": \"end_time\",\r\n \"display\": \"End time\",\r\n \"length\": 20\r\n }, \r\n {\r\n \"name\": \"log_time\",\r\n \"display\": \"Log time\",\r\n \"length\": 20\r\n }\r\n ],\r\n \"end\": \"(Number of results = %d)\\n\\n\"\r\n}'); INSERT INTO `mml_http_map` VALUES (18, 'OMC', 'lst', 'eventlog', 'Get', '/api/rest/dataManagement/v1/tenants_db/event_log', NULL, NULL, '?loc=', '{}', '{\r\n \"retFmt\": \"GetDB\",\r\n \"retMsg\": \"RetCode = %d operation succeeded\\n\\n\",\r\n \"errMsg\": \"ErrorCode = %d operation failed: %s\\n\\n\",\r\n \"title\": \"Event Log\",\r\n \"singleList\": true,\r\n \"sepSpaceNum\": 2,\r\n \"alignmentM\": \"Left\",\r\n \"alignmentSN\": \"Right\",\r\n \"alignmentSV\": \"Left\",\r\n \"cols\": [\r\n {\r\n \"name\": \"ne_type\",\r\n \"display\": \"NE type\",\r\n \"length\": 10\r\n },\r\n {\r\n \"name\": \"ne_id\",\r\n \"display\": \"NE ID\",\r\n \"length\": 28\r\n },\r\n {\r\n \"name\": \"event\",\r\n \"display\": \"Event\",\r\n \"length\": 12\r\n },\r\n {\r\n \"name\": \"event time\",\r\n \"display\": \"Event\",\r\n \"length\": 20\r\n },\r\n {\r\n \"name\": \"log_time\",\r\n \"display\": \"Log time\",\r\n \"length\": 20\r\n }\r\n ],\r\n \"end\": \"(Number of results = %d)\\n\\n\"\r\n}'); diff --git a/database/install/sys_dict_data1_i18n_zh.sql b/database/install/sys_dict_data1_i18n_zh.sql index 90f07fc7..8ee09c39 100644 --- a/database/install/sys_dict_data1_i18n_zh.sql +++ b/database/install/sys_dict_data1_i18n_zh.sql @@ -689,6 +689,8 @@ INSERT INTO `sys_dict_data` VALUES (2178, 2178, 'dictData.cdr_cause_code.41', ' INSERT INTO `sys_dict_data` VALUES (2179, 2179, 'dictData.cdr_cause_code.42', '拥塞', 'i18n_zh', '', '', '1', 'supervisor', 1725877564156, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (2180, 2180, 'dictData.cdr_cause_code.47', '资源不可用', 'i18n_zh', '', '', '1', 'supervisor', 1725877564156, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (2181, 2181, 'dictData.cdr_cause_code.50', '请求的设施未订阅', 'i18n_zh', '', '', '1', 'supervisor', 1725877564156, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2182, 2182, 'job.exportSMSCCDR', '定期从短信话单表导出文件至指定目录', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2183, 2183, 'job.removeExportedFiles', '定期删除指定目录过期文件', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); -- 多租户 INSERT INTO `sys_dict_data` VALUES (11000, 11000, 'menu.security.tenant', '租户管理', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); diff --git a/database/install/sys_dict_data2_i18n_en.sql b/database/install/sys_dict_data2_i18n_en.sql index 2b09acca..977cb16d 100644 --- a/database/install/sys_dict_data2_i18n_en.sql +++ b/database/install/sys_dict_data2_i18n_en.sql @@ -689,6 +689,8 @@ INSERT INTO `sys_dict_data` VALUES (4178, 4178, 'dictData.cdr_cause_code.41', 'T INSERT INTO `sys_dict_data` VALUES (4179, 4179, 'dictData.cdr_cause_code.42', 'Congestion', 'i18n_en', '', '', '1', 'supervisor', 1725877564156, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (4180, 4180, 'dictData.cdr_cause_code.47', 'Resources Unavailable Unspec', 'i18n_en', '', '', '1', 'supervisor', 1725877564156, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (4181, 4181, 'dictData.cdr_cause_code.50', 'Requested Facility Not Subscribed', 'i18n_en', '', '', '1', 'supervisor', 1725877564156, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4182, 4182, 'job.exportSMSCCDR', 'Export regularly from SMSC CDR table', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4183, 4183, 'job.removeExportedFiles', 'Regularly delete expired files in the specified directory', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); -- 多租户 INSERT INTO `sys_dict_data` VALUES (14000, 14000, 'menu.security.tenant', 'Tenant Management', 'i18n_en', '', '', '1', 'supervisor', 1705550000000, '', 0, ''); diff --git a/database/install/sys_job.sql b/database/install/sys_job.sql index 131ad511..8faeafbb 100644 --- a/database/install/sys_job.sql +++ b/database/install/sys_job.sql @@ -40,5 +40,7 @@ INSERT INTO `sys_job` VALUES (10, 'job.genNeStateAlarm', 'SYSTEM', 'genNeStateAl INSERT INTO `sys_job` VALUES (11, 'job.exportOperateLog', 'SYSTEM', 'exportTable', '{\"duration\":1,\"tableName\":\"sys_log_operate\",\"timeCol\":\"oper_time\",\"timeUnit\":\"milli\",\"columns\":\"oper_id,omc_get_dict_value(title, \\\"i18n_en\\\") as title,business_type,method,request_method,operator_type,oper_name,dept_name,oper_url,oper_ip,oper_location,oper_param,oper_msg,status,oper_time,cost_time,tenant_id\",\"extras\":\"\",\"filePath\":\"/usr/local/omc/backup/operate_log\"}', '0 0 0/1 * * ?', '3', '0', '1', '1', 'supervisor', 1698478134842, 'admin', 1724833786290, 'job.exportOperateLog'); INSERT INTO `sys_job` VALUES (12, 'job.exportIMSCDR', 'SYSTEM', 'exportTable', '{\"duration\":1,\"tableName\":\"cdr_event_ims\",\"columns\":\"id,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.recordType\')) as record_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.callType\')) as call_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.callerParty\')) as caller_party,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.calledParty\')) as called_party,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.callDuration\')) as call_duration,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.serviceResult\')) as service_result,DATE_FORMAT(FROM_UNIXTIME(timestamp), \'%Y-%m-%d %H:%i:%s\') AS timestamp\",\"timeCol\":\"timestamp\",\"timeUnit\":\"second\",\"extras\":\"\",\"filePath\":\"/usr/local/omc/backup/ims_cdr\"}', '0 0 0/1 * * ?', '3', '0', '1', '1', 'supervisor', 1698478134842, 'admin', 1722224659251, ''); INSERT INTO `sys_job` VALUES (13, 'job.exportSMFCDR', 'SYSTEM', 'exportTable', '{\"duration\":1,\"tableName\":\"cdr_event_smf\",\"columns\":\"id,ne_type,ne_name,rm_uid,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.recordType\')) AS record_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.chargingID\')) AS charging_id,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.subscriberIdentifier.subscriptionIDType\')) AS subscriber_id_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.subscriberIdentifier.subscriptionIDData\')) AS subscriber_id_data,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.duration\')) AS duration,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.invocationTimestamp\')) as invocationTimestamp,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataVolumeUplink\')) AS data_volume_uplink,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataVolumeDownlink\')) AS data_volume_downlink,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataTotalVolume\')) AS data_total_volume,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.pDUSessionChargingInformation.pDUAddress.pDUIPv4Address\')) AS pdu_ipv4_address,timestamp\",\"timeCol\":\"timestamp\",\"timeUnit\":\"second\",\"extras\":\"\",\"filePath\":\"/usr/local/omc/backup/smf_cdr\"}', '0 0 0/1 * * ?', '3', '0', '1', '1', 'supervisor', 1698478134842, 'admin', 1724309047797, ''); +INSERT INTO `sys_job` VALUES (14, 'job.exportSMSCCDR', 'SYSTEM', 'exportTable', '{\"duration\":1,\"tableName\":\"cdr_event_smsc\",\"columns\":\"id,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.recordType\')) as record_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.serviceType\')) as service_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.callerParty\')) as caller_party,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.calledParty\')) as called_party,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.result\')) as result,DATE_FORMAT(FROM_UNIXTIME(JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.updateTime\'))), \'%Y-%m-%d %H:%i:%s\') as update_time\",\"timeCol\":\"timestamp\",\"timeUnit\":\"second\",\"extras\":\"\",\"filePath\":\"/usr/local/omc/backup/smsc_cdr\"}', '0 0 0/1 * * ?', '3', '0', '1', '1', 'supervisor', 1698478134842, 'admin', 1724309047797, ''); +INSERT INTO `sys_job` VALUES (15, 'job.removeExportedFiles', 'SYSTEM', 'removeFile', '[{\"filePath\":\"/usr/local/omc/backup/operate_log\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/ims_cdr\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/smf_cdr\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/smsc_cdr\",\"maxDays\":30}]', '0 10 0 * * ?', '3', '0', '1', '1', 'supervisor', 1698478134842, 'admin', 1728634085631, ''); SET FOREIGN_KEY_CHECKS = 1; diff --git a/database/upgrade/upg_sys_dict_data1_i18n_zh.sql b/database/upgrade/upg_sys_dict_data1_i18n_zh.sql index b14044d0..a176e3f0 100644 --- a/database/upgrade/upg_sys_dict_data1_i18n_zh.sql +++ b/database/upgrade/upg_sys_dict_data1_i18n_zh.sql @@ -696,6 +696,8 @@ REPLACE INTO `sys_dict_data` VALUES (2178, 2178, 'dictData.cdr_cause_code.41', ' REPLACE INTO `sys_dict_data` VALUES (2179, 2179, 'dictData.cdr_cause_code.42', '拥塞', 'i18n_zh', '', '', '1', 'supervisor', 1725877564156, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (2180, 2180, 'dictData.cdr_cause_code.47', '资源不可用', 'i18n_zh', '', '', '1', 'supervisor', 1725877564156, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (2181, 2181, 'dictData.cdr_cause_code.50', '请求的设施未订阅', 'i18n_zh', '', '', '1', 'supervisor', 1725877564156, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2182, 2182, 'job.exportSMSCCDR', '定期从短信话单表导出文件至指定目录', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2183, 2183, 'job.removeExportedFiles', '定期删除指定目录过期文件', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); -- multi-tenancy REPLACE INTO `sys_dict_data` VALUES (11000, 11000, 'menu.security.tenant', '租户管理', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); diff --git a/database/upgrade/upg_sys_dict_data2_i18n_en.sql b/database/upgrade/upg_sys_dict_data2_i18n_en.sql index 7a17fce6..8b9d951f 100644 --- a/database/upgrade/upg_sys_dict_data2_i18n_en.sql +++ b/database/upgrade/upg_sys_dict_data2_i18n_en.sql @@ -691,6 +691,8 @@ REPLACE INTO `sys_dict_data` VALUES (4178, 4178, 'dictData.cdr_cause_code.41', ' REPLACE INTO `sys_dict_data` VALUES (4179, 4179, 'dictData.cdr_cause_code.42', 'Congestion', 'i18n_en', '', '', '1', 'supervisor', 1725877564156, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (4180, 4180, 'dictData.cdr_cause_code.47', 'Resources Unavailable Unspec', 'i18n_en', '', '', '1', 'supervisor', 1725877564156, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (4181, 4181, 'dictData.cdr_cause_code.50', 'Requested Facility Not Subscribed', 'i18n_en', '', '', '1', 'supervisor', 1725877564156, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4182, 4182, 'job.exportSMSCCDR', 'Export regularly from SMSC CDR table', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4183, 4183, 'job.removeExportedFiles', 'Regularly delete expired files in the specified directory', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); -- 多租户 REPLACE INTO `sys_dict_data` VALUES (14000, 14000, 'menu.security.tenant', 'Tenant Management', 'i18n_en', '', '', '1', 'supervisor', 1705550000000, '', 0, ''); diff --git a/database/upgrade/upg_sys_job.sql b/database/upgrade/upg_sys_job.sql index 48332084..b6d5c02b 100644 --- a/database/upgrade/upg_sys_job.sql +++ b/database/upgrade/upg_sys_job.sql @@ -43,6 +43,8 @@ REPLACE INTO `sys_job` VALUES (9, 'job.getStateFromNE', 'SYSTEM', 'getStateFromN REPLACE INTO `sys_job` VALUES (10, 'job.genNeStateAlarm', 'SYSTEM', 'genNeStateAlarm', '{\"alarmID\":\"HXEMSSM10000\",\"alarmCode\":10000,\"alarmTitle\":\"The system state is abnormal\",\"neType\":\"OMC\",\"alarmType\":\"EquipmentAlarm\",\"origSeverity\": \"Major\",\"objectName\":\"EMS;SystemManagement;Heartbeat\",\"objectType\":\"SystemState\",\"specificProblem\":\"Alarm cause: the system state of target NE has not been received for {threshold} seconds\", \"specificProblemID\":\"AC10000\",\"threshold\":30}', '0/5 * * * * ?', '3', '0', '0', '0', 'supervisor', 1698478134842, 'admin', 1713781643031, 'job.genNeStateAlarmRemark'); REPLACE INTO `sys_job` VALUES (11, 'job.exportOperateLog', 'SYSTEM', 'exportTable', '{\"duration\":1,\"tableName\":\"sys_log_operate\",\"timeCol\":\"oper_time\",\"timeUnit\":\"milli\",\"columns\":\"oper_id,omc_get_dict_value(title, \\\"i18n_en\\\") as title,business_type,method,request_method,operator_type,oper_name,dept_name,oper_url,oper_ip,oper_location,oper_param,oper_msg,status,oper_time,cost_time,tenant_id\",\"extras\":\"\",\"filePath\":\"/usr/local/omc/backup/operate_log\"}', '0 0 0/1 * * ?', '3', '0', '1', '1', 'supervisor', 1698478134842, 'admin', 1724833786290, 'job.exportOperateLog'); REPLACE INTO `sys_job` VALUES (12, 'job.exportIMSCDR', 'SYSTEM', 'exportTable', '{\"duration\":1,\"tableName\":\"cdr_event_ims\",\"columns\":\"id,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.recordType\')) as record_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.callType\')) as call_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.callerParty\')) as caller_party,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.calledParty\')) as called_party,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.callDuration\')) as call_duration,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.serviceResult\')) as service_result,DATE_FORMAT(FROM_UNIXTIME(timestamp), \'%Y-%m-%d %H:%i:%s\') AS timestamp\",\"timeCol\":\"timestamp\",\"timeUnit\":\"second\",\"extras\":\"\",\"filePath\":\"/usr/local/omc/backup/ims_cdr\"}', '0 0 0/1 * * ?', '3', '0', '1', '1', 'supervisor', 1698478134842, 'admin', 1722224659251, ''); -REPLACE INTO `sys_job` VALUES (13, 'job.exportSMFCDR', 'SYSTEM', 'exportTable', '{\"duration\":1,\"tableName\":\"cdr_event_smf\",\"columns\":\"id,ne_type,ne_name,rm_uid,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.recordType\')) AS record_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.chargingID\')) AS charging_id,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.subscriberIdentifier.subscriptionIDType\')) AS subscriber_id_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.subscriberIdentifier.subscriptionIDData\')) AS subscriber_id_data,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.duration\')) AS duration,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.invocationTimestamp\')) as invocationTimestamp,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataVolumeUplink\')) AS data_volume_uplink,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataVolumeDownlink\')) AS data_volume_downlink,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataTotalVolume\')) AS data_total_volume,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.pDUSessionChargingInformation.pDUAddress.pDUIPv4Address\')) AS pdu_ipv4_address,timestamp\",\"timeCol\":\"timestamp\",\"timeUnit\":\"second\",\"extras\":\"\",\"filePath\":\"/usr/local/omc/backup/smf_cdr\"}', '0 0 0/1 * * ?', '3', '0', '1', '1', 'supervisor', 1698478134842, 'admin', 1724309047797, ''); +REPLACE INTO `sys_job` VALUES (13, 'job.exportSMFCDR', 'SYSTEM', 'exportTable', '{\"duration\":1,\"tableName\":\"cdr_event_smf\",\"columns\":\"id,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.recordType\')) AS record_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.chargingID\')) AS charging_id,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.subscriberIdentifier.subscriptionIDType\')) AS subscriber_id_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.subscriberIdentifier.subscriptionIDData\')) AS subscriber_id_data,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.duration\')) AS duration,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.invocationTimestamp\')) as invocationTimestamp,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataVolumeUplink\')) AS data_volume_uplink,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataVolumeDownlink\')) AS data_volume_downlink,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataTotalVolume\')) AS data_total_volume,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.pDUSessionChargingInformation.pDUAddress.pDUIPv4Address\')) AS pdu_ipv4_address,timestamp\",\"timeCol\":\"timestamp\",\"timeUnit\":\"second\",\"extras\":\"\",\"filePath\":\"/usr/local/omc/backup/smf_cdr\"}', '0 0 0/1 * * ?', '3', '0', '1', '1', 'supervisor', 1698478134842, 'admin', 1724309047797, ''); +REPLACE INTO `sys_job` VALUES (14, 'job.exportSMSCCDR', 'SYSTEM', 'exportTable', '{\"duration\":1,\"tableName\":\"cdr_event_smsc\",\"columns\":\"id,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.recordType\')) as record_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.serviceType\')) as service_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.callerParty\')) as caller_party,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.calledParty\')) as called_party,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.result\')) as result,DATE_FORMAT(FROM_UNIXTIME(JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.updateTime\'))), \'%Y-%m-%d %H:%i:%s\') as update_time\",\"timeCol\":\"timestamp\",\"timeUnit\":\"second\",\"extras\":\"\",\"filePath\":\"/usr/local/omc/backup/smsc_cdr\"}', '0 0 0/1 * * ?', '3', '0', '1', '1', 'supervisor', 1698478134842, 'admin', 1724309047797, ''); +REPLACE INTO `sys_job` VALUES (15, 'job.removeExportedFiles', 'SYSTEM', 'removeFile', '[{\"filePath\":\"/usr/local/omc/backup/operate_log\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/ims_cdr\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/smf_cdr\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/smsc_cdr\",\"maxDays\":30}]', '0 10 0 * * ?', '3', '0', '1', '1', 'supervisor', 1698478134842, 'admin', 1728634085631, ''); SET FOREIGN_KEY_CHECKS = 1; \ No newline at end of file diff --git a/features/pm/performance.go b/features/pm/performance.go index a11d27c3..168b88ac 100644 --- a/features/pm/performance.go +++ b/features/pm/performance.go @@ -44,7 +44,7 @@ type KpiReport struct { NeType string `json:"NeType"` KPIs []struct { KPIID string `json:"KPIID"` - Value int `json:"Value"` + Value int64 `json:"Value"` Err string `json:"Err"` } `json:"KPIs"` } `json:"NE"` @@ -62,7 +62,7 @@ type GoldKpi struct { RmUid string `json:"rmUid" xorm:"rm_uid"` NEType string `json:"neType" xorm:"ne_type"` KpiId string `json:"kpiId" xorm:"kpi_id"` - Value int `json:"value"` + Value int64 `json:"value"` Error string `json:"error"` Timestamp string `json:"timestamp"` } diff --git a/src/modules/crontask/processor/processor.go b/src/modules/crontask/processor/processor.go index 09176717..5363e561 100644 --- a/src/modules/crontask/processor/processor.go +++ b/src/modules/crontask/processor/processor.go @@ -10,6 +10,7 @@ import ( "be.ems/src/modules/crontask/processor/getStateFromNE" processorMonitorSysResource "be.ems/src/modules/crontask/processor/monitor_sys_resource" processorNeConfigBackup "be.ems/src/modules/crontask/processor/ne_config_backup" + "be.ems/src/modules/crontask/processor/removeFile" ) // InitCronQueue 初始定时任务队列 @@ -25,4 +26,5 @@ func InitCronQueue() { cron.CreateQueue("getStateFromNE", getStateFromNE.NewProcessor) cron.CreateQueue("genNeStateAlarm", genNeStateAlarm.NewProcessor) cron.CreateQueue("exportTable", exportTable.NewProcessor) + cron.CreateQueue("removeFile", removeFile.NewProcessor) } diff --git a/src/modules/crontask/processor/removeFile/removeFile.go b/src/modules/crontask/processor/removeFile/removeFile.go new file mode 100644 index 00000000..5420b40b --- /dev/null +++ b/src/modules/crontask/processor/removeFile/removeFile.go @@ -0,0 +1,159 @@ +package removeFile + +import ( + "encoding/json" + "os" + "path/filepath" + "sort" + "time" + + "be.ems/lib/log" + "be.ems/src/framework/cron" +) + +var NewProcessor = &BarProcessor{ + progress: 0, + count: 0, +} + +// bar 队列任务处理 +type BarProcessor struct { + // 任务进度 + progress int + // 执行次数 + count int +} + +type BarParams struct { + FilePath string `json:"filePath"` // file path + MaxDays int `json:"maxDays"` + MaxFiles *int `json:"maxFiles"` // keep max files + MaxSize *int64 `json:"maxSize"` + Extras string `json:"extras"` // extras condition for where +} + +type FileInfo struct { + Path string + Info os.FileInfo +} + +func (s *BarProcessor) Execute(data any) (any, error) { + s.count++ + + options := data.(cron.JobData) + sysJob := options.SysJob + var params []BarParams + + err := json.Unmarshal([]byte(sysJob.TargetParams), ¶ms) + if err != nil { + return nil, err + } + result := []map[string]any{} + for _, param := range params { + res, _ := s.ExecuteOne(param) + result = append(result, res) + } + + // 返回结果,用于记录执行结果 + return map[string]any{ + "result": result, + }, nil +} + +func (s *BarProcessor) ExecuteOne(params BarParams) (map[string]any, error) { + var maxFiles int = 0 + var maxSize int64 = 0 + if params.MaxFiles != nil { + maxFiles = *params.MaxFiles + } + if params.MaxSize != nil { + maxSize = int64(*params.MaxSize * 1024 * 1024) + } + files, err := getFiles(params.FilePath) + if err != nil { + return map[string]any{ + "msg": "failed", + "err": err.Error(), + }, err + } + + // 获取本地时区 + loc, err := time.LoadLocation("Local") + if err != nil { + return map[string]any{ + "msg": "failed", + "err": err.Error(), + }, err + } + cutoff := time.Now().In(loc).AddDate(0, 0, -params.MaxDays) + + var oldFiles []FileInfo + for _, file := range files { + if file.Info.ModTime().Before(cutoff) { + oldFiles = append(oldFiles, file) + } + } + + // 按修改时间排序文件(最旧的在前) + sort.Slice(oldFiles, func(i, j int) bool { + return oldFiles[i].Info.ModTime().Before(oldFiles[j].Info.ModTime()) + }) + + deleted, errorDel := 0, 0 + + // 删除文件,直到满足文件总数不超过maxFiles个且总大小不超过maxSize的条件 + var totalSize int64 + for i, file := range oldFiles { + if (maxFiles > 0 && i >= maxFiles) || (maxSize > 0 && totalSize+file.Info.Size() > maxSize) { + break + } + err := os.Remove(file.Path) + if err != nil { + log.Error("Error deleting file:", file.Path, err) + errorDel++ + continue + } + totalSize += file.Info.Size() + deleted++ + } + + // 如果仍然有超过maxFiles个文件或总大小超过maxSize,继续删除最旧的文件 + remainingFiles := files + sort.Slice(remainingFiles, func(i, j int) bool { + return remainingFiles[i].Info.ModTime().Before(remainingFiles[j].Info.ModTime()) + }) + + for (maxFiles > 0 && len(remainingFiles) > maxFiles) || (maxSize > 0 && totalSize > maxSize) { + file := remainingFiles[0] + err := os.Remove(file.Path) + if err != nil { + log.Error("Error deleting file:", file.Path, err) + remainingFiles = remainingFiles[1:] + continue + } + totalSize -= file.Info.Size() + remainingFiles = remainingFiles[1:] + } + + // 返回结果,用于记录执行结果 + return map[string]any{ + "msg": "successed", + "filePath": params.FilePath, + "deleted": deleted, + "errorDel": errorDel, + }, nil +} + +func getFiles(dir string) ([]FileInfo, error) { + var files []FileInfo + err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if !info.IsDir() { + files = append(files, FileInfo{Path: path, Info: info}) + } + return nil + }) + return files, err +} diff --git a/src/modules/trace/controller/packet.go b/src/modules/trace/controller/packet.go index a89cacc6..ac54aa2b 100644 --- a/src/modules/trace/controller/packet.go +++ b/src/modules/trace/controller/packet.go @@ -21,7 +21,7 @@ type PacketController struct { packetService *traceService.Packet // 信令跟踪服务 } -// 网元跟踪网卡设备列表 +// 信令跟踪网卡设备列表 // // GET /devices func (s *PacketController) Devices(c *gin.Context) { @@ -29,22 +29,23 @@ func (s *PacketController) Devices(c *gin.Context) { c.JSON(200, result.OkData(data)) } -// 网元跟踪开始 +// 信令跟踪开始 // // POST /start func (s *PacketController) Start(c *gin.Context) { language := ctx.AcceptLanguage(c) var body struct { - Device string `json:"device" binding:"required"` // 网卡设备 - TaskNo string `json:"taskNo" binding:"required"` // 任务编号 - Output string `json:"output" ` // 输出PCAP文件路径,为空则不输出 + TaskNo string `json:"taskNo" binding:"required"` // 任务编号 + Device string `json:"device" binding:"required"` // 网卡设备 + Filter string `json:"filter" ` // 过滤表达式(port 33030 or 33040) + OutputPCAP bool `json:"outputPCAP" ` // 输出PCAP文件 (默认false) } if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil { c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } - msg, err := s.packetService.LiveStart(body.TaskNo, body.Device, body.Output) + msg, err := s.packetService.LiveStart(body.TaskNo, body.Device, body.Filter, body.OutputPCAP) if err != nil { c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error()))) return @@ -52,7 +53,7 @@ func (s *PacketController) Start(c *gin.Context) { c.JSON(200, result.OkData(msg)) } -// 网元跟踪结束 +// 信令跟踪结束 // // POST /stop func (s *PacketController) Stop(c *gin.Context) { @@ -72,14 +73,14 @@ func (s *PacketController) Stop(c *gin.Context) { c.JSON(200, result.Ok(nil)) } -// 网元跟踪过滤 +// 信令跟踪过滤 // // PUT /filter func (s *PacketController) Filter(c *gin.Context) { language := ctx.AcceptLanguage(c) var body struct { TaskNo string `json:"taskNo" binding:"required"` // 任务编号 - Expr string `json:"expr" binding:"required"` // 过滤表达式(port 33030 or 33040) + Expr string `json:"expr" ` // 过滤表达式(port 33030 or 33040) } if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil { c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) @@ -93,19 +94,28 @@ func (s *PacketController) Filter(c *gin.Context) { c.JSON(200, result.Ok(nil)) } -// 网元跟踪续期保活 +// 信令跟踪续期保活 // // PUT /keep-alive func (s *PacketController) KeepAlive(c *gin.Context) { language := ctx.AcceptLanguage(c) var body struct { - IntervalIn int `json:"intervalIn" ` // 服务续约的频率,默认设置为60秒 - Duration int `json:"duration" ` // 服务失效的时间,默认设置为120秒 + TaskNo string `json:"taskNo" binding:"required"` // 任务编号 + Duration int `json:"duration" ` // 服务失效的时间,默认设置为120秒 } - err := c.ShouldBindBodyWith(&body, binding.JSON) - if err != nil { + if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil { c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } + + // 默认设置为120秒 + if body.Duration <= 1 { + body.Duration = 120 + } + + if err := s.packetService.LiveTimeout(body.TaskNo, body.Duration); err != nil { + c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error()))) + return + } c.JSON(200, result.Ok(nil)) } diff --git a/src/modules/trace/packet_task/packet.go b/src/modules/trace/packet_task/packet.go new file mode 100644 index 00000000..5df723b3 --- /dev/null +++ b/src/modules/trace/packet_task/packet.go @@ -0,0 +1,245 @@ +package packet_task + +import ( + "fmt" + "os" + "path/filepath" + "runtime" + "strings" + "sync" + "time" + + "be.ems/src/framework/logger" + wsService "be.ems/src/modules/ws/service" + "github.com/gopacket/gopacket" + "github.com/gopacket/gopacket/layers" + "github.com/gopacket/gopacket/pcap" + "github.com/gopacket/gopacket/pcapgo" +) + +// 捕获任务 +var taskMap sync.Map + +// task 任务信息 +type task struct { + TaskNo string // 任务编号 + Handle *pcap.Handle // 捕获句柄 + File *os.File // 捕获信息输出文件句柄 + Writer *pcapgo.Writer // 捕获信息输出句柄 + Filter string // 过滤表达式 + Ticker *time.Ticker // 任务失效定时器 +} + +// NetworkDevices 获取网卡设备信息 +func NetworkDevices() ([]pcap.Interface, error) { + devices, err := pcap.FindAllDevs() + if err != nil { + logger.Errorf("interfaces find all devices err: %s", err.Error()) + return nil, err + } + return devices, nil +} + +// verifyDevice 检查网卡设备是否存在 +func verifyDevice(str string) (string, bool) { + devices, err := pcap.FindAllDevs() + if err != nil { + logger.Errorf("interfaces find all devices err: %s", err.Error()) + return "", false + } + for _, device := range devices { + if len(device.Addresses) == 0 { + continue + } + if device.Name == str { + return device.Name, true + } + for _, address := range device.Addresses { + if address.IP.String() == str { + return device.Name, true + } + } + } + return "", false +} + +// outputPCAP 输出 pcap 文件 +// 新文件时需要 snaplen 最大长度 linktype 链路类型 +func outputPCAP(snaplen uint32, linktype layers.LinkType, outputFile string) (*os.File, *pcapgo.Writer, error) { + var err error + var f *os.File + if err := os.MkdirAll(filepath.Dir(outputFile), 0775); err != nil { + return nil, nil, err + } + + // 检查文件是否存在 + if _, err = os.Stat(outputFile); os.IsNotExist(err) { + f, err = os.Create(outputFile) + if err != nil { + return nil, nil, err + } + w := pcapgo.NewWriter(f) + w.WriteFileHeader(snaplen, linktype) // new file, must do this. + return f, w, nil + } + + f, err = os.OpenFile(outputFile, os.O_APPEND, 0700) + if err != nil { + return nil, nil, err + } + w := pcapgo.NewWriter(f) + return f, w, nil +} + +// capturePacketSource 捕获数据 +func capturePacketSource(taskInfo *task) { + // capture packets + packetSource := gopacket.NewPacketSource(taskInfo.Handle, taskInfo.Handle.LinkType()) + packetSource.Lazy = false + packetSource.NoCopy = true + packetSource.DecodeStreamsAsDatagrams = true + + // 协程停止后关闭句柄并移除任务信息 + defer func() { + taskInfo.Ticker.Stop() + taskInfo.Handle.Close() + if taskInfo.File != nil { + taskInfo.File.Close() + } + taskMap.Delete(taskInfo.TaskNo) + }() + + frameNumber := 0 // 帧编号 + frameTime := 0.000000 // 时间 + var startTimestamp time.Time // 开始时间 + + for { + select { + case <-taskInfo.Ticker.C: + return + case packet := <-packetSource.Packets(): + if packet == nil { + continue + } + // if packet.Metadata().Timestamp.Before(time.Now()) { + // continue + // } + if taskInfo.Writer != nil { + taskInfo.Writer.WritePacket(packet.Metadata().CaptureInfo, packet.Data()) + } + fmt.Println("---------- packet.Layers() ", len(packet.Layers())) + frameNumber++ // 帧编号 + currentTimestamp := packet.Metadata().Timestamp + if !startTimestamp.IsZero() { + // 计算时间差转换为秒 + frameTime = currentTimestamp.Sub(startTimestamp).Seconds() + } else { + startTimestamp = currentTimestamp + } + + // 数据 + frameMeta := parsePacketFrame(frameNumber, frameTime, packet) + + // 推送到ws订阅组 + wsService.NewWSSend.ByGroupID(fmt.Sprintf("%s%s", wsService.GROUP_TRACE_PACKET, taskInfo.TaskNo), frameMeta) + } + } +} + +// LiveStart 开始捕获数据 +func LiveStart(taskNo, deviceName, filterBPF string, outputFile bool) (string, error) { + if _, ok := taskMap.Load(taskNo); ok { + return "", fmt.Errorf("task no. %s already exist", taskNo) + } + + // Verify the specified network interface exists + device, deviceOk := verifyDevice(deviceName) + if !deviceOk { + return "", fmt.Errorf("network device not exist: %s", deviceName) + } + + snapshotLength := 262144 + + // open device + handle, err := pcap.OpenLive(device, int32(snapshotLength), true, pcap.BlockForever) + if err != nil { + logger.Errorf("open live err: %s", err.Error()) + if strings.Contains(err.Error(), "operation not permitted") { + return "", fmt.Errorf("you don't have permission to capture on that/these device(s)") + } + return "", err + } + + // write a new file + var w *pcapgo.Writer + var f *os.File + if outputFile { + // 网管本地路径 + localFilePath := fmt.Sprintf("/tmp/omc/packet/%s.pcap", taskNo) + if runtime.GOOS == "windows" { + localFilePath = fmt.Sprintf("C:%s", localFilePath) + } + f, w, err = outputPCAP(uint32(snapshotLength), handle.LinkType(), localFilePath) + if err != nil { + return "", err + } + } + + // set filter + if filterBPF != "" { + if err = handle.SetBPFFilter(filterBPF); err != nil { + logger.Errorf("packet BPF Filter %s => %s", filterBPF, err.Error()) + filterBPF = "" + } + } + + // save tasks + taskInfo := &task{ + TaskNo: taskNo, + Handle: handle, + File: f, + Writer: w, + Filter: filterBPF, + Ticker: time.NewTicker(time.Second * 120), + } + + go capturePacketSource(taskInfo) + taskMap.Store(taskNo, taskInfo) + return fmt.Sprintf("task no. %s initiated", taskNo), nil +} + +// LiveFilter 捕获过滤 +func LiveFilter(taskNo, expr string) error { + info, ok := taskMap.Load(taskNo) + if !ok { + return fmt.Errorf("task no. %s not exist", taskNo) + } + task := info.(*task) + task.Filter = expr + err := task.Handle.SetBPFFilter(expr) + if err != nil { + logger.Errorf("packet BPF Filter %s => %s", expr, err.Error()) + return fmt.Errorf("can't parse filter expression") + } + return nil +} + +// LiveTimeout 更新捕获失效时间 +func LiveTimeout(taskNo string, seconds int) error { + info, ok := taskMap.Load(taskNo) + if !ok { + return fmt.Errorf("task no. %s not exist", taskNo) + } + info.(*task).Ticker.Reset(time.Duration(seconds) * time.Second) + return nil +} + +// LiveStop 停止捕获数据 +func LiveStop(taskNo string) error { + info, ok := taskMap.Load(taskNo) + if !ok { + return fmt.Errorf("task no. %s not exist", taskNo) + } + info.(*task).Ticker.Reset(time.Millisecond) + return nil +} diff --git a/src/modules/trace/packet_task/packet_frame.go b/src/modules/trace/packet_task/packet_frame.go new file mode 100644 index 00000000..d060149d --- /dev/null +++ b/src/modules/trace/packet_task/packet_frame.go @@ -0,0 +1,843 @@ +package packet_task + +import ( + "encoding/base64" + "fmt" + "strings" + + "be.ems/src/framework/logger" + "github.com/gopacket/gopacket" + "github.com/gopacket/gopacket/layers" +) + +// FrameMeta 数据帧元信息 +type FrameMeta struct { + Number int `json:"number"` + Comments bool `json:"comments"` + Ignored bool `json:"ignored"` + Marked bool `json:"marked"` + Bg int `json:"bg"` // 背景色 数值转字符串16进制 15007687->e4ffc7 + Fg int `json:"fg"` // 前景色 文字 + Columns [7]string `json:"columns"` // 长度对应字段 ['No.', 'Time', 'Source', 'Destination', 'Protocol', 'Length', 'Info'] + Frame Frame `json:"frame"` +} + +// Frame 数据帧信息 +type Frame struct { + Number int `json:"number"` + Comments []string `json:"comments"` + DataSource []map[string]string `json:"data_sources"` + Tree []ProtoTree `json:"tree"` + Follow [][]string `json:"follow"` +} + +// ProtoTree 数据帧协议树 +type ProtoTree struct { + Label string `json:"label"` // 显示的文本 + Filter string `json:"filter"` // 过滤条件 + Severity string `json:"severity"` + Type string `json:"type"` + URL string `json:"url"` + Fnum int `json:"fnum"` + Start int `json:"start"` // 开始位置 + Length int `json:"length"` // 长度 + DataSourceIdx int `json:"data_source_idx"` + Tree []ProtoTree `json:"tree"` // 子节点 +} + +// parsePacketFrame 解析数据包帧信息 +// frameNumber 帧编号 i++ +// frameTime 时间秒 0.000000 +func parsePacketFrame(frameNumber int, frameTime float64, packet gopacket.Packet) FrameMeta { + frameSrcHost := "" // 源主机IP + frameDstHost := "" // 目的主机IP + frameProtocol := "" // 协议 + frameLength := fmt.Sprintf("%d", packet.Metadata().Length) // 长度 + frameInfo := "" // 信息 + fg, bg := colorRuleFB(packet) // 背景色 数值转字符串16进制 15007687->e4ffc7 + + frame := Frame{ + Number: frameNumber, + Comments: []string{}, + DataSource: []map[string]string{ + { + "name": fmt.Sprintf("Frame (%d bytes)", packet.Metadata().Length), + "data": base64.StdEncoding.EncodeToString(packet.Data()), + }, + }, + Tree: []ProtoTree{}, // 各层的数据 + Follow: [][]string{}, // {"TCP", "tcp.stream eq 0"} + } + + // 连接层 + // fmt.Println(packet.LinkLayer()) + if linkLayer := packet.LinkLayer(); linkLayer != nil { + linkTree := linkLayerTree(linkLayer) + frame.Tree = append(frame.Tree, linkTree) + } + + // 网络层 + // fmt.Println(packet.NetworkLayer()) + if networkLayer := packet.NetworkLayer(); networkLayer != nil { + networkTree := networkLayerTree(networkLayer) + frame.Tree = append(frame.Tree, networkTree) + + src, dst := networkLayer.NetworkFlow().Endpoints() + frameSrcHost = src.String() + frameDstHost = dst.String() + if frameDstHost == "ff:ff:ff:ff" { + frameDstHost = "Broadcast" + } + } + + // 传输层 + // fmt.Println(packet.TransportLayer()) + if transportLayer := packet.TransportLayer(); transportLayer != nil { + info, transportTree := transportLayerTree(transportLayer) + frame.Tree = append(frame.Tree, transportTree) + + frameProtocol = transportLayer.LayerType().String() + frameInfo += info + frame.Follow = append(frame.Follow, []string{ + frameProtocol, + fmt.Sprintf("%s.stream eq 0", strings.ToLower(frameProtocol)), + }) + } + + // 应用层 + // fmt.Println(packet.ApplicationLayer()) + if applicationLayer := packet.ApplicationLayer(); applicationLayer != nil { + applicationTree := applicationLayerTree(applicationLayer) + frame.Tree = append(frame.Tree, applicationTree) + } + + return FrameMeta{ + Number: frameNumber, + Comments: false, + Ignored: false, + Marked: false, + Bg: fg, + Fg: bg, + Columns: [7]string{ + fmt.Sprintf("%d", frameNumber), + fmt.Sprintf("%.6f", frameTime), // 格式化为 0.000000 + frameSrcHost, + frameDstHost, + frameProtocol, + frameLength, + frameInfo, + }, + Frame: frame, + } +} + +// linkLayerTree 连接层 +func linkLayerTree(linkLayer gopacket.LinkLayer) ProtoTree { + var protoTree ProtoTree + switch layer := linkLayer.(type) { + case *layers.Ethernet: // 最常见的链路层协议,用于局域网(LAN)中。 + srcMAC := layer.SrcMAC + dstMAC := layer.DstMAC + ethernetLayerLen := len(layer.Contents) + protoTree = ProtoTree{ + Label: fmt.Sprintf("%s II, Src: %s, Dst: %s", layer.LayerType(), srcMAC, dstMAC), + Filter: "eth", + Start: 0, + Length: ethernetLayerLen, + DataSourceIdx: 0, + Tree: []ProtoTree{ + { + Label: fmt.Sprintf("Destination: %s", dstMAC.String()), + Filter: fmt.Sprintf("eth.dst == %s", dstMAC.String()), + Start: 0, + Length: ethernetLayerLen, + DataSourceIdx: 0, + Tree: []ProtoTree{ + { + Label: fmt.Sprintf("Address: %s", dstMAC.String()), + Filter: fmt.Sprintf("eth.addr == %s", dstMAC.String()), + Start: 0, + Length: 6, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 926233912, + URL: "", + }, + { + Label: ".... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)", + Filter: "eth.dst.lg == 0", + Start: 0, + Length: 3, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 926233912, + URL: "", + }, + { + Label: ".... ...0 .... .... .... .... = IG bit: Individual address (unicast)", + Filter: "eth.dst.ig == 0", + Start: 0, + Length: 3, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 926233912, + URL: "", + }, + }, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: fmt.Sprintf("Source: %s", srcMAC.String()), + Filter: fmt.Sprintf("eth.src == %s", srcMAC.String()), + Start: ethernetLayerLen, + Length: ethernetLayerLen, + DataSourceIdx: 0, + Tree: []ProtoTree{ + { + Label: fmt.Sprintf("Address: %s", srcMAC.String()), + Filter: fmt.Sprintf("eth.addr == %s", dstMAC.String()), + Start: ethernetLayerLen, + Length: ethernetLayerLen, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 926233912, + URL: "", + }, + { + Label: ".... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)", + Filter: "eth.src.lg == 0", + Start: len(srcMAC), + Length: len(srcMAC) / 2, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 926233912, + URL: "", + }, + { + Label: ".... ...0 .... .... .... .... = IG bit: Individual address (unicast)", + Filter: "eth.src.ig == 0", + Start: len(srcMAC), + Length: len(srcMAC) / 2, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 926233912, + URL: "", + }, + }, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: "Type: IPv4 (0x0800)", + Filter: "eth.type == 0x0800", + Start: len(dstMAC) + len(srcMAC), + Length: len(layer.LayerContents()) - (len(dstMAC) + len(srcMAC)), + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + }, + Severity: "", + Type: "proto", + Fnum: 1052, + URL: "", + } + case *layers.PPP: // 点对点协议,通常用于拨号连接。 + protoTree = ProtoTree{ + Label: fmt.Sprintf("%s ", layer.LayerType()), + Filter: "ppp", + Start: 0, + Length: len(layer.LayerContents()), + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "proto", + Fnum: 1052, + URL: "", + } + } + return protoTree +} + +// networkLayerTree 网络层 +func networkLayerTree(networkLayer gopacket.NetworkLayer) ProtoTree { + var protoTree ProtoTree + switch layer := networkLayer.(type) { + case *layers.IPv4: // 第四版因特网协议,广泛使用。 + // 偏移量取连接层的长度Length + linkLayerLen := 14 + networkLayerLen := len(layer.Contents) + + version := layer.Version + length := layer.Length + srcIP := layer.SrcIP + dstIP := layer.DstIP + ihl := layer.IHL + headerLength := ihl * 4 // 提取头部长度 + tos := layer.TOS + dscp, ecn := networkDSCPAndECN(tos) + identification := layer.Id + flags := layer.Flags // 提取标志位 + // 生成标志描述 + flagsDesc := networkFlagsDesc(flags) + rb, rbDesc := networkFlagsEvil(flags) + df, dfDesc := networkFlagsDF(flags) + mf, mfDesc := networkFlagsMF(flags) + fragOffset := layer.FragOffset + fragOffsetDesc := networkOffset(fragOffset) + ttl := layer.TTL + proto := layer.Protocol + checksum := layer.Checksum + + protoTree = ProtoTree{ + Label: fmt.Sprintf("Internet Protocol Version %d, Src: %s, Dst: %s", version, srcIP, dstIP), + Filter: "ip", + Start: linkLayerLen, + Length: networkLayerLen, + DataSourceIdx: 0, + Tree: []ProtoTree{ + { + Label: fmt.Sprintf("%04b .... = Version: %d", version, version), + Filter: fmt.Sprintf("ip.version == %d", version), + Start: linkLayerLen, + Length: 1, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: fmt.Sprintf(".... 0101 = Header Length: %d bytes (%d)", headerLength, ihl), + Filter: fmt.Sprintf("ip.hdr_len == %d", headerLength), + Start: linkLayerLen, + Length: 1, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: fmt.Sprintf("Differentiated Services Field: 0x%02x (DSCP: %s, ECN: %s)", tos, dscp, ecn), + Filter: fmt.Sprintf("ip.dsfield == 0x%02x", tos), + Start: linkLayerLen + 1, + Length: 1, + DataSourceIdx: 0, + Tree: []ProtoTree{ + { + Label: fmt.Sprintf("0000 00.. = Differentiated Services Codepoint: %s (%d)", dscp, tos), + Filter: fmt.Sprintf("ip.dsfield.dscp == %d", tos>>2), + Start: linkLayerLen + 1, + Length: 1, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 926233912, + URL: "", + }, + { + Label: fmt.Sprintf(".... ..00 = Explicit Congestion Notification: %s Capable Transport (%d)", ecn, tos), + Filter: fmt.Sprintf("ip.dsfield.ecn == %d", tos&0x03), + Start: linkLayerLen + 1, + Length: 1, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 926233912, + URL: "", + }, + }, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: fmt.Sprintf("Total Length: %d", length), + Filter: fmt.Sprintf("ip.len == %d", length), + Start: linkLayerLen + 2, + Length: 2, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: fmt.Sprintf("Identification: 0x%X (%d)", identification, identification), + Filter: fmt.Sprintf("ip.id == 0x%X", identification), + Start: linkLayerLen + 4, + Length: 2, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: fmt.Sprintf("%03b. .... = Flags: %s", flags, flagsDesc), + Filter: fmt.Sprintf("ip.flags == 0x%X", flags), + Start: linkLayerLen + 6, + Length: 1, + DataSourceIdx: 0, + Tree: []ProtoTree{ + { + Label: fmt.Sprintf("0... .... = Reserved bit: %s", rbDesc), + Filter: fmt.Sprintf("ip.flags.rb == %d", rb), + Start: linkLayerLen + 6, + Length: 1, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 926233912, + URL: "", + }, + { + Label: fmt.Sprintf(".1.. .... = Don't fragment: %s", dfDesc), + Filter: fmt.Sprintf("ip.flags.df == %d", df), + Start: linkLayerLen + 6, + Length: 1, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 926233912, + URL: "", + }, + { + Label: fmt.Sprintf("..0. .... = More fragments: %s", mfDesc), + Filter: fmt.Sprintf("ip.flags.mf == %d", mf), + Start: linkLayerLen + 6, + Length: 1, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 926233912, + URL: "", + }, + }, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: fmt.Sprintf("%s = Fragment Offset: %d", fragOffsetDesc, fragOffset), + Filter: fmt.Sprintf("ip.frag_offset == %d", fragOffset), + Start: linkLayerLen + 6, + Length: 2, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: fmt.Sprintf("Time to Live: %d", ttl), + Filter: fmt.Sprintf("ip.ttl == %d", ttl), + Start: linkLayerLen + 8, + Length: 1, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: fmt.Sprintf("Protocol: TCP (%d)", proto), + Filter: fmt.Sprintf("ip.proto == %d", proto), + Start: linkLayerLen + 9, + Length: 1, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: fmt.Sprintf("Header Checksum: 0x%x [validation disabled]", checksum), + Filter: fmt.Sprintf("ip.checksum == 0x%x", checksum), + Start: linkLayerLen + 10, + Length: 2, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: "Header checksum status: Unverified", + Filter: "ip.checksum.status == \"Unverified\"", + Start: 0, + Length: 0, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: fmt.Sprintf("Source Address: %s", srcIP), + Filter: fmt.Sprintf("ip.src == %s", srcIP), + Start: linkLayerLen + 12, + Length: 4, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: fmt.Sprintf("Destination Address: %s", dstIP), + Filter: fmt.Sprintf("ip.dst == %s", dstIP), + Start: linkLayerLen + 16, + Length: 4, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + }, + Severity: "", + Type: "proto", + Fnum: 1052, + URL: "", + } + + logger.Infof("-> (tos 0x%x, ttl %d, id %d, offset %d, flags [%s], proto %s (%d), length %d)\n", tos, ttl, identification, fragOffset, flags, proto, proto, len(layer.Contents)+len(layer.Payload)) + case *layers.IPv6: // 第六版因特网协议,逐渐取代 IPv4。 + logger.Infof("-> (flowlabel 0x%x, hlim %d, next-header %s (%d), payload length: %d)\n", layer.FlowLabel, layer.HopLimit, layer.NextHeader, layer.NextHeader, len(layer.Payload)) + } + return protoTree +} + +// transportLayerTree 传输层 +func transportLayerTree(transportLayer gopacket.TransportLayer) (string, ProtoTree) { + var info string + var tree ProtoTree + switch layer := transportLayer.(type) { + case *layers.TCP: // 传输控制协议,提供可靠的数据传输。 + // 偏移量取连接层加网络层的长度Length + linkLayerAndNetworkLayerLen := 14 + 20 + transportLayerLen := len(layer.Contents) + payloadrLen := len(layer.Payload) + seq := layer.Seq + ack := layer.Ack + srcPort := layer.SrcPort + dstPort := layer.DstPort + dataOffset := layer.DataOffset + hdrLen := dataOffset * 4 + flags, flagsDesc := transportFlagsDesc(layer) + flagsACK, flagsACKDesc := transportFlagsStatus(layer.ACK) + flagsPSH, flagsPSHDesc := transportFlagsStatus(layer.PSH) + window := layer.Window + checksum := layer.Checksum + urgent := layer.Urgent + optionsLen, optionsDesc := transportOptions(layer.Options) + payloadStr := bytesToHexString(layer.Payload) + + tree = ProtoTree{ + Label: fmt.Sprintf("Transmission Control Protocol, Src Port: %s, Dst Port: %s, Seq: %d, Ack: %d, Len: %d", srcPort, dstPort, seq, ack, payloadrLen), + Filter: "tcp", + Start: linkLayerAndNetworkLayerLen, + Length: transportLayerLen, + DataSourceIdx: 0, + Tree: []ProtoTree{ + { + Label: fmt.Sprintf("Source Port: %s", srcPort), + Filter: fmt.Sprintf("tcp.srcport == %d", srcPort), + Start: linkLayerAndNetworkLayerLen, + Length: 2, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: fmt.Sprintf("Destination Port: %s", dstPort), + Filter: fmt.Sprintf("tcp.dstport == %d", dstPort), + Start: linkLayerAndNetworkLayerLen + 2, + Length: 2, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: fmt.Sprintf("TCP Segment Len: %d", payloadrLen), + Filter: fmt.Sprintf("tcp.len == %d", payloadrLen), + Start: linkLayerAndNetworkLayerLen + 12, + Length: 1, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: fmt.Sprintf("Sequence Number: %d (relative sequence number)", seq), + Filter: fmt.Sprintf("tcp.seq == %d", seq), + Start: linkLayerAndNetworkLayerLen + 4, + Length: 4, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: fmt.Sprintf("Acknowledgment Number: %d (relative ack number)", ack), + Filter: fmt.Sprintf("tcp.ack == %d", ack), + Start: linkLayerAndNetworkLayerLen + 8, + Length: 4, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: fmt.Sprintf("%04b .... = Header Length: %d bytes (%d)", dataOffset, hdrLen, dataOffset), + Filter: fmt.Sprintf("tcp.hdr_len == %d", hdrLen), + Start: linkLayerAndNetworkLayerLen + 12, + Length: 1, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: fmt.Sprintf("Flags: 0x%03X (%s)", flags, flagsDesc), + Filter: fmt.Sprintf("ip.frag_offset == 0x%03X", flags), + Start: linkLayerAndNetworkLayerLen + 12, + Length: 2, + DataSourceIdx: 0, + Tree: []ProtoTree{ + { + Label: fmt.Sprintf(".... ...%d .... = Acknowledgment: %s", flagsACK, flagsACKDesc), + Filter: fmt.Sprintf("tcp.flags.ack == %d", flagsACK), + Start: linkLayerAndNetworkLayerLen + 13, + Length: 1, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 926233912, + URL: "", + }, + { + Label: fmt.Sprintf(".... .... %d... = Push: %s", flagsPSH, flagsPSHDesc), + Filter: fmt.Sprintf("tcp.flags.push == %d", flagsPSH), + Start: linkLayerAndNetworkLayerLen + 13, + Length: 1, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 926233912, + URL: "", + }, + }, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: fmt.Sprintf("Window: %d", window), + Filter: fmt.Sprintf("tcp.window_size_value == %d", window), + Start: linkLayerAndNetworkLayerLen + 14, + Length: 2, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: fmt.Sprintf("Calculated window size: %d", window), + Filter: fmt.Sprintf("tcp.window_size == %d", window), + Start: linkLayerAndNetworkLayerLen + 14, + Length: 2, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: fmt.Sprintf("Checksum: 0x%04x [unverified]", checksum), + Filter: fmt.Sprintf("tcp.checksum == 0x%04x", checksum), + Start: linkLayerAndNetworkLayerLen + 16, + Length: 2, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: "Checksum Status: Unverified", + Filter: "tcp.checksum.status == \"Unverified\"", + Start: 0, + Length: 0, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: fmt.Sprintf("Urgent Pointer: %d", urgent), + Filter: fmt.Sprintf("tcp.urgent_pointer == %d", urgent), + Start: linkLayerAndNetworkLayerLen + 18, + Length: 2, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: fmt.Sprintf("Options: (%d bytes), %s", optionsLen, optionsDesc), + Filter: fmt.Sprintf("tcp.options == %d", optionsLen), + Start: linkLayerAndNetworkLayerLen + 20, + Length: int(optionsLen), + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + { + Label: fmt.Sprintf("TCP payload (%d bytes)", payloadrLen), + Filter: fmt.Sprintf("tcp.payload == %s", payloadStr), + Start: linkLayerAndNetworkLayerLen + 32, + Length: payloadrLen, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "", + Fnum: 0, + URL: "", + }, + }, + Severity: "", + Type: "proto", + Fnum: 1052, + URL: "", + } + + info = fmt.Sprintf("%v -> %v [%s], Seq=%d Ack=%d Win=%d Len=1%d ", srcPort, dstPort, flagsDesc, seq, ack, window, payloadrLen) + logger.Infof("-> TCP, %s", info) + case *layers.UDP: // 用户数据报协议,提供无连接的快速数据传输。 + logger.Infof("-> UDP, length %d", len(layer.Payload)) + case *layers.UDPLite: + logger.Infof("-> UDPLite, length %d", len(layer.Payload)) + case *layers.SCTP: // 流控制传输协议,支持多流和多宿主机。 + logger.Infof("-> SCTP, length %d", len(layer.Payload)) + } + return info, tree +} + +// applicationLayerTree 应用层 +func applicationLayerTree(applicationLayer gopacket.ApplicationLayer) ProtoTree { + var protoTree ProtoTree + switch layer := applicationLayer.(type) { + case *layers.DNS: + logger.Infof("-> DNS, %d", layer.ID) + case *layers.SIP: + logger.Infof("-> SIP, %s", layer.RequestURI) + default: + logger.Infof("-> %s, length %d", layer.LayerType(), layer.Payload()) + if applicationHTTP(layer.LayerContents()) { + logger.Infof("-> HTTP, %s", layer.LayerContents()) + // 偏移量取连接层加网络层加协议层的长度Length + linkLayerAndNetworkLayerAndTransportLayerLen := 14 + 20 + 32 + length := len(layer.LayerContents()) + + protoTree = ProtoTree{ + Label: "Hypertext Transfer Protocol", + Filter: "http", + Start: linkLayerAndNetworkLayerAndTransportLayerLen, + Length: length, + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "Chat", + Fnum: 1052, + URL: "", + } + + result := applicationHTTPProcess(string(layer.LayerContents())) + for _, v := range result { + protoTree.Tree = append(protoTree.Tree, ProtoTree{ + Label: v["label"].(string), + Filter: fmt.Sprintf("http.%s == %s", v["key"].(string), v["value"].(string)), + Start: linkLayerAndNetworkLayerAndTransportLayerLen + v["length"].(int), + Length: v["length"].(int), + DataSourceIdx: 0, + Tree: []ProtoTree{}, + Severity: "", + Type: "Chat", + Fnum: 1052, + URL: "", + }) + } + + } + } + return protoTree +} diff --git a/src/modules/trace/packet_task/packet_frame_util.go b/src/modules/trace/packet_task/packet_frame_util.go new file mode 100644 index 00000000..77d86a9f --- /dev/null +++ b/src/modules/trace/packet_task/packet_frame_util.go @@ -0,0 +1,346 @@ +package packet_task + +import ( + "encoding/binary" + "fmt" + "net" + "strings" + + "github.com/gopacket/gopacket" + "github.com/gopacket/gopacket/layers" +) + +// networkDSCPAndECN 提取 TOS 字段并获取 DSCP 和 ECN +func networkDSCPAndECN(tos uint8) (string, string) { + // 提取 DSCP 和 ECN + dscp := tos >> 2 // 高 6 位 + ecn := tos & 0x03 // 低 2 位 + + // 定义 DSCP 映射 + dscpMapping := map[uint8]string{ + 0: "Default CS0", // Default Forwarding (DF) + 8: "CS1", // Class Selector 1 + 16: "CS2", // Class Selector 2 + 24: "CS3", // Class Selector 3 + 32: "CS4", // Class Selector 4 + 40: "CS5", // Class Selector 5 + 48: "CS6", // Class Selector 6 + 56: "CS7", // Class Selector 7 + } + + // 定义 ECN 映射 + ecnMapping := map[uint8]string{ + 0: "Not-ECT", // Not ECN-Capable Transport + 1: "ECT(1)", // ECN-Capable Transport + 2: "ECT(0)", // ECN-Capable Transport + 3: "CE", // Congestion Experienced + } + + // 返回可读的 DSCP 和 ECN 字符串 + return dscpMapping[dscp], ecnMapping[ecn] +} + +// networkFlagsDesc 生成标志描述 +func networkFlagsDesc(flags layers.IPv4Flag) string { + f := fmt.Sprintf("Flags: 0x%X", flags) + if flags&layers.IPv4DontFragment != 0 { + f += ", Don't fragment" + } + if flags&layers.IPv4MoreFragments != 0 { + f += ", More fragments" + } + return f +} + +// networkFlagsEvil 生成标志描述 Evil +func networkFlagsEvil(flags layers.IPv4Flag) (int, string) { + if flags&layers.IPv4EvilBit != 0 { + return 1, "Set" + } + return 0, "Not set" +} + +// networkFlagsDF 生成标志描述 DF +func networkFlagsDF(flags layers.IPv4Flag) (int, string) { + if flags&layers.IPv4DontFragment != 0 { + return 1, " Set" + } + return 0, "Not set" +} + +// networkFlagsMF 生成标志描述 MF +func networkFlagsMF(flags layers.IPv4Flag) (int, string) { + if flags&layers.IPv4MoreFragments != 0 { + return 1, " Set" + } + return 0, "Not set" +} + +// networkOffset 二进制Fragment Offset表示 ...0 0000 0000 0000 +func networkOffset(offset uint16) string { + return fmt.Sprintf("...0 %04b %04b %04b %04b", + (offset>>12)&0xF, // 高四位 + (offset>>8)&0xF, // 次四位 + (offset>>4)&0xF, // 再次四位 + offset&0xF, // 低四位 + ) +} + +// transportFlagsDesc 生成标志描述 +func transportFlagsDesc(layer *layers.TCP) (byte, string) { + var flags byte + var flagsDesc []string + if layer.FIN { + flags |= 1 << 0 // 0b00000001 + flagsDesc = append(flagsDesc, "FIN") + } + if layer.SYN { + flags |= 1 << 1 // 0b00000010 + flagsDesc = append(flagsDesc, "SYN") + } + if layer.RST { + flags |= 1 << 2 // 0b00000100 + flagsDesc = append(flagsDesc, "RST") + } + if layer.PSH { + flags |= 1 << 3 // 0b00001000 + flagsDesc = append(flagsDesc, "PSH") + } + if layer.ACK { + flags |= 1 << 4 // 0b00010000 + flagsDesc = append(flagsDesc, "ACK") + } + if layer.URG { + flags |= 1 << 5 // 0b00100000 + flagsDesc = append(flagsDesc, "URG") + } + if layer.ECE { + flags |= 1 << 6 // 0b01000000 + flagsDesc = append(flagsDesc, "ECE") + } + if layer.CWR { + flags |= 1 << 7 // 0b10000000 + flagsDesc = append(flagsDesc, "CWR") + } + if layer.NS { + flagsDesc = append(flagsDesc, "NS") + } + + return flags, strings.Join(flagsDesc, ", ") +} + +// transportFlagsStatus 生成标志描述状态 +func transportFlagsStatus(flag bool) (int, string) { + if flag { + return 1, " Set" + } + return 0, "Not set" +} + +// bytesToHexString 转换为十六进制字符串格式 +func bytesToHexString(data []byte) string { + var sb strings.Builder + for i, b := range data { + if i > 0 { + sb.WriteString(":") + } + sb.WriteString(fmt.Sprintf("%02x", b)) + } + return sb.String() +} + +// transportOptions 生成头部选项描述 +func transportOptions(options []layers.TCPOption) (uint8, string) { + var opts []string + var optLen uint8 + for _, opt := range options { + if opt.OptionType == layers.TCPOptionKindMSS && len(opt.OptionData) == 2 { + optLen += opt.OptionLength + opts = append(opts, fmt.Sprintf("%s val %v", + opt.OptionType.String(), + binary.BigEndian.Uint16(opt.OptionData), + )) + } else if opt.OptionType == layers.TCPOptionKindTimestamps && len(opt.OptionData) == 8 { + optLen += opt.OptionLength + opts = append(opts, fmt.Sprintf("%s val %v echo %v", + opt.OptionType.String(), + binary.BigEndian.Uint32(opt.OptionData[:4]), + binary.BigEndian.Uint32(opt.OptionData[4:8]), + )) + } else { + optLen += opt.OptionLength + opts = append(opts, opt.OptionType.String()) + } + } + return optLen, strings.Join(opts, ", ") +} + +// applicationHTTP 辨别 HTTP 数据 +func applicationHTTP(data []byte) bool { + if len(data) == 0 { + return false + } + prefixStr := string(data) + return strings.HasPrefix(prefixStr, "GET ") || strings.HasPrefix(prefixStr, "POST ") || + strings.HasPrefix(prefixStr, "PUT ") || strings.HasPrefix(prefixStr, "DELETE ") || + strings.HasPrefix(prefixStr, "HEAD ") || strings.HasPrefix(prefixStr, "OPTIONS ") || + strings.HasPrefix(prefixStr, "HTTP/") +} + +// applicationHTTP 处理 HTTP 请求 +func applicationHTTPProcess(data string) map[string]map[string]any { + p := make(map[string]map[string]any, 0) + // 按行分割 + lines := strings.Split(data, "\r\n") + for i, line := range lines { + if i == 0 { + label := line + "\r\n" + p[label] = map[string]any{ + "label": label, + "length": len([]byte(label)), + "key": "", + "value": "", + } + continue + } + + // 空行表示头部结束,Body开始 + if line == "" { + break + } + + label := line + "\r\n" + p[label] = map[string]any{ + "label": label, + "length": len([]byte(label)), + "key": "", + "value": "", + } + + // 分割键值对 + parts := strings.SplitN(line, ":", 2) + if len(parts) == 2 { + key := strings.TrimSpace(parts[0]) + value := strings.TrimSpace(parts[1]) + p[label]["key"] = key + p[label]["value"] = value + } + } + return p +} + +// colorRuleFB 着色规则-F前景,B背景 +// +// This file was created by Wireshark. Edit with care. +func colorRuleFB(packet gopacket.Packet) (int, int) { + // Ethernet + if ethernetLayer := packet.Layer(layers.LayerTypeEthernet); ethernetLayer != nil { + eth := ethernetLayer.(*layers.Ethernet) + ethData := eth.Contents + // Broadcast 检查第一个字节的最低位 + // #babdb6, #ffffff + if len(ethData) > 0 && (ethData[0]&1) == 1 { + return 12238262, 16777215 + } + // Routing CDP (Cisco Discovery Protocol) 检查前三个字节 + // #12272e, #fff3d6 + if ethernetLayer.LayerPayload()[0] == 0x01 && ethernetLayer.LayerPayload()[1] == 0x00 && ethernetLayer.LayerPayload()[2] == 0x0c { + return 1189678, 16774102 + } + // Routing CARP (Common Address Redundancy Protocol) uses a specific Ethernet type (0x0800) + // #12272e, #fff3d6 + if ethernetLayer.LayerType() == 0x0800 { + return 1189678, 16774102 + } + } + // ARP + if arpLayer := packet.Layer(layers.LayerTypeARP); arpLayer != nil { + // #12272e, #faf0d7 + return 1189678, 16445655 + } + // ICMP + if icmpLayer := packet.Layer(layers.LayerTypeICMPv4); icmpLayer != nil { + // #12272e, #fce0ff + return 1189678, 16572671 + } + if icmpLayer := packet.Layer(layers.LayerTypeICMPv6); icmpLayer != nil { + // #12272e, #fce0ff + return 1189678, 16572671 + } + // SCTP + if sctpLayer := packet.Layer(layers.LayerTypeSCTP); sctpLayer != nil { + sctp := sctpLayer.(*layers.SCTP) + // SCTP ABORT + // #fffc9c, #a40000 + if sctp.Checksum == 6 { + return 16776348, 10747904 + } + } + // TCP + if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil { + tcp := tcpLayer.(*layers.TCP) + // TCP SYN/FIN + // #12272e, #a0a0a0 + if tcp.SYN && tcp.FIN { + return 1189678, 10526880 + } + // TCP RST + // #fffc9c, #a40000 + if tcp.RST { + return 16776348, 10747904 + } + // HTTP + // #12272e, #e4ffc7 + if tcp.SrcPort == 80 || tcp.DstPort == 80 || tcp.SrcPort == 443 || tcp.DstPort == 443 { + return 1189678, 15007687 + } + // 检查 SMB - 通常基于 TCP 445 或 139 + // #12272e, #feffd0 + if tcp.SrcPort == 445 || tcp.DstPort == 445 || tcp.SrcPort == 139 || tcp.DstPort == 139 { + return 1189678, 16711632 + } + // Routing BGP usually runs on TCP port 179 + // #12272e, #fff3d6 + if tcp.DstPort == 179 || tcp.SrcPort == 179 { + return 1189678, 16774102 + } + } + // UDP + if udpLayer := packet.Layer(layers.LayerTypeUDP); udpLayer != nil { + udp := udpLayer.(*layers.UDP) + // 检查 SMB NetBIOS 名称服务 (NBNS) - 端口 53 + // 检查 SMB NetBIOS 数据报服务 (NBDS) - 端口 138 + if udp.SrcPort == 53 || udp.DstPort == 53 || udp.SrcPort == 138 || udp.DstPort == 138 { + return 1189678, 16711632 + } + } + // IPv4 + if ipv4Layer := packet.Layer(layers.LayerTypeIPv4); ipv4Layer != nil { + ipv4 := ipv4Layer.(*layers.IPv4) + // TCP(6) + // #12272e, #e7e6ff + if ipv4.Protocol == layers.IPProtocolTCP { + return 1189678, 15197951 + } + // UDP(17) + // #12272e, #daeeff + if ipv4.Protocol == layers.IPProtocolUDP || ipv4.Protocol == layers.IPProtocolUDPLite { + return 1189678, 14348031 + } + // Routing EIGRP(0x2f) OSPF(89) + // #12272e, #fff3d6 + if ipv4.Protocol == 0x2f || ipv4.Protocol == layers.IPProtocolOSPF { + return 1189678, 16774102 + } + // Routing + // GVRP (GARP VLAN Registration Protocol) + // GVRP typically utilizes the same multicast address as GARP + // HSRP (Hot Standby Router Protocol) uses multicast IP 224.0.0.2 + // VRRP (Virtual Router Redundancy Protocol) uses multicast IP 224.0.0.18 + // #12272e, #fff3d6 + if ipv4.DstIP.Equal(net.IPv4(224, 0, 0, 2)) || ipv4.DstIP.Equal(net.IPv4(224, 0, 0, 100)) { + return 1189678, 16774102 + } + } + return 16222087, 1189678 // 默认颜色值 #f78787, #12272e +} diff --git a/src/modules/trace/service/packet.go b/src/modules/trace/service/packet.go index 9b6e8f8a..64cc6430 100644 --- a/src/modules/trace/service/packet.go +++ b/src/modules/trace/service/packet.go @@ -1,46 +1,21 @@ package service import ( - "context" - "fmt" - "os" - "strings" - "sync" - "time" - - "be.ems/src/framework/logger" "be.ems/src/framework/vo" - "github.com/gopacket/gopacket" - "github.com/gopacket/gopacket/pcap" - "github.com/gopacket/gopacket/pcapgo" + packetTask "be.ems/src/modules/trace/packet_task" ) // 实例化服务层 Packet 结构体 -var NewPacket = &Packet{ - taskMap: sync.Map{}, -} +var NewPacket = &Packet{} // 信令跟踪 服务层处理 -type Packet struct { - taskMap sync.Map // 捕获任务 -} - -// task 任务信息 -type task struct { - TaskNo string // 任务编号 - Handle *pcap.Handle // 捕获句柄 - File *os.File // 捕获信息输出文件句柄 - Writer *pcapgo.Writer // 捕获信息输出句柄 - Expire time.Time // 过期时间 - context context.Context // 上下文 控制完成结束 -} +type Packet struct{} // NetworkDevices 获取网卡设备信息 func (s *Packet) NetworkDevices() []vo.TreeSelect { arr := make([]vo.TreeSelect, 0) - devices, err := pcap.FindAllDevs() + devices, err := packetTask.NetworkDevices() if err != nil { - logger.Errorf("interfaces find all devices err: %s", err.Error()) return arr } @@ -71,121 +46,22 @@ func (s *Packet) NetworkDevices() []vo.TreeSelect { return arr } -// verifyDevice 检查网卡设备是否存在 -func (s *Packet) verifyDevice(str string) (string, bool) { - devices, err := pcap.FindAllDevs() - if err != nil { - logger.Errorf("interfaces find all devices err: %s", err.Error()) - return "", false - } - for _, device := range devices { - if len(device.Addresses) == 0 { - continue - } - if device.Name == str { - return device.Name, true - } - for _, address := range device.Addresses { - if address.IP.String() == str { - return device.Name, true - } - } - } - return "", false -} - // LiveStart 开始捕获数据 -func (s *Packet) LiveStart(taskNo, deviceName, outputFile string) (string, error) { - if _, ok := s.taskMap.Load(taskNo); ok { - return "", fmt.Errorf("task no. %s already exist", taskNo) - } - - // Verify the specified network interface exists - device, deviceOk := s.verifyDevice(deviceName) - if !deviceOk { - return "", fmt.Errorf("network device not exist: %s", deviceName) - } - - snapshotLength := 262144 - - // open device - handle, err := pcap.OpenLive(device, int32(snapshotLength), true, pcap.BlockForever) - if err != nil { - logger.Errorf("open live err: %s", err.Error()) - if strings.Contains(err.Error(), "operation not permitted") { - return "", fmt.Errorf("you don't have permission to capture on that/these device(s)") - } - return "", err - } - - // write a new file - var w *pcapgo.Writer - var f *os.File - if outputFile != "" { - f, err = os.Create(outputFile) - if err != nil { - return "", err - } - w = pcapgo.NewWriter(f) - w.WriteFileHeader(uint32(snapshotLength), handle.LinkType()) - } - - // capture packets - packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) - packetSource.Lazy = false - packetSource.NoCopy = true - packetSource.DecodeStreamsAsDatagrams = true - - // save tasks - ctx := context.Background() - task := &task{ - TaskNo: taskNo, - Handle: handle, - File: f, - Writer: w, - Expire: time.Now().Add(time.Second * 120), - context: ctx, - } - s.taskMap.Store(taskNo, task) - - // start capture - go func() { - for packet := range packetSource.PacketsCtx(ctx) { - if packet == nil { - continue - } - if packet.Metadata().Timestamp.Before(time.Now()) { - continue - } - if w != nil { - w.WritePacket(packet.Metadata().CaptureInfo, packet.Data()) - } - fmt.Println(packet.Dump()) - } - }() - return "task initiated", nil +func (s *Packet) LiveStart(taskNo, deviceName, filterBPF string, outputPCAP bool) (string, error) { + return packetTask.LiveStart(taskNo, deviceName, filterBPF, outputPCAP) } // LiveFilter 捕获过滤 func (s *Packet) LiveFilter(taskNo, expr string) error { - info, ok := s.taskMap.Load(taskNo) - if !ok { - return fmt.Errorf("task no. %s not exist", taskNo) - } - return info.(*task).Handle.SetBPFFilter(expr) + return packetTask.LiveFilter(taskNo, expr) +} + +// LiveTimeout 更新捕获失效时间 +func (s *Packet) LiveTimeout(taskNo string, seconds int) error { + return packetTask.LiveTimeout(taskNo, seconds) } // LiveStop 停止捕获数据 func (s *Packet) LiveStop(taskNo string) error { - info, ok := s.taskMap.Load(taskNo) - if !ok { - return fmt.Errorf("task no. %s not exist", taskNo) - } - info.(*task).context.Done() - info.(*task).Handle.Close() - if info.(task).File != nil { - info.(task).File.Close() - } - s.taskMap.Delete(taskNo) - return nil + return packetTask.LiveStop(taskNo) } diff --git a/src/modules/trace/service/trace_task.go b/src/modules/trace/service/trace_task.go index fbfb1643..bc1682c7 100644 --- a/src/modules/trace/service/trace_task.go +++ b/src/modules/trace/service/trace_task.go @@ -96,7 +96,7 @@ func (r *TraceTask) CreateUDP() error { // 推送文件 if v, ok := mData["pcapFile"]; ok && v != "" { logger.Infof("pcapFile: %s", v) - wsService.NewWSSend.ByGroupID(fmt.Sprintf("%s%d", wsService.GROUP_TRACE, taskId), taskId) + wsService.NewWSSend.ByGroupID(fmt.Sprintf("%s%d", wsService.GROUP_TRACE_NE, taskId), taskId) } }) @@ -145,7 +145,7 @@ func (r *TraceTask) CreateUDP() error { // 推送文件 if v, ok := mData["pcapFile"]; ok && v != "" { logger.Infof("pcapFile: %s", v) - wsService.NewWSSend.ByGroupID(fmt.Sprintf("%s%d", wsService.GROUP_TRACE, taskId), taskId) + wsService.NewWSSend.ByGroupID(fmt.Sprintf("%s%d", wsService.GROUP_TRACE_NE, taskId), taskId) } }) return nil diff --git a/src/modules/trace/trace.go b/src/modules/trace/trace.go index 98ff72da..3ffb0ab2 100644 --- a/src/modules/trace/trace.go +++ b/src/modules/trace/trace.go @@ -65,7 +65,6 @@ func Setup(router *gin.Engine) { ) packetGroup.PUT("/keep-alive", middleware.PreAuthorize(nil), - collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.packet", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewPacket.KeepAlive, ) } diff --git a/src/modules/ws/service/ws_send.go b/src/modules/ws/service/ws_send.go index 04fff1f9..4d024143 100644 --- a/src/modules/ws/service/ws_send.go +++ b/src/modules/ws/service/ws_send.go @@ -12,13 +12,15 @@ import ( const ( // 组号-其他 GROUP_OTHER = "0" - // 组号-跟踪任务数据变更 2_traceId - GROUP_TRACE = "2_" + // 组号-跟踪任务网元数据变更 2_traceId + GROUP_TRACE_NE = "2_" + // 组号-信令跟踪Packet 4_taskNo + GROUP_TRACE_PACKET = "4_" // 组号-指标通用 10_neType_neId GROUP_KPI = "10_" // 组号-指标UPF 12_neId GROUP_KPI_UPF = "12_" - // 组号-自定义KPI指标20_neType_neId + // 组号-自定义KPI指标 20_neType_neId GROUP_KPI_C = "20_" // 组号-IMS_CDR会话事件 1005_neId GROUP_IMS_CDR = "1005_" diff --git a/sshsvc/setHLRServiceState b/sshsvc/setHLRServiceState index c792036b..dee6e381 100644 --- a/sshsvc/setHLRServiceState +++ b/sshsvc/setHLRServiceState @@ -2,21 +2,22 @@ TargetIP="[2001:db8::9166]" PORT="34957" +OID=".1.3.6.1.4.1.1379.2.3.3.3.1.1.9.0" case "$1" in 1) echo -n "Set HLR state link down ... " - snmpset -v3 -l noAuthNoPriv -u manager ${TargetIP}:${PORT} .1.3.6.1.4.1.1379.2.3.3.3.1.1.9.0 i 1 >/dev/null + snmpset -v3 -l noAuthNoPriv -u manager ${TargetIP}:${PORT} ${OID} i 1 >/dev/null echo "done" ;; 2) echo -n "Set HLR state link up ... " - snmpset -v3 -l noAuthNoPriv -u manager ${TargetIP}:${PORT} .1.3.6.1.4.1.1379.2.3.3.3.1.1.9.0 i 2 >/dev/null + snmpset -v3 -l noAuthNoPriv -u manager ${TargetIP}:${PORT} ${OID} i 2 >/dev/null echo "done" ;; 3) echo -n "Set HLR state authentication failure ... " - snmpset -v3 -l noAuthNoPriv -u manager ${TargetIP}:${PORT} .1.3.6.1.4.1.1379.2.3.3.3.1.1.9.0 i 3 >/dev/null + snmpset -v3 -l noAuthNoPriv -u manager ${TargetIP}:${PORT} ${OID} i 3 >/dev/null echo "done" ;; *)