Получение списка аварий из OSS через интерфейс AlarmIRP

Здравствуйте. Данная тема очень слабо раскрыта в Сети поскольку представляет интерес лишь в узких кругах. Чтобы немного восполнить этот пробел, данное место мне видится наиболее подходящим.

Интерфейс CORBA AlarmIRP присутствует во всех системах управления производителей оборудования с которыми мне пришлось столкнуться, поскольку предписан стандартом 3GPP 3G TS 32.106-2. Рассмотрим на примере OSS-RC Ericsson, в чьей документации процесс хоть как-то описан. Для NetAct Nokia и M-2000 Huawei код будет примерно такой же, с отличиями в нюансах реализации одного стандарта. Я постараюсь максимально понятно описать процесс создания приложения для чтения списка аварийных сообщений, но, поскольку, ранее я никогда не писал ничего на Java и не работал с CORBA некоторые детали позволю себе оставить за рамками данной статьи.

Всё приложении можно разбить на 3 части:

  1. получение IOR интерфейса
  2. создание объекта ссылающегося на интерфейс
  3. вызов методов интерфейса

Итак, согласно документации IOR хранится в двух местах: в файле

/var/opt/ericsson/blkcm/data/bulkcm.nameservice

и на web-сервере

http://«masterhost ip»:80/ior/ExternalNameService.ior

Воспользуемся первым способом:

private String readIOR() {         String mastersvc = "/var/opt/ericsson/blkcm/data/bulkcm.nameservice";         File f = new File(mastersvc);         BufferedReader br;         String iorContents = null; 		try { 			br = new BufferedReader(new FileReader(f)); 	        	iorContents = br.readLine(); 	        	br.close(); 		} catch (IOException e) { 			e.printStackTrace(); 		}         return iorContents; } 

Если быть точным, то метод выше нам вернёт не IOR, а ссылку на NameService (терминология CORBA), которую мы могли бы получить из IOR-файла на web-сервере. Если проще: результат мы будем использовать для инициализации подключения.

Второй этап инициализация объекта подключения ORB:

public void createAlarmObj(){ 	org.omg.CORBA.Object rootObj = null; 	NamingContextExt rootNameCon = null; 	Properties props = new Properties(); 	props.put("org.omg.CORBA.ORBInitRef", "NameService=" + readIOR()); 	org.omg.CORBA.ORB orb = ORB.init(new String[0], props); 	// Resolve the CORBA Naming Service  	try { 		rootObj = orb.resolve_initial_references("NameService"); 		rootNameCon = NamingContextExtHelper.narrow(rootObj); 		String s = "com/ericsson/nms/fm_cirpagent/AlarmIRP"; 		//Locate Alarm IRP 		rootObj = rootNameCon.resolve(rootNameCon.to_name(s)); 		_alarmIrp = com.ericsson.irp.AlarmIRPSystem._AlarmIRPOperationsHelper.narrow(rootObj); 	} catch (InvalidName | NotFound | CannotProceed | org.omg.CosNaming.NamingContextPackage.InvalidName e) { 		e.printStackTrace(); 	} } 

Теперь у нас есть ссылка на объект к которому мы можем обращаться вызывая его методы. В частности метод get_alarm_list и возвращает нужный нам список. Вот его поисание из 3GPP:

This method returns Alarm Informations. If flag is
TRUE, all returned Alarm Informations shall be in AlarmInformationSeq
that contains 0,1 or more Alarm Informations. Output parameter iter
shall be useless. If flag is FALSE, no Alarm Information shall be
in AlarmInformationSeq. IRPAgent needs to use iter to retrieve them.

public void getActiveAlarms(){ 	BooleanHolder flag = new BooleanHolder(false);  // false for iteration 	com.ericsson.irp.AlarmIRPSystem.AlarmInformationIteratorHolder iter = new com.ericsson.irp.AlarmIRPSystem.AlarmInformationIteratorHolder(); 	try { 		_alarmIrp.get_alarm_list(alarmFilter, flag, iter); 		EventBatchHolder alarmInformation = new EventBatchHolder(); 		short alarmSize = 100; 		List<StructuredEvent> alarms = new ArrayList<StructuredEvent>(); 		boolean haveMoreAlarms = false; 		do{ 			if (iter.value != null) { 				haveMoreAlarms = iter.value.next_alarmInformations(alarmSize, alarmInformation); 				alarms.addAll(Arrays.asList(alarmInformation.value)); 			} 		}while (haveMoreAlarms); 			for (StructuredEvent alarm: alarms) { 				alarmPrint(alarm); 			} 		} 	} catch (GetAlarmList | ParameterNotSupported | InvalidParameter | NextAlarmInformations e) { 		e.printStackTrace(); 	} } 

Данный метод получает итератор содержащий список аварий в виде объектов типа StructuredEvent которые затем выводит в консоль alarmPrint(alarm). Запись StructuredEvent содержит заголовок header и, собственно, данные filterable_data. Данные это тоже запись имеющая имя name и значение value. Описание полей тоже есть в стандарте:

const string NV_NOTIFICATION_ID =«a»;
const string NV_CORRELATED_NOTIFICATIONS = «b»;
const string NV_EVENT_TIME = «c»;
const string NV_SYSTEM_DN = «d»;
const string NV_MANAGED_OBJECT_CLASS = «e»;
const string NV_MANAGED_OBJECT_INSTANCE= «f»;
const string NV_SPECIFIC_PROBLEM = «i»;

Теперь всё это соберём вместе и выведем для примера instance и specific_problem:

private void alarmPrint(StructuredEvent alarm){ 	String result = "" 	if (alarm.filterable_data != null) { 		for (Property filterableData: alarm.filterable_data) { 			String fieldName = filterableData.name; 			switch (fieldName){ 				case "f": 					result = result + filterableData.value.extract_string() + ";"; 					break; 				case "i": 					result = result + filterableData.value.extract_string(); 					break; 			} 		} 	} 	System.out.println(result); } 

Наконец полный код полученного черновика:

Полный код

import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Properties; import org.omg.CORBA.*; import org.omg.CORBA.ORBPackage.InvalidName; import org.omg.CosNaming.NamingContextExt; import org.omg.CosNaming.NamingContextExtHelper; import org.omg.CosNaming.NamingContextPackage.CannotProceed; import org.omg.CosNaming.NamingContextPackage.NotFound; import org.omg.CosNotification.EventBatchHolder; import org.omg.CosNotification.Property; import org.omg.CosNotification.StructuredEvent; import com.ericsson.irp.AlarmIRPSystem.GetAlarmList; import com.ericsson.irp.AlarmIRPSystem.InvalidParameter; import com.ericsson.irp.AlarmIRPSystem.NextAlarmInformations; import com.ericsson.irp.AlarmIRPSystem.ParameterNotSupported;   public class AlarmClient {  	private com.ericsson.irp.AlarmIRPSystem._AlarmIRPOperations _alarmIrp = null; 	 	public static void main(String[] args) { 		AlarmClient ac = new AlarmClient(); 		ac.createAlarmObj(); 		ac.getActiveAlarms(); 	} 	 	private String readIOR() {         File f = new File("/var/opt/ericsson/blkcm/data/bulkcm.nameservice");         BufferedReader br;         String iorContents = null; 		try { 			br = new BufferedReader(new FileReader(f)); 	        iorContents = br.readLine(); 	        br.close(); 		} catch (IOException e) { 			e.printStackTrace(); 		}         return iorContents; 	} 	 	public void createAlarmObj(){ 		org.omg.CORBA.Object rootObj = null; 		NamingContextExt rootNameCon = null; 		Properties props = new Properties(); 		props.put("org.omg.CORBA.ORBInitRef", "NameService=" + readIOR()); 		org.omg.CORBA.ORB orb = ORB.init(new String[0], props); 		// Resolve the CORBA Naming Service  		try { 			rootObj = orb.resolve_initial_references("NameService"); 			rootNameCon = NamingContextExtHelper.narrow(rootObj); 			String s = "com/ericsson/nms/fm_cirpagent/AlarmIRP"; 			//Locate Alarm IRP 			rootObj = rootNameCon.resolve(rootNameCon.to_name(s)); 			_alarmIrp = com.ericsson.irp.AlarmIRPSystem._AlarmIRPOperationsHelper.narrow(rootObj); 			//System.out.println(_alarmIrp); 		} catch (InvalidName | NotFound | CannotProceed | org.omg.CosNaming.NamingContextPackage.InvalidName e) { 			e.printStackTrace(); 		} 	}  	public void getActiveAlarms(){ 		BooleanHolder flag = new BooleanHolder(false);  // false for iteration 		com.ericsson.irp.AlarmIRPSystem.AlarmInformationIteratorHolder iter = new com.ericsson.irp.AlarmIRPSystem.AlarmInformationIteratorHolder(); 		try { 			_alarmIrp.get_alarm_list("", flag, iter); 			EventBatchHolder alarmInformation = new EventBatchHolder(); 			short alarmSize = 100; 			List<StructuredEvent> alarms = new ArrayList<StructuredEvent>(); 			boolean haveMoreAlarms = false; 			do{ 				if (iter.value != null) { 					haveMoreAlarms = iter.value.next_alarmInformations(alarmSize, alarmInformation); 					alarms.addAll(Arrays.asList(alarmInformation.value)); 				} 			}while (haveMoreAlarms); 			if (iter.value != null) { 				for (StructuredEvent alarm: alarms) { 					alarmPrint(alarm); 				} 			} 		} catch (GetAlarmList | ParameterNotSupported | InvalidParameter | NextAlarmInformations e) { 			e.printStackTrace(); 		} 	} 	 	private void alarmPrint(StructuredEvent alarm){ 		String result = ""; 		if (alarm.filterable_data != null) { 			for (Property filterableData: alarm.filterable_data) { 				String fieldName = filterableData.name; 				switch (fieldName){ 					case "f": 						result = result + filterableData.value.extract_string() + ";"; 						break; 					case "i": 						result = result + filterableData.value.extract_string(); 						break; 				} 			} 		} 		System.out.println(result); 	} } 

Запуск производится командой:

java -cp .:/opt/ericsson/fm_core/classes/alarmirp.jar AlarmClient

Что в итоге: кроме «фана» я других применений пока не использую. В перспективе есть ещё NotificationIRP — получение событий сразу после их появления, BulkCmIRP — конфигурирование из внешней системы и т.д. Технология аналогичная, но при необходимости можно написать отдельную статью. По этой теме, пожалуй, всё. На вопросы могу ответить в комментариях. Спасибо!

FavoriteLoadingДобавить в избранное
Posted in Без рубрики

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *