Committed by
Gerrit Code Review
[ONOS-3203] End-to-end demo of Fault Management via SNMP.
This adds SNMP device-discovery, and a Fault Management app which makes alarms available to users via REST/GUI/CLI interfaces. There is still code cleanup that could be done, but aim of this commit is an end-to-end proof of concept. To demonstrate : 1) /opt/onos/bin/onos-service onos> app activate org.onosproject.snmp onos> app activate org.onosproject.faultmanagement 2) SNMP devices are seeded via config file. The default seed file contains connection details for devices (SNMP agents) available via internet e.g. demo.snmplabs.com cp /opt/onos/apache-karaf-3.0.3/etc/samples/org.onosproject.provider.snmp.device.impl.SnmpDeviceProvider.cfg /opt/onos/apache-karaf-3.0.3/etc/ 3) ONOS will poll these SNMP devices and store their alarms. 4) You can now manipulate the alarms via REST e.g. http://<onos>:8181/onos/v1/fm/alarms , via CLI via various "alarm-*” commands or in UI with an Alarms Overlay. More info at https://wiki.onosproject.org/display/ONOS/Fault+Management 15/Dec/15: Updated regarding review comments from Thomas Vachuska. 17/Dec/15: Updated coreService.registerApplication(name) as per https://gerrit.onosproject.org/#/c/6878/ Change-Id: I886f8511f178dc4600ab96e5ff10cc90329cabec
Showing
76 changed files
with
4194 additions
and
369 deletions
... | @@ -21,4 +21,6 @@ | ... | @@ -21,4 +21,6 @@ |
21 | 21 | ||
22 | <artifact>mvn:${project.groupId}/onos-app-fm-mgr/${project.version}</artifact> | 22 | <artifact>mvn:${project.groupId}/onos-app-fm-mgr/${project.version}</artifact> |
23 | <artifact>mvn:${project.groupId}/onos-app-fm-web/${project.version}</artifact> | 23 | <artifact>mvn:${project.groupId}/onos-app-fm-web/${project.version}</artifact> |
24 | + <artifact>mvn:${project.groupId}/onos-app-fm-gui/${project.version}</artifact> | ||
25 | + <artifact>mvn:${project.groupId}/onos-app-fm-cli/${project.version}</artifact> | ||
24 | </app> | 26 | </app> | ... | ... |
... | @@ -21,5 +21,7 @@ | ... | @@ -21,5 +21,7 @@ |
21 | <feature>onos-drivers</feature> | 21 | <feature>onos-drivers</feature> |
22 | <bundle>mvn:${project.groupId}/onos-app-fm-mgr/${project.version}</bundle> | 22 | <bundle>mvn:${project.groupId}/onos-app-fm-mgr/${project.version}</bundle> |
23 | <bundle>mvn:${project.groupId}/onos-app-fm-web/${project.version}</bundle> | 23 | <bundle>mvn:${project.groupId}/onos-app-fm-web/${project.version}</bundle> |
24 | + <bundle>mvn:${project.groupId}/onos-app-fm-gui/${project.version}</bundle> | ||
25 | + <bundle>mvn:${project.groupId}/onos-app-fm-cli/${project.version}</bundle> | ||
24 | </feature> | 26 | </feature> |
25 | </features> | 27 | </features> | ... | ... |
1 | <?xml version="1.0" encoding="UTF-8"?> | 1 | <?xml version="1.0" encoding="UTF-8"?> |
2 | <!-- | 2 | <!-- |
3 | - ~ Copyright 2015 Open Networking Laboratory | 3 | +~ Copyright 2015 Open Networking Laboratory |
4 | - ~ | 4 | +~ |
5 | - ~ Licensed under the Apache License, Version 2.0 (the "License"); | 5 | +~ Licensed under the Apache License, Version 2.0 (the "License"); |
6 | - ~ you may not use this file except in compliance with the License. | 6 | +~ you may not use this file except in compliance with the License. |
7 | - ~ You may obtain a copy of the License at | 7 | +~ You may obtain a copy of the License at |
8 | - ~ | 8 | +~ |
9 | - ~ http://www.apache.org/licenses/LICENSE-2.0 | 9 | +~ http://www.apache.org/licenses/LICENSE-2.0 |
10 | - ~ | 10 | +~ |
11 | - ~ Unless required by applicable law or agreed to in writing, software | 11 | +~ Unless required by applicable law or agreed to in writing, software |
12 | - ~ distributed under the License is distributed on an "AS IS" BASIS, | 12 | +~ distributed under the License is distributed on an "AS IS" BASIS, |
13 | - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 13 | +~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
14 | - ~ See the License for the specific language governing permissions and | 14 | +~ See the License for the specific language governing permissions and |
15 | - ~ limitations under the License. | 15 | +~ limitations under the License. |
16 | - --> | 16 | +--> |
17 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | 17 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
18 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | 18 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> |
19 | <modelVersion>4.0.0</modelVersion> | 19 | <modelVersion>4.0.0</modelVersion> |
... | @@ -28,7 +28,7 @@ | ... | @@ -28,7 +28,7 @@ |
28 | <artifactId>onos-app-fm-onosfw</artifactId> | 28 | <artifactId>onos-app-fm-onosfw</artifactId> |
29 | <packaging>pom</packaging> | 29 | <packaging>pom</packaging> |
30 | 30 | ||
31 | - <description>ONOS framework applications</description> | 31 | + <description>ONOS fault management application</description> |
32 | 32 | ||
33 | <dependencies> | 33 | <dependencies> |
34 | <dependency> | 34 | <dependency> |
... | @@ -41,6 +41,15 @@ | ... | @@ -41,6 +41,15 @@ |
41 | <artifactId>onos-app-fm-mgr</artifactId> | 41 | <artifactId>onos-app-fm-mgr</artifactId> |
42 | <version>${project.version}</version> | 42 | <version>${project.version}</version> |
43 | </dependency> | 43 | </dependency> |
44 | + <dependency> | ||
45 | + <groupId>org.onosproject</groupId> | ||
46 | + <artifactId>onos-app-fm-gui</artifactId> | ||
47 | + <version>${project.version}</version> | ||
48 | + </dependency> | ||
49 | + <dependency> | ||
50 | + <groupId>org.onosproject</groupId> | ||
51 | + <artifactId>onos-app-fm-cli</artifactId> | ||
52 | + <version>${project.version}</version> | ||
53 | + </dependency> | ||
44 | </dependencies> | 54 | </dependencies> |
45 | - | ||
46 | </project> | 55 | </project> | ... | ... |
apps/faultmanagement/fmcli/pom.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<!-- | ||
3 | +~ Copyright 2015 Open Networking Laboratory | ||
4 | +~ | ||
5 | +~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | +~ you may not use this file except in compliance with the License. | ||
7 | +~ You may obtain a copy of the License at | ||
8 | +~ | ||
9 | +~ http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | +~ | ||
11 | +~ Unless required by applicable law or agreed to in writing, software | ||
12 | +~ distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | +~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | +~ See the License for the specific language governing permissions and | ||
15 | +~ limitations under the License. | ||
16 | +--> | ||
17 | +<project | ||
18 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" | ||
19 | + xmlns="http://maven.apache.org/POM/4.0.0" | ||
20 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | ||
21 | + | ||
22 | + <modelVersion>4.0.0</modelVersion> | ||
23 | + | ||
24 | + <parent> | ||
25 | + <groupId>org.onosproject</groupId> | ||
26 | + <artifactId>onos-app-fm</artifactId> | ||
27 | + <version>1.4.0-SNAPSHOT</version> | ||
28 | + <relativePath>../pom.xml</relativePath> | ||
29 | + </parent> | ||
30 | + | ||
31 | + <artifactId>onos-app-fm-cli</artifactId> | ||
32 | + <packaging>bundle</packaging> | ||
33 | + <dependencies> | ||
34 | + <dependency> | ||
35 | + <groupId>org.onosproject</groupId> | ||
36 | + <artifactId>onlab-osgi</artifactId> | ||
37 | + <version>${project.version}</version> | ||
38 | + </dependency> | ||
39 | + | ||
40 | + <dependency> | ||
41 | + <groupId>org.onosproject</groupId> | ||
42 | + <artifactId>onlab-junit</artifactId> | ||
43 | + <scope>test</scope> | ||
44 | + </dependency> | ||
45 | + | ||
46 | + <dependency> | ||
47 | + <groupId>org.apache.felix</groupId> | ||
48 | + <artifactId>org.apache.felix.scr.annotations</artifactId> | ||
49 | + <scope>provided</scope> | ||
50 | + </dependency> | ||
51 | + <dependency> | ||
52 | + <groupId>org.onosproject</groupId> | ||
53 | + <artifactId>onos-cli</artifactId> | ||
54 | + <version>${project.version}</version> | ||
55 | + </dependency> | ||
56 | + <dependency> | ||
57 | + <groupId>org.apache.karaf.shell</groupId> | ||
58 | + <artifactId>org.apache.karaf.shell.console</artifactId> | ||
59 | + </dependency> | ||
60 | + </dependencies> | ||
61 | +</project> |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.faultmanagement.alarms.cli; | ||
17 | + | ||
18 | +import java.util.Set; | ||
19 | +import org.apache.commons.lang3.builder.ToStringBuilder; | ||
20 | +import org.apache.commons.lang3.builder.ToStringStyle; | ||
21 | +import org.apache.karaf.shell.commands.Command; | ||
22 | +import org.onosproject.cli.AbstractShellCommand; | ||
23 | +import org.onosproject.incubator.net.faultmanagement.alarm.Alarm; | ||
24 | +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmService; | ||
25 | + | ||
26 | +/** | ||
27 | + * Lists active alarms across all devices. | ||
28 | + */ | ||
29 | +@Command(scope = "onos", name = "alarm-list-active", | ||
30 | + description = "Lists all the ACTIVE alarms across all devices.") | ||
31 | +public class GetAllActiveAlarms extends AbstractShellCommand { | ||
32 | + | ||
33 | + | ||
34 | + @Override | ||
35 | + protected void execute() { | ||
36 | + printAlarms(AbstractShellCommand.get(AlarmService.class).getActiveAlarms()); | ||
37 | + } | ||
38 | + | ||
39 | + void printAlarms(Set<Alarm> alarms) { | ||
40 | + alarms.stream().forEach((alarm) -> { | ||
41 | + print(ToStringBuilder.reflectionToString(alarm, ToStringStyle.SHORT_PREFIX_STYLE)); | ||
42 | + }); | ||
43 | + } | ||
44 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.faultmanagement.alarms.cli; | ||
17 | + | ||
18 | +import java.util.Set; | ||
19 | +import org.apache.commons.lang3.builder.ToStringBuilder; | ||
20 | +import org.apache.commons.lang3.builder.ToStringStyle; | ||
21 | +import org.apache.karaf.shell.commands.Command; | ||
22 | +import org.onosproject.cli.AbstractShellCommand; | ||
23 | +import org.onosproject.incubator.net.faultmanagement.alarm.Alarm; | ||
24 | +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmService; | ||
25 | + | ||
26 | +/** | ||
27 | + * Lists alarms across all devices. | ||
28 | + */ | ||
29 | +@Command(scope = "onos", name = "alarm-list", | ||
30 | + description = "Lists active alarms across all devices.") | ||
31 | +public class GetAllAlarms extends AbstractShellCommand { | ||
32 | + | ||
33 | + @Override | ||
34 | + protected void execute() { | ||
35 | + printAlarms(AbstractShellCommand.get(AlarmService.class).getAlarms()); | ||
36 | + } | ||
37 | + | ||
38 | + void printAlarms(Set<Alarm> alarms) { | ||
39 | + alarms.stream().forEach((alarm) -> { | ||
40 | + print(ToStringBuilder.reflectionToString(alarm, ToStringStyle.SHORT_PREFIX_STYLE)); | ||
41 | + }); | ||
42 | + } | ||
43 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.faultmanagement.alarms.cli; | ||
17 | + | ||
18 | +import java.util.Map; | ||
19 | +import org.apache.karaf.shell.commands.Command; | ||
20 | +import org.onosproject.cli.AbstractShellCommand; | ||
21 | +import org.onosproject.incubator.net.faultmanagement.alarm.Alarm; | ||
22 | +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmService; | ||
23 | + | ||
24 | +/** | ||
25 | + * Lists alarm counts across all devices. | ||
26 | + */ | ||
27 | +@Command(scope = "onos", name = "alarm-counts", | ||
28 | + description = "Lists alarm counts across all devices.") | ||
29 | +public class GetAllAlarmsCounts extends AbstractShellCommand { | ||
30 | + | ||
31 | + @Override | ||
32 | + protected void execute() { | ||
33 | + Map<Alarm.SeverityLevel, Long> alarmCounts | ||
34 | + = AbstractShellCommand.get(AlarmService.class).getAlarmCounts(); | ||
35 | + printCounts(alarmCounts); | ||
36 | + } | ||
37 | + | ||
38 | + static void printCounts(Map<Alarm.SeverityLevel, Long> alarmCounts) { | ||
39 | + alarmCounts.entrySet().stream().forEach((countEntry) -> { | ||
40 | + System.out.println(String.format("%s, %d", | ||
41 | + countEntry.getKey(), countEntry.getValue())); | ||
42 | + | ||
43 | + }); | ||
44 | + } | ||
45 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.faultmanagement.alarms.cli; | ||
17 | + | ||
18 | +import java.util.Map; | ||
19 | +import org.apache.karaf.shell.commands.Argument; | ||
20 | +import org.apache.karaf.shell.commands.Command; | ||
21 | +import org.onosproject.cli.AbstractShellCommand; | ||
22 | +import org.onosproject.incubator.net.faultmanagement.alarm.Alarm; | ||
23 | +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmService; | ||
24 | +import org.onosproject.net.DeviceId; | ||
25 | + | ||
26 | +/** | ||
27 | + * Lists alarm counts across specified device. | ||
28 | + */ | ||
29 | +@Command(scope = "onos", name = "alarm-counts-device", | ||
30 | + description = "Lists alarm counts across specified device.") | ||
31 | +public class GetDeviceAlarmsCounts extends AbstractShellCommand { | ||
32 | + | ||
33 | + @Argument(index = 0, name = "deviceId", description = "Device identity", required = true, multiValued = false) | ||
34 | + String deviceId = null; | ||
35 | + | ||
36 | + @Override | ||
37 | + protected void execute() { | ||
38 | + Map<Alarm.SeverityLevel, Long> alarmCounts = AbstractShellCommand.get(AlarmService.class). | ||
39 | + getAlarmCounts(DeviceId.deviceId(deviceId)); | ||
40 | + // Deliberately using same formatting for both ... | ||
41 | + GetAllAlarmsCounts.printCounts(alarmCounts); | ||
42 | + } | ||
43 | + | ||
44 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +/** | ||
18 | + * CLI implementation for alarms. | ||
19 | + */ | ||
20 | +package org.onosproject.faultmanagement.alarms.cli; |
1 | +<!-- | ||
2 | +~ Copyright 2015 Open Networking Laboratory | ||
3 | +~ | ||
4 | +~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | +~ you may not use this file except in compliance with the License. | ||
6 | +~ You may obtain a copy of the License at | ||
7 | +~ | ||
8 | +~ http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | +~ | ||
10 | +~ Unless required by applicable law or agreed to in writing, software | ||
11 | +~ distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | +~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | +~ See the License for the specific language governing permissions and | ||
14 | +~ limitations under the License. | ||
15 | +--> | ||
16 | +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> | ||
17 | + | ||
18 | + <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0"> | ||
19 | + | ||
20 | + <command> | ||
21 | + <action class="org.onosproject.faultmanagement.alarms.cli.GetAllActiveAlarms"/> | ||
22 | + </command> | ||
23 | + <command> | ||
24 | + <action class="org.onosproject.faultmanagement.alarms.cli.GetAllAlarms"/> | ||
25 | + </command> | ||
26 | + <command> | ||
27 | + <action class="org.onosproject.faultmanagement.alarms.cli.GetAllAlarmsCounts"/> | ||
28 | + </command> | ||
29 | + <command> | ||
30 | + <action class="org.onosproject.faultmanagement.alarms.cli.GetDeviceAlarmsCounts"/> | ||
31 | + <completers> | ||
32 | + <ref component-id="deviceIdCompleter"/> | ||
33 | + </completers> | ||
34 | + </command> | ||
35 | + </command-bundle> | ||
36 | + | ||
37 | + | ||
38 | + <bean id="deviceIdCompleter" class="org.onosproject.cli.net.DeviceIdCompleter"/> | ||
39 | + | ||
40 | +</blueprint> |
apps/faultmanagement/fmcli/src/test/java/org/onosproject/faultmanagement/alarms/cli/README.txt
0 → 100644
1 | +# Need to write unit tests but do so after there are other CLI tests to use as a template. |
apps/faultmanagement/fmgui/pom.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<!-- | ||
3 | +~ Copyright 2015 Open Networking Laboratory | ||
4 | +~ | ||
5 | +~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | +~ you may not use this file except in compliance with the License. | ||
7 | +~ You may obtain a copy of the License at | ||
8 | +~ | ||
9 | +~ http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | +~ | ||
11 | +~ Unless required by applicable law or agreed to in writing, software | ||
12 | +~ distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | +~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | +~ See the License for the specific language governing permissions and | ||
15 | +~ limitations under the License. | ||
16 | +--> | ||
17 | + | ||
18 | +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
19 | + <modelVersion>4.0.0</modelVersion> | ||
20 | + | ||
21 | + | ||
22 | + <parent> | ||
23 | + <groupId>org.onosproject</groupId> | ||
24 | + <artifactId>onos-app-fm</artifactId> | ||
25 | + <version>1.4.0-SNAPSHOT</version> | ||
26 | + <relativePath>../pom.xml</relativePath> | ||
27 | + </parent> | ||
28 | + | ||
29 | + <artifactId>onos-app-fm-gui</artifactId> | ||
30 | + <packaging>bundle</packaging> | ||
31 | + | ||
32 | + <dependencies> | ||
33 | + <dependency> | ||
34 | + <groupId>org.apache.karaf.shell</groupId> | ||
35 | + <artifactId>org.apache.karaf.shell.console</artifactId> | ||
36 | + <scope>compile</scope> | ||
37 | + </dependency> | ||
38 | + | ||
39 | + <dependency> | ||
40 | + <groupId>org.onosproject</groupId> | ||
41 | + <artifactId>onlab-osgi</artifactId> | ||
42 | + </dependency> | ||
43 | + | ||
44 | + <dependency> | ||
45 | + <groupId>org.onosproject</groupId> | ||
46 | + <artifactId>onlab-junit</artifactId> | ||
47 | + <scope>test</scope> | ||
48 | + </dependency> | ||
49 | + | ||
50 | + | ||
51 | + <dependency> | ||
52 | + <groupId>org.apache.felix</groupId> | ||
53 | + <artifactId>org.apache.felix.scr.annotations</artifactId> | ||
54 | + <scope>provided</scope> | ||
55 | + </dependency> | ||
56 | + | ||
57 | + <dependency> | ||
58 | + <groupId>org.onosproject</groupId> | ||
59 | + <artifactId>onos-cli</artifactId> | ||
60 | + <version>${project.version}</version> | ||
61 | + <type>jar</type> | ||
62 | + </dependency> | ||
63 | + </dependencies> | ||
64 | + | ||
65 | +</project> |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.faultmanagement.alarms.gui; | ||
17 | + | ||
18 | +import java.util.Map; | ||
19 | +import java.util.Set; | ||
20 | +import org.onosproject.cli.AbstractShellCommand; | ||
21 | +import org.onosproject.incubator.net.faultmanagement.alarm.Alarm; | ||
22 | +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmId; | ||
23 | +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmService; | ||
24 | +import org.onosproject.net.DeviceId; | ||
25 | + | ||
26 | +/** | ||
27 | + * | ||
28 | + * Utility for invoking on alarm service. | ||
29 | + */ | ||
30 | +public final class AlarmServiceUtil { | ||
31 | + | ||
32 | + static Alarm lookupAlarm(AlarmId alarmId) { | ||
33 | + return alarmService().getAlarm(alarmId); | ||
34 | + } | ||
35 | + | ||
36 | + static Set<Alarm> lookUpAlarms() { | ||
37 | + return alarmService().getAlarms(); | ||
38 | + } | ||
39 | + | ||
40 | + static Set<Alarm> lookUpAlarms(DeviceId deviceId) { | ||
41 | + return alarmService().getAlarms(deviceId); | ||
42 | + } | ||
43 | + | ||
44 | + static Map<Alarm.SeverityLevel, Long> lookUpAlarmCounts(DeviceId deviceId) { | ||
45 | + return alarmService().getAlarmCounts(deviceId); | ||
46 | + } | ||
47 | + | ||
48 | + static Map<Alarm.SeverityLevel, Long> lookUpAlarmCounts() { | ||
49 | + return alarmService().getAlarmCounts(); | ||
50 | + } | ||
51 | + | ||
52 | + private static AlarmService alarmService() { | ||
53 | + return AbstractShellCommand.get(AlarmService.class); | ||
54 | + } | ||
55 | + | ||
56 | + private AlarmServiceUtil() { | ||
57 | + } | ||
58 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.faultmanagement.alarms.gui; | ||
17 | + | ||
18 | +import com.google.common.collect.ImmutableList; | ||
19 | +import org.apache.felix.scr.annotations.Activate; | ||
20 | +import org.apache.felix.scr.annotations.Component; | ||
21 | +import org.apache.felix.scr.annotations.Deactivate; | ||
22 | +import org.apache.felix.scr.annotations.Reference; | ||
23 | +import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
24 | +import org.onosproject.ui.UiExtension; | ||
25 | +import org.onosproject.ui.UiExtensionService; | ||
26 | +import org.onosproject.ui.UiMessageHandlerFactory; | ||
27 | +import org.onosproject.ui.UiView; | ||
28 | +import org.slf4j.Logger; | ||
29 | +import org.slf4j.LoggerFactory; | ||
30 | + | ||
31 | +import java.util.List; | ||
32 | + | ||
33 | +/** | ||
34 | + * Skeletal ONOS UI Table-View application component. | ||
35 | + */ | ||
36 | +@Component(immediate = true) | ||
37 | +public class AlarmTableComponent { | ||
38 | + | ||
39 | + private static final String VIEW_ID = "alarmTable"; | ||
40 | + private static final String VIEW_TEXT = "Alarms"; | ||
41 | + | ||
42 | + private final Logger log = LoggerFactory.getLogger(getClass()); | ||
43 | + | ||
44 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
45 | + protected UiExtensionService uiExtensionService; | ||
46 | + | ||
47 | + // List of application views | ||
48 | + private final List<UiView> uiViews = ImmutableList.of( | ||
49 | + new UiView(UiView.Category.OTHER, VIEW_ID, VIEW_TEXT) | ||
50 | + ); | ||
51 | + | ||
52 | + // Factory for UI message handlers | ||
53 | + private final UiMessageHandlerFactory messageHandlerFactory = | ||
54 | + () -> ImmutableList.of( | ||
55 | + new AlarmTableMessageHandler() | ||
56 | + ); | ||
57 | + | ||
58 | + // Application UI extension | ||
59 | + protected UiExtension extension = | ||
60 | + new UiExtension.Builder(getClass().getClassLoader(), uiViews) | ||
61 | + .resourcePath(VIEW_ID) | ||
62 | + .messageHandlerFactory(messageHandlerFactory) | ||
63 | + .build(); | ||
64 | + | ||
65 | + @Activate | ||
66 | + protected void activate() { | ||
67 | + uiExtensionService.register(extension); | ||
68 | + log.info("Started"); | ||
69 | + } | ||
70 | + | ||
71 | + @Deactivate | ||
72 | + protected void deactivate() { | ||
73 | + uiExtensionService.unregister(extension); | ||
74 | + log.info("Stopped"); | ||
75 | + } | ||
76 | + | ||
77 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.faultmanagement.alarms.gui; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
19 | +import com.google.common.base.Strings; | ||
20 | +import com.google.common.collect.ImmutableSet; | ||
21 | +import org.onosproject.ui.RequestHandler; | ||
22 | +import org.onosproject.ui.UiMessageHandler; | ||
23 | +import org.onosproject.ui.table.TableModel; | ||
24 | +import org.onosproject.ui.table.TableRequestHandler; | ||
25 | +import org.slf4j.Logger; | ||
26 | +import org.slf4j.LoggerFactory; | ||
27 | + | ||
28 | +import java.util.Collection; | ||
29 | +import java.util.Set; | ||
30 | +import org.joda.time.DateTime; | ||
31 | +import org.onosproject.incubator.net.faultmanagement.alarm.Alarm; | ||
32 | +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmId; | ||
33 | +import org.onosproject.net.DeviceId; | ||
34 | +import org.onosproject.ui.table.cell.TimeFormatter; | ||
35 | + | ||
36 | +/** | ||
37 | + * Skeletal ONOS UI Table-View message handler. | ||
38 | + */ | ||
39 | +public class AlarmTableMessageHandler extends UiMessageHandler { | ||
40 | + | ||
41 | + private static final String ALARM_TABLE_DATA_REQ = "alarmTableDataRequest"; | ||
42 | + private static final String ALARM_TABLE_DATA_RESP = "alarmTableDataResponse"; | ||
43 | + private static final String ALARM_TABLES = "alarmTables"; | ||
44 | + | ||
45 | + private static final String ALARM_TABLE_DETAIL_REQ = "alarmTableDetailsRequest"; | ||
46 | + private static final String ALARM_TABLE_DETAIL_RESP = "alarmTableDetailsResponse"; | ||
47 | + private static final String DETAILS = "details"; | ||
48 | + | ||
49 | + private static final String ID = "id"; | ||
50 | + private static final String DEVICE_ID_STR = "alarmDeviceId"; | ||
51 | + private static final String DESCRIPTION = "alarmDesc"; | ||
52 | + private static final String SOURCE = "alarmSource"; | ||
53 | + private static final String TIME_RAISED = "alarmTimeRaised"; | ||
54 | + private static final String TIME_UPDATED = "alarmTimeUpdated"; | ||
55 | + private static final String TIME_CLEARED = "alarmTimeCleared"; | ||
56 | + private static final String SEVERITY = "alarmSeverity"; | ||
57 | + private static final String RESULT = "result"; | ||
58 | + | ||
59 | + // TODO No need to show id column in ONOS-GUI | ||
60 | + | ||
61 | + // TODO Replace SEVERITY column by color-coding of row depending on severity ie. red=critical, green=cleared etc | ||
62 | + private static final String[] COLUMN_IDS = {ID, DEVICE_ID_STR, DESCRIPTION, SOURCE, TIME_RAISED, SEVERITY}; | ||
63 | + | ||
64 | + private final Logger log = LoggerFactory.getLogger(getClass()); | ||
65 | + | ||
66 | + @Override | ||
67 | + protected Collection<RequestHandler> createRequestHandlers() { | ||
68 | + return ImmutableSet.of( | ||
69 | + new AlarmTableDataRequestHandler(), | ||
70 | + new AlarmTableDetailRequestHandler() | ||
71 | + ); | ||
72 | + } | ||
73 | + | ||
74 | + // handler for alarm table requests | ||
75 | + private final class AlarmTableDataRequestHandler extends TableRequestHandler { | ||
76 | + | ||
77 | + private AlarmTableDataRequestHandler() { | ||
78 | + super(ALARM_TABLE_DATA_REQ, ALARM_TABLE_DATA_RESP, ALARM_TABLES); | ||
79 | + } | ||
80 | + | ||
81 | + @Override | ||
82 | + protected String defaultColumnId() { | ||
83 | + // if necessary, override defaultColumnId() -- if it isn't "id" | ||
84 | + return ID; | ||
85 | + } | ||
86 | + | ||
87 | + @Override | ||
88 | + protected String[] getColumnIds() { | ||
89 | + return COLUMN_IDS; | ||
90 | + } | ||
91 | + | ||
92 | + @Override | ||
93 | + protected TableModel createTableModel() { | ||
94 | + // if required, override createTableModel() to set column formatters / comparators | ||
95 | + TableModel tm = super.createTableModel(); | ||
96 | + tm.setFormatter(TIME_RAISED, new TimeFormatter()); | ||
97 | + return tm; | ||
98 | + } | ||
99 | + | ||
100 | + @Override | ||
101 | + protected void populateTable(TableModel tm, ObjectNode payload) { | ||
102 | + log.debug(" populateTable tm={} payload ={}", tm, payload); | ||
103 | + String devId = string(payload, "devId"); | ||
104 | + | ||
105 | + Set<Alarm> alarms = Strings.isNullOrEmpty(devId) ? | ||
106 | + AlarmServiceUtil.lookUpAlarms() : | ||
107 | + AlarmServiceUtil.lookUpAlarms(DeviceId.deviceId(devId)); | ||
108 | + | ||
109 | + alarms.stream().forEach((alarm) -> { | ||
110 | + populateRow(tm.addRow(), alarm); | ||
111 | + }); | ||
112 | + | ||
113 | + } | ||
114 | + | ||
115 | + private void populateRow(TableModel.Row row, Alarm alarm) { | ||
116 | + log.debug("populate table Row row={} item ={}", row, alarm); | ||
117 | + | ||
118 | + row.cell(ID, alarm.id().fingerprint()) | ||
119 | + .cell(DEVICE_ID_STR, alarm.deviceId()) | ||
120 | + .cell(DESCRIPTION, alarm.description()) | ||
121 | + .cell(SOURCE, alarm.source()) | ||
122 | + .cell(TIME_RAISED, new DateTime(alarm.timeRaised())) | ||
123 | + .cell(SEVERITY, alarm.severity()); | ||
124 | + } | ||
125 | + } | ||
126 | + | ||
127 | + // handler for alarm details requests | ||
128 | + private final class AlarmTableDetailRequestHandler extends RequestHandler { | ||
129 | + | ||
130 | + private AlarmTableDetailRequestHandler() { | ||
131 | + super(ALARM_TABLE_DETAIL_REQ); | ||
132 | + } | ||
133 | + | ||
134 | + @Override | ||
135 | + public void process(long sid, ObjectNode payload) { | ||
136 | + log.debug("sid={}, payload ={}", sid, payload); | ||
137 | + | ||
138 | + String id = string(payload, ID, "(none)"); | ||
139 | + Alarm alarm = AlarmServiceUtil.lookupAlarm(AlarmId.alarmId(Long.parseLong(id))); | ||
140 | + ObjectNode rootNode = objectNode(); | ||
141 | + ObjectNode data = objectNode(); | ||
142 | + rootNode.set(DETAILS, data); | ||
143 | + | ||
144 | + if (alarm == null) { | ||
145 | + rootNode.put(RESULT, "Item with id '" + id + "' not found"); | ||
146 | + log.warn("attempted to get item detail for id '{}'", id); | ||
147 | + | ||
148 | + } else { | ||
149 | + rootNode.put(RESULT, "Found item with id '" + id + "'"); | ||
150 | + | ||
151 | + data.put(ID, alarm.id().fingerprint()); | ||
152 | + data.put(DESCRIPTION, alarm.description()); | ||
153 | + data.put(DEVICE_ID_STR, alarm.deviceId().toString()); | ||
154 | + data.put(SOURCE, alarm.source().toString()); | ||
155 | + long timeRaised = alarm.timeRaised(); | ||
156 | + data.put(TIME_RAISED, | ||
157 | + formatTime(timeRaised) | ||
158 | + ); | ||
159 | + data.put(TIME_UPDATED, formatTime(alarm.timeUpdated())); | ||
160 | + data.put(TIME_CLEARED, formatTime(alarm.timeCleared())); | ||
161 | + data.put(SEVERITY, alarm.severity().toString()); | ||
162 | + } | ||
163 | + log.debug("send ={}", rootNode); | ||
164 | + | ||
165 | + sendMessage(ALARM_TABLE_DETAIL_RESP, 0, rootNode); | ||
166 | + } | ||
167 | + } | ||
168 | + | ||
169 | + private static String formatTime(Long msSinceStartOfEpoch) { | ||
170 | + if (msSinceStartOfEpoch == null) { | ||
171 | + return "-"; | ||
172 | + } | ||
173 | + return new TimeFormatter().format(new DateTime(msSinceStartOfEpoch)); | ||
174 | + } | ||
175 | + | ||
176 | + | ||
177 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.faultmanagement.alarms.gui; | ||
17 | + | ||
18 | +import com.google.common.collect.ImmutableList; | ||
19 | +import org.apache.felix.scr.annotations.Activate; | ||
20 | +import org.apache.felix.scr.annotations.Component; | ||
21 | +import org.apache.felix.scr.annotations.Deactivate; | ||
22 | +import org.apache.felix.scr.annotations.Reference; | ||
23 | +import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
24 | +import org.onosproject.ui.UiExtension; | ||
25 | +import org.onosproject.ui.UiExtensionService; | ||
26 | +import org.onosproject.ui.UiMessageHandlerFactory; | ||
27 | +import org.onosproject.ui.UiTopoOverlayFactory; | ||
28 | +import org.onosproject.ui.UiView; | ||
29 | +import org.onosproject.ui.UiViewHidden; | ||
30 | +import org.slf4j.Logger; | ||
31 | +import org.slf4j.LoggerFactory; | ||
32 | + | ||
33 | +import java.util.List; | ||
34 | + | ||
35 | +/** | ||
36 | + * Skeletal ONOS UI Topology-Overlay application component. | ||
37 | + */ | ||
38 | +@Component(immediate = true) | ||
39 | +public class AlarmTopovComponent { | ||
40 | + | ||
41 | + private static final ClassLoader CL = AlarmTopovComponent.class.getClassLoader(); | ||
42 | + private static final String VIEW_ID = "alarmTopov"; | ||
43 | + | ||
44 | + private final Logger log = LoggerFactory.getLogger(getClass()); | ||
45 | + | ||
46 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
47 | + protected UiExtensionService uiExtensionService; | ||
48 | + | ||
49 | + // List of application views | ||
50 | + private final List<UiView> uiViews = ImmutableList.of( | ||
51 | + new UiViewHidden(VIEW_ID) | ||
52 | + ); | ||
53 | + | ||
54 | + // Factory for UI message handlers | ||
55 | + private final UiMessageHandlerFactory messageHandlerFactory = | ||
56 | + () -> ImmutableList.of( | ||
57 | + new AlarmTopovMessageHandler() | ||
58 | + ); | ||
59 | + | ||
60 | + // Factory for UI topology overlays | ||
61 | + private final UiTopoOverlayFactory topoOverlayFactory = | ||
62 | + () -> ImmutableList.of( | ||
63 | + new AlarmTopovOverlay() | ||
64 | + ); | ||
65 | + | ||
66 | + // Application UI extension | ||
67 | + protected UiExtension extension = | ||
68 | + new UiExtension.Builder(CL, uiViews) | ||
69 | + .resourcePath(VIEW_ID) | ||
70 | + .messageHandlerFactory(messageHandlerFactory) | ||
71 | + .topoOverlayFactory(topoOverlayFactory) | ||
72 | + .build(); | ||
73 | + | ||
74 | + @Activate | ||
75 | + protected void activate() { | ||
76 | + uiExtensionService.register(extension); | ||
77 | + log.info("Started"); | ||
78 | + } | ||
79 | + | ||
80 | + @Deactivate | ||
81 | + protected void deactivate() { | ||
82 | + uiExtensionService.unregister(extension); | ||
83 | + log.info("Stopped"); | ||
84 | + } | ||
85 | + | ||
86 | +} |
1 | +/* | ||
2 | + * Copyright 2014,2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.faultmanagement.alarms.gui; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
19 | +import com.google.common.base.Strings; | ||
20 | +import com.google.common.collect.ImmutableSet; | ||
21 | +import org.onlab.osgi.ServiceDirectory; | ||
22 | +import org.onosproject.net.Device; | ||
23 | +import org.onosproject.net.DeviceId; | ||
24 | +import org.onosproject.net.Element; | ||
25 | +import org.onosproject.net.HostId; | ||
26 | +import org.onosproject.net.device.DeviceService; | ||
27 | +import org.onosproject.net.host.HostService; | ||
28 | +import org.onosproject.ui.RequestHandler; | ||
29 | +import org.onosproject.ui.UiConnection; | ||
30 | +import org.onosproject.ui.UiMessageHandler; | ||
31 | +import org.onosproject.ui.topo.DeviceHighlight; | ||
32 | +import org.onosproject.ui.topo.Highlights; | ||
33 | +import org.onosproject.ui.topo.NodeBadge; | ||
34 | +import org.onosproject.ui.topo.NodeBadge.Status; | ||
35 | +import org.onosproject.ui.topo.TopoJson; | ||
36 | +import org.slf4j.Logger; | ||
37 | +import org.slf4j.LoggerFactory; | ||
38 | + | ||
39 | +import java.util.Collection; | ||
40 | +import java.util.Set; | ||
41 | +import org.onosproject.incubator.net.faultmanagement.alarm.Alarm; | ||
42 | +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmService; | ||
43 | + | ||
44 | +/** | ||
45 | + * Skeletal ONOS UI Topology-Overlay message handler. | ||
46 | + */ | ||
47 | +public class AlarmTopovMessageHandler extends UiMessageHandler { | ||
48 | + | ||
49 | + private static final String ALARM_TOPOV_DISPLAY_START = "alarmTopovDisplayStart"; | ||
50 | + private static final String ALARM_TOPOV_DISPLAY_UPDATE = "alarmTopovDisplayUpdate"; | ||
51 | + private static final String ALARM_TOPOV_DISPLAY_STOP = "alarmTopovDisplayStop"; | ||
52 | + | ||
53 | + private static final String ID = "id"; | ||
54 | + private static final String MODE = "mode"; | ||
55 | + | ||
56 | + private enum Mode { | ||
57 | + | ||
58 | + IDLE, MOUSE | ||
59 | + } | ||
60 | + | ||
61 | + private final Logger log = LoggerFactory.getLogger(getClass()); | ||
62 | + | ||
63 | + private DeviceService deviceService; | ||
64 | + private HostService hostService; | ||
65 | + private AlarmService alarmService; | ||
66 | + | ||
67 | + private Mode currentMode = Mode.IDLE; | ||
68 | + private Element elementOfNote; | ||
69 | + | ||
70 | + // ===============-=-=-=-=-=-======================-=-=-=-=-=-=-================================ | ||
71 | + @Override | ||
72 | + public void init(UiConnection connection, ServiceDirectory directory) { | ||
73 | + super.init(connection, directory); | ||
74 | + deviceService = directory.get(DeviceService.class); | ||
75 | + hostService = directory.get(HostService.class); | ||
76 | + alarmService = directory.get(AlarmService.class); | ||
77 | + } | ||
78 | + | ||
79 | + @Override | ||
80 | + protected Collection<RequestHandler> createRequestHandlers() { | ||
81 | + return ImmutableSet.of( | ||
82 | + new DisplayStartHandler(), | ||
83 | + new DisplayUpdateHandler(), | ||
84 | + new DisplayStopHandler() | ||
85 | + ); | ||
86 | + } | ||
87 | + | ||
88 | + // === ------------------------- | ||
89 | + // === Handler classes | ||
90 | + private final class DisplayStartHandler extends RequestHandler { | ||
91 | + | ||
92 | + public DisplayStartHandler() { | ||
93 | + super(ALARM_TOPOV_DISPLAY_START); | ||
94 | + } | ||
95 | + | ||
96 | + @Override | ||
97 | + public void process(long sid, ObjectNode payload) { | ||
98 | + String mode = string(payload, MODE); | ||
99 | + | ||
100 | + log.debug("Start Display: mode [{}]", mode); | ||
101 | + clearState(); | ||
102 | + clearForMode(); | ||
103 | + | ||
104 | + switch (mode) { | ||
105 | + case "mouse": | ||
106 | + currentMode = Mode.MOUSE; | ||
107 | + | ||
108 | + sendMouseData(); | ||
109 | + break; | ||
110 | + | ||
111 | + default: | ||
112 | + currentMode = Mode.IDLE; | ||
113 | + | ||
114 | + break; | ||
115 | + } | ||
116 | + } | ||
117 | + } | ||
118 | + | ||
119 | + private final class DisplayUpdateHandler extends RequestHandler { | ||
120 | + | ||
121 | + public DisplayUpdateHandler() { | ||
122 | + super(ALARM_TOPOV_DISPLAY_UPDATE); | ||
123 | + } | ||
124 | + | ||
125 | + @Override | ||
126 | + public void process(long sid, ObjectNode payload) { | ||
127 | + String id = string(payload, ID); | ||
128 | + log.debug("Update Display: id [{}]", id); | ||
129 | + if (!Strings.isNullOrEmpty(id)) { | ||
130 | + updateForMode(id); | ||
131 | + } else { | ||
132 | + clearForMode(); | ||
133 | + } | ||
134 | + } | ||
135 | + } | ||
136 | + | ||
137 | + private final class DisplayStopHandler extends RequestHandler { | ||
138 | + | ||
139 | + public DisplayStopHandler() { | ||
140 | + super(ALARM_TOPOV_DISPLAY_STOP); | ||
141 | + } | ||
142 | + | ||
143 | + @Override | ||
144 | + public void process(long sid, ObjectNode payload) { | ||
145 | + log.debug("Stop Display"); | ||
146 | + clearState(); | ||
147 | + clearForMode(); | ||
148 | + } | ||
149 | + } | ||
150 | + | ||
151 | + // === ------------ | ||
152 | + private void clearState() { | ||
153 | + currentMode = Mode.IDLE; | ||
154 | + elementOfNote = null; | ||
155 | + } | ||
156 | + | ||
157 | + private void updateForMode(String id) { | ||
158 | + log.debug("host service: {}", hostService); | ||
159 | + log.debug("device service: {}", deviceService); | ||
160 | + | ||
161 | + try { | ||
162 | + HostId hid = HostId.hostId(id); | ||
163 | + log.debug("host id {}", hid); | ||
164 | + elementOfNote = hostService.getHost(hid); | ||
165 | + log.debug("host element {}", elementOfNote); | ||
166 | + | ||
167 | + } catch (RuntimeException e) { | ||
168 | + try { | ||
169 | + DeviceId did = DeviceId.deviceId(id); | ||
170 | + log.debug("device id {}", did); | ||
171 | + elementOfNote = deviceService.getDevice(did); | ||
172 | + log.debug("device element {}", elementOfNote); | ||
173 | + | ||
174 | + } catch (RuntimeException e2) { | ||
175 | + log.debug("Unable to process ID [{}]", id); | ||
176 | + elementOfNote = null; | ||
177 | + } | ||
178 | + } | ||
179 | + | ||
180 | + switch (currentMode) { | ||
181 | + case MOUSE: | ||
182 | + sendMouseData(); | ||
183 | + break; | ||
184 | + | ||
185 | + default: | ||
186 | + break; | ||
187 | + } | ||
188 | + | ||
189 | + } | ||
190 | + | ||
191 | + private void clearForMode() { | ||
192 | + sendHighlights(new Highlights()); | ||
193 | + } | ||
194 | + | ||
195 | + private void sendHighlights(Highlights highlights) { | ||
196 | + sendMessage(TopoJson.highlightsMessage(highlights)); | ||
197 | + } | ||
198 | + | ||
199 | + private void sendMouseData() { | ||
200 | + if (elementOfNote != null && elementOfNote instanceof Device) { | ||
201 | + DeviceId devId = (DeviceId) elementOfNote.id(); | ||
202 | + Set<Alarm> alarmsOnDevice = alarmService.getAlarms(devId); | ||
203 | + Highlights highlights = new Highlights(); | ||
204 | + | ||
205 | + addDeviceBadge(highlights, devId, alarmsOnDevice.size()); | ||
206 | + sendHighlights(highlights); | ||
207 | + } | ||
208 | + // Note: could also process Host, if available | ||
209 | + } | ||
210 | + | ||
211 | + private void addDeviceBadge(Highlights h, DeviceId devId, int n) { | ||
212 | + DeviceHighlight dh = new DeviceHighlight(devId.toString()); | ||
213 | + dh.setBadge(createBadge(n)); | ||
214 | + h.add(dh); | ||
215 | + } | ||
216 | + | ||
217 | + private NodeBadge createBadge(int n) { | ||
218 | + Status status = n > 0 ? Status.ERROR : Status.INFO; | ||
219 | + String noun = n > 0 ? "(Alarmed)" : "(Normal)"; | ||
220 | + String msg = "Alarms: " + n + " " + noun; | ||
221 | + return NodeBadge.number(status, n, msg); | ||
222 | + } | ||
223 | + | ||
224 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.faultmanagement.alarms.gui; | ||
17 | + | ||
18 | +import java.util.Map; | ||
19 | +import org.onosproject.incubator.net.faultmanagement.alarm.Alarm; | ||
20 | +import org.onosproject.net.DeviceId; | ||
21 | +import org.onosproject.ui.UiTopoOverlay; | ||
22 | +import org.onosproject.ui.topo.ButtonId; | ||
23 | +import org.onosproject.ui.topo.PropertyPanel; | ||
24 | +import org.onosproject.ui.topo.TopoConstants.CoreButtons; | ||
25 | +import static org.onosproject.ui.topo.TopoConstants.Properties.*; | ||
26 | + | ||
27 | +/** | ||
28 | + * Our topology overlay. | ||
29 | + */ | ||
30 | +public class AlarmTopovOverlay extends UiTopoOverlay { | ||
31 | + | ||
32 | + // NOTE: this must match the ID defined in alarmTopov.js | ||
33 | + private static final String OVERLAY_ID = "alarmsTopo-overlay"; | ||
34 | + | ||
35 | + private static final ButtonId ALARM1_BUTTON = new ButtonId("alarm1button"); | ||
36 | + private static final ButtonId ALARM2_BUTTON = new ButtonId("alarm2button"); | ||
37 | + | ||
38 | + public AlarmTopovOverlay() { | ||
39 | + super(OVERLAY_ID); | ||
40 | + } | ||
41 | + | ||
42 | + @Override | ||
43 | + public void modifySummary(PropertyPanel pp) { | ||
44 | + pp.title("Alarms Overview"); | ||
45 | + // We could just remove some properties here but lets keep it uncluttered, unless | ||
46 | + // there is feedback other properties are essential. | ||
47 | + pp.removeAllProps(); | ||
48 | + Map<Alarm.SeverityLevel, Long> countsForAll = AlarmServiceUtil.lookUpAlarmCounts(); | ||
49 | + addAlarmCountsProperties(pp, countsForAll); | ||
50 | + | ||
51 | + } | ||
52 | + | ||
53 | + @Override | ||
54 | + public void modifyDeviceDetails(PropertyPanel pp, DeviceId deviceId) { | ||
55 | + pp.title("Alarm Details"); | ||
56 | + pp.removeProps(LATITUDE, LONGITUDE, PORTS, FLOWS, TUNNELS, SERIAL_NUMBER, PROTOCOL); | ||
57 | + | ||
58 | + Map<Alarm.SeverityLevel, Long> countsForDevice = AlarmServiceUtil.lookUpAlarmCounts(deviceId); | ||
59 | + addAlarmCountsProperties(pp, countsForDevice); | ||
60 | + | ||
61 | + pp.addButton(ALARM1_BUTTON) | ||
62 | + .addButton(ALARM2_BUTTON); | ||
63 | + | ||
64 | + pp.removeButtons(CoreButtons.SHOW_PORT_VIEW) | ||
65 | + .removeButtons(CoreButtons.SHOW_GROUP_VIEW); | ||
66 | + } | ||
67 | + | ||
68 | + private void addAlarmCountsProperties(PropertyPanel pp, Map<Alarm.SeverityLevel, Long> countsForDevice) { | ||
69 | + | ||
70 | + // TODO we could show these as color-coded squares with a count inside, to save space on the screen. | ||
71 | + | ||
72 | + long cr = countsForDevice.getOrDefault(Alarm.SeverityLevel.CRITICAL, 0L); | ||
73 | + long ma = countsForDevice.getOrDefault(Alarm.SeverityLevel.MAJOR, 0L); | ||
74 | + long mi = countsForDevice.getOrDefault(Alarm.SeverityLevel.MINOR, 0L); | ||
75 | + long wa = countsForDevice.getOrDefault(Alarm.SeverityLevel.WARNING, 0L); | ||
76 | + long in = countsForDevice.getOrDefault(Alarm.SeverityLevel.INDETERMINATE, 0L); | ||
77 | + long cl = countsForDevice.getOrDefault(Alarm.SeverityLevel.CLEARED, 0L); | ||
78 | + | ||
79 | + // Unfortunately the PropertyPanel does not righ justify numbers even when using longs, | ||
80 | + // but that not in scope of fault management work | ||
81 | + pp.addProp("Critical", cr); | ||
82 | + pp.addProp("Major", ma); | ||
83 | + pp.addProp("Minor", mi); | ||
84 | + pp.addProp("Warning", wa); | ||
85 | + pp.addProp("Indeter.", in); | ||
86 | + pp.addProp("Cleared", cl); | ||
87 | + pp.addSeparator(); | ||
88 | + pp.addProp("Total", cr + ma + mi + wa + in + cl); | ||
89 | + | ||
90 | + } | ||
91 | + | ||
92 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +/** | ||
18 | + * Fault Management GUI implementation. | ||
19 | + */ | ||
20 | +package org.onosproject.faultmanagement.alarms.gui; |
1 | +<link rel="stylesheet" href="app/view/alarmTable/alarmTable.css"> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +<script src="app/view/alarmTable/alarmTable.js"></script> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +<link rel="stylesheet" href="app/view/alarmTopov/alarmTopov.css"> |
1 | +/* css for alarm table view */ | ||
2 | + | ||
3 | +#ov-alarm-table h2 { | ||
4 | + display: inline-block; | ||
5 | +} | ||
6 | + | ||
7 | +/* Panel Styling */ | ||
8 | +#ov-alarm-table-item-details-panel.floatpanel { | ||
9 | + position: absolute; | ||
10 | + top: 115px; | ||
11 | +} | ||
12 | + | ||
13 | +.light #ov-alarm-table-item-details-panel.floatpanel { | ||
14 | + background-color: rgb(229, 234, 237); | ||
15 | +} | ||
16 | +.dark #ov-alarm-table-item-details-panel.floatpanel { | ||
17 | + background-color: #3A4042; | ||
18 | +} | ||
19 | + | ||
20 | +#ov-alarm-table-item-details-panel h3 { | ||
21 | + margin: 0; | ||
22 | + font-size: large; | ||
23 | +} | ||
24 | + | ||
25 | +#ov-alarm-table-item-details-panel h4 { | ||
26 | + margin: 0; | ||
27 | +} | ||
28 | + | ||
29 | +#ov-alarm-table-item-details-panel td { | ||
30 | + padding: 5px; | ||
31 | +} | ||
32 | +#ov-alarm-table-item-details-panel td.label { | ||
33 | + font-style: italic; | ||
34 | + opacity: 0.8; | ||
35 | +} |
1 | +<!-- partial HTML --> | ||
2 | +<div id="ov-alarm-table"> | ||
3 | + <div class="tabular-header"> | ||
4 | + <h2>Alarms for {{devId || "all devices."}} ({{tableData.length}} total)</h2> | ||
5 | + <div class="ctrl-btns"> | ||
6 | + <div class="refresh" ng-class="{active: autoRefresh}" | ||
7 | + icon icon-id="refresh" icon-size="36" | ||
8 | + tooltip tt-msg="autoRefreshTip" | ||
9 | + ng-click="toggleRefresh()"></div> | ||
10 | + </div> | ||
11 | + </div> | ||
12 | + | ||
13 | + <div class="summary-list" onos-table-resize> | ||
14 | + | ||
15 | + <div class="table-header" onos-sortable-header> | ||
16 | + <table> | ||
17 | + <tr> | ||
18 | + | ||
19 | + <td colId="id" sortable>Id </td> | ||
20 | + <td colId="alarmDeviceId" sortable>Device </td> | ||
21 | + <td colId="alarmDesc" sortable>Description </td> | ||
22 | + <td colId="alarmSource" sortable>Source </td> | ||
23 | + <td colId="alarmTimeRaised" sortable>Time Raised </td> | ||
24 | + <td colId="alarmSeverity" sortable>Severity </td> | ||
25 | + | ||
26 | + </tr> | ||
27 | + </table> | ||
28 | + </div> | ||
29 | + | ||
30 | + <div class="table-body"> | ||
31 | + <table> | ||
32 | + <tr ng-if="!tableData.length" class="no-data"> | ||
33 | + <td colspan="3"> | ||
34 | + No Alarms found | ||
35 | + </td> | ||
36 | + </tr> | ||
37 | + | ||
38 | + <tr ng-repeat="item in tableData track by $index" | ||
39 | + ng-click="selectCallback($event, item)" | ||
40 | + ng-class="{selected: item.id === selId}"> | ||
41 | + <td>{{item.id}}</td> | ||
42 | + <td>{{item.alarmDeviceId}}</td> | ||
43 | + <td>{{item.alarmDesc}}</td> | ||
44 | + <td>{{item.alarmSource}}</td> | ||
45 | + <td>{{item.alarmTimeRaised}}</td> | ||
46 | + <td>{{item.alarmSeverity}}</td> | ||
47 | + </tr> | ||
48 | + </table> | ||
49 | + </div> | ||
50 | + | ||
51 | + </div> | ||
52 | + | ||
53 | + <ov-alarm-table-item-details-panel></ov-alarm-table-item-details-panel> | ||
54 | +</div> |
1 | +// js for alarm app table view | ||
2 | +(function () { | ||
3 | + 'use strict'; | ||
4 | + | ||
5 | + // injected refs | ||
6 | + var $log, $scope, $loc, devId, fs, wss; | ||
7 | + | ||
8 | + // constants | ||
9 | + var detailsReq = 'alarmTableDetailsRequest', | ||
10 | + detailsResp = 'alarmTableDetailsResponse', | ||
11 | + pName = 'ov-alarm-table-item-details-panel', | ||
12 | + propOrder = ['id', 'alarmDeviceId', 'alarmDesc', 'alarmSource', 'alarmTimeRaised', 'alarmTimeUpdated', 'alarmTimeCleared', 'alarmSeverity'], | ||
13 | + friendlyProps = ['Alarm Id', 'Device Id', 'Description', 'Source', 'Time Raised', 'Time Updated', 'Time Cleared', 'Severity']; | ||
14 | + | ||
15 | + | ||
16 | + function addProp(tbody, index, value) { | ||
17 | + var tr = tbody.append('tr'); | ||
18 | + | ||
19 | + function addCell(cls, txt) { | ||
20 | + tr.append('td').attr('class', cls).html(txt); | ||
21 | + } | ||
22 | + addCell('label', friendlyProps[index] + ' :'); | ||
23 | + addCell('value', value); | ||
24 | + } | ||
25 | + | ||
26 | + function populatePanel(panel) { | ||
27 | + var title = panel.append('h3'), | ||
28 | + tbody = panel.append('table').append('tbody'); | ||
29 | + | ||
30 | + title.text('Alarm Details'); | ||
31 | + | ||
32 | + propOrder.forEach(function (prop, i) { | ||
33 | + addProp(tbody, i, $scope.panelDetails[prop]); | ||
34 | + }); | ||
35 | + | ||
36 | + panel.append('hr'); | ||
37 | + panel.append('h4').text('Comments'); | ||
38 | + panel.append('p').text($scope.panelDetails.comment); | ||
39 | + } | ||
40 | + | ||
41 | + function respDetailsCb(data) { | ||
42 | + $scope.panelDetails = data.details; | ||
43 | + $scope.$apply(); | ||
44 | + } | ||
45 | + | ||
46 | + angular.module('ovAlarmTable', []) | ||
47 | + .controller('OvAlarmTableCtrl', | ||
48 | + ['$log', '$scope', '$location', 'TableBuilderService', | ||
49 | + 'FnService', 'WebSocketService', | ||
50 | + function (_$log_, _$scope_, _$location_, tbs, _fs_, _wss_) { | ||
51 | + var params; | ||
52 | + | ||
53 | + $log = _$log_; | ||
54 | + $scope = _$scope_; | ||
55 | + $loc = _$location_; | ||
56 | + | ||
57 | + fs = _fs_; | ||
58 | + wss = _wss_; | ||
59 | + | ||
60 | + | ||
61 | + params = $loc.search(); | ||
62 | + if (params.hasOwnProperty('devId')) { | ||
63 | + $scope.devId = params['devId']; | ||
64 | + } | ||
65 | + | ||
66 | + var handlers = {}; | ||
67 | + $scope.panelDetails = {}; | ||
68 | + | ||
69 | + // details response handler | ||
70 | + handlers[detailsResp] = respDetailsCb; | ||
71 | + wss.bindHandlers(handlers); | ||
72 | + | ||
73 | + // custom selection callback | ||
74 | + function selCb($event, row) { | ||
75 | + $log.debug("selCb row=" + JSON.stringify(row, null, 4) + | ||
76 | + ", $event=" + JSON.stringify($event, null, 4)); | ||
77 | + $log.debug('$scope.selId=', $scope.selId); | ||
78 | + if ($scope.selId) { | ||
79 | + $log.debug('send'); | ||
80 | + wss.sendEvent(detailsReq, {id: row.id}); | ||
81 | + } else { | ||
82 | + $log.debug('hidePanel'); | ||
83 | + $scope.hidePanel(); | ||
84 | + } | ||
85 | + $log.debug('Got a click on:', row); | ||
86 | + } | ||
87 | + | ||
88 | + // TableBuilderService creating a table for us | ||
89 | + tbs.buildTable({ | ||
90 | + scope: $scope, | ||
91 | + tag: 'alarmTable', | ||
92 | + selCb: selCb, | ||
93 | + query: params | ||
94 | + }); | ||
95 | + | ||
96 | + // cleanup | ||
97 | + $scope.$on('$destroy', function () { | ||
98 | + wss.unbindHandlers(handlers); | ||
99 | + $log.log('OvAlarmTableCtrl has been destroyed'); | ||
100 | + }); | ||
101 | + | ||
102 | + $log.log('OvAlarmTableCtrl has been created'); | ||
103 | + }]) | ||
104 | + | ||
105 | + .directive('ovAlarmTableItemDetailsPanel', ['PanelService', 'KeyService', | ||
106 | + function (ps, ks) { | ||
107 | + return { | ||
108 | + restrict: 'E', | ||
109 | + link: function (scope, element, attrs) { | ||
110 | + // insert details panel with PanelService | ||
111 | + // create the panel | ||
112 | + var panel = ps.createPanel(pName, { | ||
113 | + width: 400, | ||
114 | + margin: 20, | ||
115 | + hideMargin: 0 | ||
116 | + }); | ||
117 | + panel.hide(); | ||
118 | + scope.hidePanel = function () { | ||
119 | + panel.hide(); | ||
120 | + }; | ||
121 | + | ||
122 | + function closePanel() { | ||
123 | + if (panel.isVisible()) { | ||
124 | + $scope.selId = null; | ||
125 | + panel.hide(); | ||
126 | + return true; | ||
127 | + } | ||
128 | + return false; | ||
129 | + } | ||
130 | + | ||
131 | + // create key bindings to handle panel | ||
132 | + ks.keyBindings({ | ||
133 | + esc: [closePanel, 'Close the details panel'], | ||
134 | + _helpFormat: ['esc'] | ||
135 | + }); | ||
136 | + ks.gestureNotes([ | ||
137 | + ['click', 'Select a row to show item details'] | ||
138 | + ]); | ||
139 | + | ||
140 | + // update the panel's contents when the data is changed | ||
141 | + scope.$watch('panelDetails', function () { | ||
142 | + if (!fs.isEmptyObject(scope.panelDetails)) { | ||
143 | + panel.empty(); | ||
144 | + populatePanel(panel); | ||
145 | + panel.show(); | ||
146 | + } | ||
147 | + }); | ||
148 | + | ||
149 | + // cleanup on destroyed scope | ||
150 | + scope.$on('$destroy', function () { | ||
151 | + ks.unbindKeys(); | ||
152 | + ps.destroyPanel(pName); | ||
153 | + }); | ||
154 | + } | ||
155 | + }; | ||
156 | + }]); | ||
157 | +}()); |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +/* | ||
18 | + Alarm Demo module. This contains the "business logic" for the topology | ||
19 | + overlay that we are implementing. | ||
20 | + */ | ||
21 | + | ||
22 | +(function () { | ||
23 | + 'use strict'; | ||
24 | + | ||
25 | + // injected refs | ||
26 | + var $log, fs, flash, wss; | ||
27 | + | ||
28 | + // constants | ||
29 | + var displayStart = 'alarmTopovDisplayStart', | ||
30 | + displayUpdate = 'alarmTopovDisplayUpdate', | ||
31 | + displayStop = 'alarmTopovDisplayStop'; | ||
32 | + | ||
33 | + // internal state | ||
34 | + var currentMode = null; | ||
35 | + | ||
36 | + | ||
37 | + // === --------------------------- | ||
38 | + // === Helper functions | ||
39 | + | ||
40 | + function sendDisplayStart(mode) { | ||
41 | + wss.sendEvent(displayStart, { | ||
42 | + mode: mode | ||
43 | + }); | ||
44 | + } | ||
45 | + | ||
46 | + function sendDisplayUpdate(what) { | ||
47 | + wss.sendEvent(displayUpdate, { | ||
48 | + id: what ? what.id : '' | ||
49 | + }); | ||
50 | + } | ||
51 | + | ||
52 | + function sendDisplayStop() { | ||
53 | + wss.sendEvent(displayStop); | ||
54 | + } | ||
55 | + | ||
56 | + // === --------------------------- | ||
57 | + // === Main API functions | ||
58 | + | ||
59 | + function startDisplay(mode) { | ||
60 | + if (currentMode === mode) { | ||
61 | + $log.debug('(in mode', mode, 'already)'); | ||
62 | + } else { | ||
63 | + currentMode = mode; | ||
64 | + sendDisplayStart(mode); | ||
65 | + flash.flash('Starting display mode: ' + mode); | ||
66 | + } | ||
67 | + } | ||
68 | + | ||
69 | + function updateDisplay(m) { | ||
70 | + if (currentMode) { | ||
71 | + sendDisplayUpdate(m); | ||
72 | + } | ||
73 | + } | ||
74 | + | ||
75 | + function stopDisplay() { | ||
76 | + if (currentMode) { | ||
77 | + currentMode = null; | ||
78 | + sendDisplayStop(); | ||
79 | + flash.flash('Canceling display mode'); | ||
80 | + return true; | ||
81 | + } | ||
82 | + return false; | ||
83 | + } | ||
84 | + | ||
85 | + // === --------------------------- | ||
86 | + // === Module Factory Definition | ||
87 | + | ||
88 | + angular.module('ovAlarmTopov', []) | ||
89 | + .factory('AlarmTopovDemoService', | ||
90 | + ['$log', 'FnService', 'FlashService', 'WebSocketService', | ||
91 | + | ||
92 | + function (_$log_, _fs_, _flash_, _wss_) { | ||
93 | + $log = _$log_; | ||
94 | + fs = _fs_; | ||
95 | + flash = _flash_; | ||
96 | + wss = _wss_; | ||
97 | + | ||
98 | + return { | ||
99 | + startDisplay: startDisplay, | ||
100 | + updateDisplay: updateDisplay, | ||
101 | + stopDisplay: stopDisplay | ||
102 | + }; | ||
103 | + }]); | ||
104 | +}()); |
1 | +// alarm topology overlay - client side | ||
2 | +// | ||
3 | +// This is the glue that binds our business logic (in alarmTopovDemo.js) | ||
4 | +// to the overlay framework. | ||
5 | + | ||
6 | +(function () { | ||
7 | + 'use strict'; | ||
8 | + | ||
9 | + // injected refs | ||
10 | + var $log, tov, stds, ns; | ||
11 | + | ||
12 | + // internal state should be kept in the service module (not here) | ||
13 | + | ||
14 | + // our overlay definition | ||
15 | + var overlay = { | ||
16 | + // NOTE: this must match the ID defined in AppUiTopovOverlay | ||
17 | + overlayId: 'alarmsTopo-overlay', | ||
18 | + glyphId: '*star4', | ||
19 | + tooltip: 'Alarms Overlay', | ||
20 | + // These glyphs get installed using the overlayId as a prefix. | ||
21 | + // e.g. 'star4' is installed as 'alarmsTopo-overlay-star4' | ||
22 | + // They can be referenced (from this overlay) as '*star4' | ||
23 | + // That is, the '*' prefix stands in for 'alarmsTopo-overlay-' | ||
24 | + glyphs: { | ||
25 | + star4: { | ||
26 | + vb: '0 0 8 8', | ||
27 | + // TODO new icon needed | ||
28 | + d: 'M1,4l2,-1l1,-2l1,2l2,1l-2,1l-1,2l-1,-2z' | ||
29 | + }, | ||
30 | + banner: { | ||
31 | + vb: '0 0 6 6', | ||
32 | + // TODO new icon needed | ||
33 | + d: 'M1,1v4l2,-2l2,2v-4z' | ||
34 | + } | ||
35 | + }, | ||
36 | + activate: function () { | ||
37 | + $log.debug("Alarm topology overlay ACTIVATED"); | ||
38 | + }, | ||
39 | + deactivate: function () { | ||
40 | + stds.stopDisplay(); | ||
41 | + $log.debug("Alarm topology overlay DEACTIVATED"); | ||
42 | + }, | ||
43 | + // detail panel button definitions | ||
44 | + buttons: { | ||
45 | + alarm1button: { | ||
46 | + gid: 'chain', | ||
47 | + tt: 'Show alarms for this device', | ||
48 | + cb: function (data) { | ||
49 | + $log.debug('Show alarms for selected device. data:', data); | ||
50 | + ns.navTo("alarmTable", {devId: data.id}); | ||
51 | + | ||
52 | + } | ||
53 | + }, | ||
54 | + alarm2button: { | ||
55 | + gid: '*banner', | ||
56 | + tt: 'Show alarms for all devices', | ||
57 | + cb: function (data) { | ||
58 | + $log.debug('Show alarms for all devices. data:', data); | ||
59 | + ns.navTo("alarmTable"); | ||
60 | + | ||
61 | + } | ||
62 | + } | ||
63 | + }, | ||
64 | + // Key bindings for traffic overlay buttons | ||
65 | + // NOTE: fully qual. button ID is derived from overlay-id and key-name | ||
66 | + keyBindings: { | ||
67 | + 0: { | ||
68 | + cb: function () { | ||
69 | + stds.stopDisplay(); | ||
70 | + }, | ||
71 | + tt: 'Cancel Alarm Count on Device', | ||
72 | + gid: 'xMark' | ||
73 | + }, | ||
74 | + V: { | ||
75 | + cb: function () { | ||
76 | + stds.startDisplay('mouse'); | ||
77 | + }, | ||
78 | + tt: 'Start Alarm Count on Device', | ||
79 | + gid: '*banner' | ||
80 | + }, | ||
81 | + _keyOrder: [ | ||
82 | + '0', 'V' | ||
83 | + ] | ||
84 | + }, | ||
85 | + hooks: { | ||
86 | + // hook for handling escape key | ||
87 | + // Must return true to consume ESC, false otherwise. | ||
88 | + escape: function () { | ||
89 | + // Must return true to consume ESC, false otherwise. | ||
90 | + return stds.stopDisplay(); | ||
91 | + }, | ||
92 | + // hooks for when the selection changes... | ||
93 | + empty: function () { | ||
94 | + selectionCallback('empty'); | ||
95 | + }, | ||
96 | + single: function (data) { | ||
97 | + selectionCallback('single', data); | ||
98 | + }, | ||
99 | + multi: function (selectOrder) { | ||
100 | + selectionCallback('multi', selectOrder); | ||
101 | + tov.addDetailButton('alarm1button'); | ||
102 | + tov.addDetailButton('alarm2button'); | ||
103 | + }, | ||
104 | + mouseover: function (m) { | ||
105 | + // m has id, class, and type properties | ||
106 | + $log.debug('mouseover:', m); | ||
107 | + stds.updateDisplay(m); | ||
108 | + }, | ||
109 | + mouseout: function () { | ||
110 | + $log.debug('mouseout'); | ||
111 | + stds.updateDisplay(); | ||
112 | + } | ||
113 | + } | ||
114 | + }; | ||
115 | + | ||
116 | + | ||
117 | + function buttonCallback(x) { | ||
118 | + $log.debug('Toolbar-button callback', x); | ||
119 | + } | ||
120 | + | ||
121 | + function selectionCallback(x, d) { | ||
122 | + $log.debug('Selection callback', x, d); | ||
123 | + } | ||
124 | + | ||
125 | + // invoke code to register with the overlay service | ||
126 | + angular.module('ovAlarmTopov') | ||
127 | + .run(['$log', 'TopoOverlayService', 'AlarmTopovDemoService', 'NavService', | ||
128 | + function (_$log_, _tov_, _stds_, _ns_) { | ||
129 | + $log = _$log_; | ||
130 | + tov = _tov_; | ||
131 | + stds = _stds_; | ||
132 | + ns = _ns_; | ||
133 | + tov.register(overlay); | ||
134 | + }]); | ||
135 | + | ||
136 | +}()); |
1 | +<link rel="stylesheet" href="app/view/alarmCustom/alarmCustom.css"> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +<script src="app/view/alarmCustom/alarmCustom.js"></script> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
apps/faultmanagement/fmgui/src/test/java/org/onosproject/faultmanagement/alarms/gui/README.txt
0 → 100644
1 | +# Need to write unit tests for the GUI server-side code ; write them after there are examples at web/gui/src/test/java/org/onosproject/ui/impl | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
... | @@ -45,6 +45,11 @@ | ... | @@ -45,6 +45,11 @@ |
45 | <version>${project.version}</version> | 45 | <version>${project.version}</version> |
46 | </dependency> | 46 | </dependency> |
47 | <dependency> | 47 | <dependency> |
48 | + <groupId>org.onosproject</groupId> | ||
49 | + <artifactId>onos-snmp-provider-alarm</artifactId> | ||
50 | + <version>${project.version}</version> | ||
51 | + </dependency> | ||
52 | + <dependency> | ||
48 | <groupId>org.osgi</groupId> | 53 | <groupId>org.osgi</groupId> |
49 | <artifactId>org.osgi.compendium</artifactId> | 54 | <artifactId>org.osgi.compendium</artifactId> |
50 | <version>5.0.0</version> | 55 | <version>5.0.0</version> | ... | ... |
... | @@ -15,13 +15,16 @@ | ... | @@ -15,13 +15,16 @@ |
15 | */ | 15 | */ |
16 | package org.onosproject.faultmanagement.impl; | 16 | package org.onosproject.faultmanagement.impl; |
17 | 17 | ||
18 | -import static com.google.common.base.Strings.isNullOrEmpty; | 18 | +import static com.google.common.base.Preconditions.checkNotNull; |
19 | import java.util.Dictionary; | 19 | import java.util.Dictionary; |
20 | import java.util.HashSet; | 20 | import java.util.HashSet; |
21 | import java.util.Map; | 21 | import java.util.Map; |
22 | import java.util.Set; | 22 | import java.util.Set; |
23 | import java.util.concurrent.ConcurrentHashMap; | 23 | import java.util.concurrent.ConcurrentHashMap; |
24 | -import java.util.concurrent.atomic.AtomicLong; | 24 | +import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; |
25 | +import java.util.concurrent.ScheduledExecutorService; | ||
26 | +import java.util.stream.Collectors; | ||
27 | +import org.apache.commons.collections.CollectionUtils; | ||
25 | import org.apache.felix.scr.annotations.Activate; | 28 | import org.apache.felix.scr.annotations.Activate; |
26 | import org.apache.felix.scr.annotations.Component; | 29 | import org.apache.felix.scr.annotations.Component; |
27 | import org.apache.felix.scr.annotations.Deactivate; | 30 | import org.apache.felix.scr.annotations.Deactivate; |
... | @@ -47,8 +50,15 @@ import org.onosproject.core.CoreService; | ... | @@ -47,8 +50,15 @@ import org.onosproject.core.CoreService; |
47 | import org.apache.felix.scr.annotations.Reference; | 50 | import org.apache.felix.scr.annotations.Reference; |
48 | import org.apache.felix.scr.annotations.ReferenceCardinality; | 51 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
49 | import org.onlab.util.ItemNotFoundException; | 52 | import org.onlab.util.ItemNotFoundException; |
53 | +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmProvider; | ||
50 | import org.onosproject.incubator.net.faultmanagement.alarm.DefaultAlarm; | 54 | import org.onosproject.incubator.net.faultmanagement.alarm.DefaultAlarm; |
55 | +import org.onosproject.net.device.DeviceService; | ||
51 | import org.osgi.service.component.ComponentContext; | 56 | import org.osgi.service.component.ComponentContext; |
57 | +import static java.util.concurrent.TimeUnit.SECONDS; | ||
58 | + | ||
59 | +import java.util.concurrent.atomic.AtomicLong; | ||
60 | +import static org.onlab.util.Tools.groupedThreads; | ||
61 | +import org.onosproject.net.Device; | ||
52 | 62 | ||
53 | /** | 63 | /** |
54 | * Implementation of the Alarm service. | 64 | * Implementation of the Alarm service. |
... | @@ -57,89 +67,133 @@ import org.osgi.service.component.ComponentContext; | ... | @@ -57,89 +67,133 @@ import org.osgi.service.component.ComponentContext; |
57 | @Service | 67 | @Service |
58 | public class AlarmsManager implements AlarmService { | 68 | public class AlarmsManager implements AlarmService { |
59 | 69 | ||
70 | + // For subscribing to device-related events | ||
60 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 71 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
61 | protected CoreService coreService; | 72 | protected CoreService coreService; |
73 | + | ||
74 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
75 | + protected DeviceService deviceService; | ||
76 | + | ||
77 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
78 | + protected AlarmProvider alarmProvider; | ||
79 | + | ||
62 | private final Logger log = getLogger(getClass()); | 80 | private final Logger log = getLogger(getClass()); |
63 | private ApplicationId appId; | 81 | private ApplicationId appId; |
64 | private IdGenerator idGenerator; | 82 | private IdGenerator idGenerator; |
65 | 83 | ||
84 | + private ScheduledExecutorService alarmPollExecutor; | ||
85 | + | ||
86 | + // dummy data | ||
87 | + private final AtomicLong alarmIdGenerator = new AtomicLong(0); | ||
66 | 88 | ||
67 | - @Property(name = "fmDevices", value = "127.0.0.1", label = "Instance-specific configurations") | 89 | + private AlarmId generateAlarmId() { |
68 | - private String devConfigs; | 90 | + return AlarmId.alarmId(alarmIdGenerator.incrementAndGet()); |
91 | + } | ||
69 | 92 | ||
70 | - private final Map<AlarmId, Alarm> alarms = new ConcurrentHashMap<>(); | 93 | + private static final int DEFAULT_POLL_FREQUENCY_SECONDS = 120; |
94 | + @Property(name = "alarmPollFrequencySeconds", intValue = DEFAULT_POLL_FREQUENCY_SECONDS, | ||
95 | + label = "Frequency (in seconds) for polling alarm from devices") | ||
96 | + private int alarmPollFrequencySeconds = DEFAULT_POLL_FREQUENCY_SECONDS; | ||
71 | 97 | ||
98 | + // TODO implement purging of old alarms. | ||
99 | + private static final int DEFAULT_CLEAR_FREQUENCY_SECONDS = 500; | ||
100 | + @Property(name = "clearedAlarmPurgeSeconds", intValue = DEFAULT_CLEAR_FREQUENCY_SECONDS, | ||
101 | + label = "Frequency (in seconds) for deleting cleared alarms") | ||
102 | + private int clearedAlarmPurgeFrequencySeconds = DEFAULT_CLEAR_FREQUENCY_SECONDS; | ||
72 | 103 | ||
73 | - private final AtomicLong alarmIdGenerator = new AtomicLong(0); | 104 | + // TODO Later should must be persisted to disk or database |
105 | + private final Map<AlarmId, Alarm> alarms = new ConcurrentHashMap<>(); | ||
74 | 106 | ||
75 | @Override | 107 | @Override |
76 | - public Alarm update(Alarm replacement) { | 108 | + public Alarm updateBookkeepingFields(AlarmId id, boolean isAcknowledged, String assignedUser) { |
109 | + | ||
110 | + Alarm found = alarms.get(id); | ||
111 | + if (found == null) { | ||
112 | + throw new ItemNotFoundException("Alarm with id " + id + " found"); | ||
113 | + } | ||
114 | + | ||
115 | + Alarm updated = new DefaultAlarm.Builder(found). | ||
116 | + withAcknowledged(isAcknowledged). | ||
117 | + withAssignedUser(assignedUser).build(); | ||
118 | + alarms.put(id, updated); | ||
119 | + return updated; | ||
120 | + } | ||
121 | + | ||
122 | + public Alarm clear(AlarmId id) { | ||
77 | 123 | ||
78 | - final Alarm found = alarms.get(replacement.id()); | 124 | + Alarm found = alarms.get(id); |
79 | if (found == null) { | 125 | if (found == null) { |
80 | - throw new ItemNotFoundException("Alarm with id " + replacement.id() + " found"); | 126 | + log.warn("id {} cant be cleared as it is already gone.", id); |
127 | + return null; | ||
81 | } | 128 | } |
82 | - final Alarm updated = new DefaultAlarm.Builder(found). | 129 | + Alarm updated = new DefaultAlarm.Builder(found).clear().build(); |
83 | - withAcknowledged(replacement.acknowledged()). | 130 | + alarms.put(id, updated); |
84 | - withAssignedUser(replacement.assignedUser()).build(); | ||
85 | - alarms.put(replacement.id(), updated); | ||
86 | return updated; | 131 | return updated; |
87 | } | 132 | } |
88 | 133 | ||
89 | @Override | 134 | @Override |
90 | - public int getActiveAlarmCount(DeviceId deviceId) { | 135 | + public Map<Alarm.SeverityLevel, Long> getAlarmCounts(DeviceId deviceId) { |
91 | - //TODO | 136 | + |
92 | - throw new UnsupportedOperationException(NOT_SUPPORTED_YET); | 137 | + return getAlarms(deviceId).stream().collect( |
138 | + Collectors.groupingBy(Alarm::severity, Collectors.counting())); | ||
139 | + | ||
140 | + } | ||
141 | + | ||
142 | + @Override | ||
143 | + public Map<Alarm.SeverityLevel, Long> getAlarmCounts() { | ||
144 | + | ||
145 | + return getAlarms().stream().collect( | ||
146 | + Collectors.groupingBy(Alarm::severity, Collectors.counting())); | ||
93 | } | 147 | } |
148 | + | ||
149 | + | ||
94 | private static final String NOT_SUPPORTED_YET = "Not supported yet."; | 150 | private static final String NOT_SUPPORTED_YET = "Not supported yet."; |
95 | 151 | ||
96 | @Override | 152 | @Override |
97 | public Alarm getAlarm(AlarmId alarmId) { | 153 | public Alarm getAlarm(AlarmId alarmId) { |
98 | return nullIsNotFound( | 154 | return nullIsNotFound( |
99 | - alarms.get(alarmId), | 155 | + alarms.get( |
156 | + checkNotNull(alarmId, "Alarm Id cannot be null")), | ||
100 | "Alarm is not found"); | 157 | "Alarm is not found"); |
101 | } | 158 | } |
102 | 159 | ||
103 | @Override | 160 | @Override |
104 | public Set<Alarm> getAlarms() { | 161 | public Set<Alarm> getAlarms() { |
105 | - //TODO | 162 | + return new HashSet<>(alarms.values()); |
106 | - throw new UnsupportedOperationException(NOT_SUPPORTED_YET); | ||
107 | } | 163 | } |
108 | 164 | ||
109 | @Override | 165 | @Override |
110 | public Set<Alarm> getActiveAlarms() { | 166 | public Set<Alarm> getActiveAlarms() { |
111 | - // Enpty set if no values | 167 | + return alarms.values().stream().filter( |
112 | - return alarms.isEmpty() ? new HashSet<>() : new HashSet<>(alarms.values()); | 168 | + a -> !a.severity().equals(Alarm.SeverityLevel.CLEARED)). |
113 | - | 169 | + collect(Collectors.toSet()); |
114 | - } | ||
115 | - | ||
116 | - private static DefaultAlarm generateFake(DeviceId deviceId, AlarmId alarmId) { | ||
117 | - | ||
118 | - return new DefaultAlarm.Builder( | ||
119 | - alarmId, deviceId, "NE is not reachable", Alarm.SeverityLevel.MAJOR, System.currentTimeMillis()). | ||
120 | - withTimeUpdated(System.currentTimeMillis()). | ||
121 | - withServiceAffecting(true) | ||
122 | - .withAcknowledged(true). | ||
123 | - withManuallyClearable(true) | ||
124 | - .withAssignedUser("user1").build(); | ||
125 | } | 170 | } |
126 | 171 | ||
127 | @Override | 172 | @Override |
128 | public Set<Alarm> getAlarms(Alarm.SeverityLevel severity) { | 173 | public Set<Alarm> getAlarms(Alarm.SeverityLevel severity) { |
129 | - //TODO | 174 | + return alarms.values().stream().filter( |
130 | - throw new UnsupportedOperationException(NOT_SUPPORTED_YET); | 175 | + a -> a.severity().equals(severity)). |
176 | + collect(Collectors.toSet()); | ||
131 | } | 177 | } |
132 | 178 | ||
133 | @Override | 179 | @Override |
134 | public Set<Alarm> getAlarms(DeviceId deviceId) { | 180 | public Set<Alarm> getAlarms(DeviceId deviceId) { |
135 | - //TODO | 181 | + return alarms.values().stream().filter( |
136 | - throw new UnsupportedOperationException(NOT_SUPPORTED_YET); | 182 | + a -> deviceId.equals(a.deviceId())). |
183 | + collect(Collectors.toSet()); | ||
184 | + } | ||
185 | + | ||
186 | + private Set<Alarm> getActiveAlarms(DeviceId deviceId) { | ||
187 | + return getActiveAlarms().stream().filter( | ||
188 | + a -> deviceId.equals(a.deviceId())). | ||
189 | + collect(Collectors.toSet()); | ||
137 | } | 190 | } |
138 | 191 | ||
139 | @Override | 192 | @Override |
140 | public Set<Alarm> getAlarms(DeviceId deviceId, AlarmEntityId source) { | 193 | public Set<Alarm> getAlarms(DeviceId deviceId, AlarmEntityId source) { |
141 | - //TODO | 194 | + return getAlarms(deviceId).stream().filter( |
142 | - throw new UnsupportedOperationException(NOT_SUPPORTED_YET); | 195 | + a -> source.equals(a.source()) |
196 | + ).collect(Collectors.toSet()); | ||
143 | } | 197 | } |
144 | 198 | ||
145 | @Override | 199 | @Override |
... | @@ -154,41 +208,92 @@ public class AlarmsManager implements AlarmService { | ... | @@ -154,41 +208,92 @@ public class AlarmsManager implements AlarmService { |
154 | throw new UnsupportedOperationException(NOT_SUPPORTED_YET); | 208 | throw new UnsupportedOperationException(NOT_SUPPORTED_YET); |
155 | } | 209 | } |
156 | 210 | ||
157 | - private void discoverAlarmsForDevice(DeviceId deviceId) { | 211 | + private final AlarmListener alarmListener = new InternalAlarmListener(); |
158 | - final AlarmId alarmId = new AlarmId(alarmIdGenerator.incrementAndGet()); | ||
159 | - | ||
160 | - // TODO In a new thread invoke SNMP Provider with DeviceId and device type and when done update our of alarms | ||
161 | - // | ||
162 | - alarms.put(alarmId, generateFake(deviceId, alarmId)); | ||
163 | - | ||
164 | - } | ||
165 | 212 | ||
166 | private class InternalAlarmListener implements AlarmListener { | 213 | private class InternalAlarmListener implements AlarmListener { |
167 | 214 | ||
168 | @Override | 215 | @Override |
169 | public void event(AlarmEvent event) { | 216 | public void event(AlarmEvent event) { |
170 | - // TODO | 217 | + log.debug("AlarmsManager. InternalAlarmListener received {}", event); |
171 | - throw new UnsupportedOperationException(NOT_SUPPORTED_YET); | 218 | + try { |
219 | + | ||
220 | + switch (event.type()) { | ||
221 | + case DEVICE_DISCOVERY: | ||
222 | + DeviceId deviceId = checkNotNull(event.getDeviceRefreshed(), "Listener cannot be null"); | ||
223 | + log.info("New alarm set for {} received!", deviceId); | ||
224 | + updateAlarms(event.subject(), deviceId); | ||
225 | + break; | ||
226 | + | ||
227 | + case NOTIFICATION: | ||
228 | + throw new IllegalArgumentException( | ||
229 | + "Alarm Notifications (Traps) not expected or implemented yet. Received =" + event); | ||
230 | + default: | ||
231 | + break; | ||
232 | + } | ||
233 | + } catch (Exception e) { | ||
234 | + log.warn("Failed to process {}", event, e); | ||
235 | + } | ||
172 | } | 236 | } |
173 | } | 237 | } |
174 | 238 | ||
175 | @Activate | 239 | @Activate |
176 | public void activate(ComponentContext context) { | 240 | public void activate(ComponentContext context) { |
177 | - log.info("Activate ..."); | 241 | + appId = coreService.registerApplication("org.onosproject.faultmanagement.alarms"); |
178 | - appId = coreService.registerApplication("org.onos.faultmanagement.alarms"); | ||
179 | idGenerator = coreService.getIdGenerator("alarm-ids"); | 242 | idGenerator = coreService.getIdGenerator("alarm-ids"); |
180 | - log.info("Started with appId={} idGenerator={}", appId, idGenerator); | 243 | + log.info("Started with appId={}", appId); |
244 | + | ||
245 | + alarmProvider.addAlarmListener(alarmListener); | ||
181 | 246 | ||
182 | - final boolean result = modified(context); | 247 | + probeActiveDevices(); |
248 | + | ||
249 | + boolean result = modified(context); | ||
183 | log.info("modified result = {}", result); | 250 | log.info("modified result = {}", result); |
184 | 251 | ||
252 | + alarmPollExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/fm", "alarms-poll-%d")); | ||
253 | + alarmPollExecutor.scheduleAtFixedRate(new PollAlarmsTask(), | ||
254 | + alarmPollFrequencySeconds, alarmPollFrequencySeconds, SECONDS); | ||
255 | + | ||
256 | + } | ||
257 | + | ||
258 | + /** | ||
259 | + * Auxiliary task to keep alarms up to date. IN future release alarm-notifications will be used as an optimization | ||
260 | + * so we dont have to wait until polling to detect changes. Furthermore with simple polling flapping alarms may be | ||
261 | + * missed. | ||
262 | + */ | ||
263 | + private final class PollAlarmsTask implements Runnable { | ||
264 | + | ||
265 | + @Override | ||
266 | + public void run() { | ||
267 | + if (Thread.currentThread().isInterrupted()) { | ||
268 | + log.info("Interrupted, quitting"); | ||
269 | + return; | ||
270 | + } | ||
271 | + try { | ||
272 | + probeActiveDevices(); | ||
273 | + } catch (RuntimeException e) { | ||
274 | + log.error("Exception thrown during alarm synchronization process", e); | ||
275 | + } | ||
276 | + } | ||
277 | + } | ||
278 | + | ||
279 | + private void probeActiveDevices() { | ||
280 | + Iterable<Device> devices = deviceService.getAvailableDevices(); | ||
281 | + log.info("Refresh alarms for all available devices={} ...", devices); | ||
282 | + for (Device d : devices) { | ||
283 | + log.info("Lets tell alarm provider to refresh alarms for {} ...", d.id()); | ||
284 | + alarmProvider.triggerProbe(d.id()); | ||
285 | + } | ||
185 | } | 286 | } |
186 | 287 | ||
187 | @Deactivate | 288 | @Deactivate |
188 | public void deactivate(ComponentContext context) { | 289 | public void deactivate(ComponentContext context) { |
189 | log.info("Deactivate ..."); | 290 | log.info("Deactivate ..."); |
190 | - // cfgService.unregisterProperties(getClass(), false); | 291 | + alarmProvider.removeAlarmListener(alarmListener); |
191 | 292 | ||
293 | + if (alarmPollExecutor != null) { | ||
294 | + alarmPollExecutor.shutdownNow(); | ||
295 | + } | ||
296 | + alarms.clear(); | ||
192 | log.info("Stopped"); | 297 | log.info("Stopped"); |
193 | } | 298 | } |
194 | 299 | ||
... | @@ -199,24 +304,36 @@ public class AlarmsManager implements AlarmService { | ... | @@ -199,24 +304,36 @@ public class AlarmsManager implements AlarmService { |
199 | log.info("No configuration file"); | 304 | log.info("No configuration file"); |
200 | return false; | 305 | return false; |
201 | } | 306 | } |
202 | - final Dictionary<?, ?> properties = context.getProperties(); | 307 | + Dictionary<?, ?> properties = context.getProperties(); |
203 | - final String ipaddresses = get(properties, "fmDevices"); | 308 | + String clearedAlarmPurgeSeconds = get(properties, "clearedAlarmPurgeSeconds"); |
204 | - log.info("Settings: devConfigs={}", ipaddresses); | 309 | + |
205 | - if (!isNullOrEmpty(ipaddresses)) { | 310 | + log.info("Settings: clearedAlarmPurgeSeconds={}", clearedAlarmPurgeSeconds); |
206 | - discover(ipaddresses); | ||
207 | 311 | ||
208 | - } | ||
209 | return true; | 312 | return true; |
210 | } | 313 | } |
211 | 314 | ||
212 | - private void discover(String ipaddresses) { | 315 | + // Synchronised to prevent duplicate NE alarms being raised |
213 | - for (String deviceEntry : ipaddresses.split(",")) { | 316 | + synchronized void updateAlarms(Set<Alarm> discoveredSet, DeviceId deviceId) { |
214 | - final DeviceId deviceId = DeviceId.deviceId(deviceEntry); | 317 | + Set<Alarm> storedSet = getActiveAlarms(deviceId); |
215 | - if (deviceId != null) { | 318 | + log.trace("currentNeAlarms={}. discoveredAlarms={}", storedSet, discoveredSet); |
216 | - log.info("Device {} needs to have its alarms refreshed!", deviceId); | 319 | + |
217 | - discoverAlarmsForDevice(deviceId); | 320 | + if (CollectionUtils.isEqualCollection(storedSet, discoveredSet)) { |
218 | - } | 321 | + log.debug("Alarm lists are equivalent so no update for {}.", deviceId); |
322 | + return; | ||
219 | } | 323 | } |
324 | + | ||
325 | + storedSet.stream().filter( | ||
326 | + (stored) -> (!discoveredSet.contains(stored))).forEach((stored) -> { | ||
327 | + log.info("Alarm will be cleared as it is not on the element. Cleared alarm: {}.", stored); | ||
328 | + clear(stored.id()); | ||
329 | + }); | ||
330 | + | ||
331 | + discoveredSet.stream().filter( | ||
332 | + (discovered) -> (!storedSet.contains(discovered))).forEach((discovered) -> { | ||
333 | + log.info("Alarm will be raised as it is missing. New alarm: {}.", discovered); | ||
334 | + AlarmId id = generateAlarmId(); | ||
335 | + alarms.put(id, new DefaultAlarm.Builder(discovered).withId(id).build()); | ||
336 | + }); | ||
220 | } | 337 | } |
221 | 338 | ||
222 | } | 339 | } | ... | ... |
apps/faultmanagement/fmmgr/src/test/java/org/onosproject/faultmanagement/impl/AlarmsManagerTest.java
0 → 100644
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.faultmanagement.impl; | ||
17 | + | ||
18 | +import com.google.common.collect.Sets; | ||
19 | +import java.util.Collections; | ||
20 | +import java.util.HashMap; | ||
21 | +import java.util.HashSet; | ||
22 | +import java.util.Map; | ||
23 | +import org.junit.Test; | ||
24 | +import static org.junit.Assert.*; | ||
25 | +import org.onlab.util.ItemNotFoundException; | ||
26 | +import org.onosproject.net.DeviceId; | ||
27 | +import static org.hamcrest.Matchers.containsString; | ||
28 | +import org.onosproject.incubator.net.faultmanagement.alarm.Alarm; | ||
29 | +import static org.onosproject.incubator.net.faultmanagement.alarm.Alarm.SeverityLevel.*; | ||
30 | +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmEntityId; | ||
31 | +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmId; | ||
32 | +import org.onosproject.incubator.net.faultmanagement.alarm.DefaultAlarm; | ||
33 | + | ||
34 | +public class AlarmsManagerTest { | ||
35 | + | ||
36 | + @Test | ||
37 | + public void testGettersWhenNoAlarms() { | ||
38 | + AlarmsManager am = new AlarmsManager(); | ||
39 | + assertTrue("No alarms", am.getAlarms().isEmpty()); | ||
40 | + assertTrue("No active alarms", am.getActiveAlarms().isEmpty()); | ||
41 | + assertTrue("No alarms gives empty map per unknown device", am.getAlarmCounts(DeviceId.NONE).keySet().isEmpty()); | ||
42 | + assertTrue("No alarms gives empty map", am.getAlarmCounts().keySet().isEmpty()); | ||
43 | + | ||
44 | + assertEquals("Zero alarms for that device", 0, am.getAlarms(DeviceId.NONE).size()); | ||
45 | + assertEquals("Zero major alarms", 0, am.getAlarms(Alarm.SeverityLevel.MAJOR).size()); | ||
46 | + | ||
47 | + try { | ||
48 | + assertEquals("no alarms", 0, am.getAlarm(null)); | ||
49 | + } catch (NullPointerException ex) { | ||
50 | + assertThat(ex.getMessage(), | ||
51 | + containsString("cannot be null")); | ||
52 | + } | ||
53 | + | ||
54 | + try { | ||
55 | + assertEquals("no alarms", 0, am.getAlarm(AlarmId.alarmId(1))); | ||
56 | + } catch (ItemNotFoundException ex) { | ||
57 | + assertThat(ex.getMessage(), | ||
58 | + containsString("not found")); | ||
59 | + } | ||
60 | + } | ||
61 | + | ||
62 | + @Test | ||
63 | + public void testAlarmUpdates() { | ||
64 | + AlarmsManager am = new AlarmsManager(); | ||
65 | + assertTrue("no alarms", am.getAlarms().isEmpty()); | ||
66 | + | ||
67 | + am.updateAlarms(new HashSet<>(), DEVICE_ID); | ||
68 | + assertTrue("still no alarms", am.getAlarms().isEmpty()); | ||
69 | + Map<Alarm.SeverityLevel, Long> zeroAlarms = new CountsMapBuilder().create(); | ||
70 | + assertEquals(zeroAlarms, am.getAlarmCounts()); | ||
71 | + assertEquals(zeroAlarms, am.getAlarmCounts(DEVICE_ID)); | ||
72 | + | ||
73 | + am.updateAlarms(Sets.newHashSet(ALARM_B, ALARM_A), DEVICE_ID); | ||
74 | + verifyGettingSetsOfAlarms(am, 2, 2); | ||
75 | + Map<Alarm.SeverityLevel, Long> critical2 = new CountsMapBuilder().with(CRITICAL, 2L).create(); | ||
76 | + assertEquals(critical2, am.getAlarmCounts()); | ||
77 | + assertEquals(critical2, am.getAlarmCounts(DEVICE_ID)); | ||
78 | + | ||
79 | + am.updateAlarms(Sets.newHashSet(ALARM_A), DEVICE_ID); | ||
80 | + verifyGettingSetsOfAlarms(am, 2, 1); | ||
81 | + Map<Alarm.SeverityLevel, Long> critical1cleared1 = | ||
82 | + new CountsMapBuilder().with(CRITICAL, 1L).with(CLEARED, 1L).create(); | ||
83 | + assertEquals(critical1cleared1, am.getAlarmCounts()); | ||
84 | + assertEquals(critical1cleared1, am.getAlarmCounts(DEVICE_ID)); | ||
85 | + | ||
86 | + // No change map when same alarms sent | ||
87 | + am.updateAlarms(Sets.newHashSet(ALARM_A), DEVICE_ID); | ||
88 | + verifyGettingSetsOfAlarms(am, 2, 1); | ||
89 | + assertEquals(critical1cleared1, am.getAlarmCounts()); | ||
90 | + assertEquals(critical1cleared1, am.getAlarmCounts(DEVICE_ID)); | ||
91 | + | ||
92 | + am.updateAlarms(Sets.newHashSet(ALARM_A, ALARM_A_WITHSRC), DEVICE_ID); | ||
93 | + verifyGettingSetsOfAlarms(am, 3, 2); | ||
94 | + Map<Alarm.SeverityLevel, Long> critical2cleared1 = | ||
95 | + new CountsMapBuilder().with(CRITICAL, 2L).with(CLEARED, 1L).create(); | ||
96 | + assertEquals(critical2cleared1, am.getAlarmCounts()); | ||
97 | + assertEquals(critical2cleared1, am.getAlarmCounts(DEVICE_ID)); | ||
98 | + | ||
99 | + am.updateAlarms(Sets.newHashSet(), DEVICE_ID); | ||
100 | + verifyGettingSetsOfAlarms(am, 3, 0); | ||
101 | + assertEquals(new CountsMapBuilder().with(CLEARED, 3L).create(), am.getAlarmCounts(DEVICE_ID)); | ||
102 | + | ||
103 | + assertEquals("No alarms for unknown devices", zeroAlarms, am.getAlarmCounts(DeviceId.NONE)); | ||
104 | + assertEquals("No alarms for unknown devices", zeroAlarms, am.getAlarmCounts(DeviceId.deviceId("junk:junk"))); | ||
105 | + | ||
106 | + } | ||
107 | + | ||
108 | + private void verifyGettingSetsOfAlarms(AlarmsManager am, int expectedTotal, int expectedActive) { | ||
109 | + assertEquals("Wrong total", expectedTotal, am.getAlarms().size()); | ||
110 | + assertEquals("Wrong active count", expectedActive, am.getActiveAlarms().size()); | ||
111 | + } | ||
112 | + private static final DeviceId DEVICE_ID = DeviceId.deviceId("foo:bar"); | ||
113 | + private static final DefaultAlarm ALARM_A = new DefaultAlarm.Builder( | ||
114 | + DEVICE_ID, "aaa", Alarm.SeverityLevel.CRITICAL, 0).build(); | ||
115 | + | ||
116 | + private static final DefaultAlarm ALARM_A_WITHSRC = new DefaultAlarm.Builder( | ||
117 | + ALARM_A).forSource(AlarmEntityId.alarmEntityId("port:foo")).build(); | ||
118 | + | ||
119 | + private static final DefaultAlarm ALARM_B = new DefaultAlarm.Builder( | ||
120 | + DEVICE_ID, "bbb", Alarm.SeverityLevel.CRITICAL, 0).build(); | ||
121 | + | ||
122 | + private static class CountsMapBuilder { | ||
123 | + | ||
124 | + private final Map<Alarm.SeverityLevel, Long> map = new HashMap<>(); | ||
125 | + | ||
126 | + public CountsMapBuilder with(Alarm.SeverityLevel sev, Long count) { | ||
127 | + map.put(sev, count); | ||
128 | + return this; | ||
129 | + } | ||
130 | + | ||
131 | + public Map<Alarm.SeverityLevel, Long> create() { | ||
132 | + return Collections.unmodifiableMap(map); | ||
133 | + } | ||
134 | + } | ||
135 | + | ||
136 | +} |
... | @@ -124,6 +124,7 @@ | ... | @@ -124,6 +124,7 @@ |
124 | com.fasterxml.jackson.core, | 124 | com.fasterxml.jackson.core, |
125 | org.apache.karaf.shell.commands, | 125 | org.apache.karaf.shell.commands, |
126 | org.apache.commons.lang.math.*, | 126 | org.apache.commons.lang.math.*, |
127 | + org.apache.commons.lang.*, | ||
127 | com.google.common.*, | 128 | com.google.common.*, |
128 | org.onlab.packet.*, | 129 | org.onlab.packet.*, |
129 | org.onlab.rest.*, | 130 | org.onlab.rest.*, | ... | ... |
... | @@ -66,28 +66,29 @@ public final class AlarmCodec extends JsonCodec<Alarm> { | ... | @@ -66,28 +66,29 @@ public final class AlarmCodec extends JsonCodec<Alarm> { |
66 | } | 66 | } |
67 | 67 | ||
68 | log.debug("id={}, full json={} ", json.get("id"), json); | 68 | log.debug("id={}, full json={} ", json.get("id"), json); |
69 | - final Long id = json.get("id").asLong(); | 69 | + Long id = json.get("id").asLong(); |
70 | 70 | ||
71 | - final DeviceId deviceId = DeviceId.deviceId(json.get("deviceId").asText()); | 71 | + DeviceId deviceId = DeviceId.deviceId(json.get("deviceId").asText()); |
72 | - final String description = json.get("description").asText(); | 72 | + String description = json.get("description").asText(); |
73 | - final Long timeRaised = json.get("timeRaised").asLong(); | 73 | + Long timeRaised = json.get("timeRaised").asLong(); |
74 | - final Long timeUpdated = json.get("timeUpdated").asLong(); | 74 | + Long timeUpdated = json.get("timeUpdated").asLong(); |
75 | 75 | ||
76 | - final JsonNode jsonTimeCleared = json.get("timeCleared"); | 76 | + JsonNode jsonTimeCleared = json.get("timeCleared"); |
77 | - final Long timeCleared = jsonTimeCleared == null || jsonTimeCleared.isNull() ? null : jsonTimeCleared.asLong(); | 77 | + Long timeCleared = jsonTimeCleared == null || jsonTimeCleared.isNull() ? null : jsonTimeCleared.asLong(); |
78 | 78 | ||
79 | - final Alarm.SeverityLevel severity = Alarm.SeverityLevel.valueOf(json.get("severity").asText().toUpperCase()); | 79 | + Alarm.SeverityLevel severity = Alarm.SeverityLevel.valueOf(json.get("severity").asText().toUpperCase()); |
80 | 80 | ||
81 | - final Boolean serviceAffecting = json.get("serviceAffecting").asBoolean(); | 81 | + Boolean serviceAffecting = json.get("serviceAffecting").asBoolean(); |
82 | - final Boolean acknowledged = json.get("acknowledged").asBoolean(); | 82 | + Boolean acknowledged = json.get("acknowledged").asBoolean(); |
83 | - final Boolean manuallyClearable = json.get("manuallyClearable").asBoolean(); | 83 | + Boolean manuallyClearable = json.get("manuallyClearable").asBoolean(); |
84 | 84 | ||
85 | - final JsonNode jsonAssignedUser = json.get("assignedUser"); | 85 | + JsonNode jsonAssignedUser = json.get("assignedUser"); |
86 | - final String assignedUser | 86 | + String assignedUser |
87 | = jsonAssignedUser == null || jsonAssignedUser.isNull() ? null : jsonAssignedUser.asText(); | 87 | = jsonAssignedUser == null || jsonAssignedUser.isNull() ? null : jsonAssignedUser.asText(); |
88 | 88 | ||
89 | return new DefaultAlarm.Builder( | 89 | return new DefaultAlarm.Builder( |
90 | - AlarmId.valueOf(id), deviceId, description, severity, timeRaised).forSource(AlarmEntityId.NONE). | 90 | + deviceId, description, severity, timeRaised).forSource(AlarmEntityId.NONE). |
91 | + withId(AlarmId.alarmId(id)). | ||
91 | withTimeUpdated(timeUpdated). | 92 | withTimeUpdated(timeUpdated). |
92 | withTimeCleared(timeCleared). | 93 | withTimeCleared(timeCleared). |
93 | withServiceAffecting(serviceAffecting). | 94 | withServiceAffecting(serviceAffecting). | ... | ... |
1 | /* | 1 | /* |
2 | - * Copyright 2014-2015 Open Networking Laboratory | 2 | + * Copyright 2015 Open Networking Laboratory |
3 | * | 3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
... | @@ -34,7 +34,9 @@ import javax.ws.rs.PathParam; | ... | @@ -34,7 +34,9 @@ import javax.ws.rs.PathParam; |
34 | import javax.ws.rs.Produces; | 34 | import javax.ws.rs.Produces; |
35 | import javax.ws.rs.QueryParam; | 35 | import javax.ws.rs.QueryParam; |
36 | import javax.ws.rs.core.MediaType; | 36 | import javax.ws.rs.core.MediaType; |
37 | +import org.apache.commons.lang.StringUtils; | ||
37 | import org.onosproject.incubator.net.faultmanagement.alarm.AlarmService; | 38 | import org.onosproject.incubator.net.faultmanagement.alarm.AlarmService; |
39 | +import org.onosproject.net.DeviceId; | ||
38 | import org.slf4j.Logger; | 40 | import org.slf4j.Logger; |
39 | import static org.slf4j.LoggerFactory.getLogger; | 41 | import static org.slf4j.LoggerFactory.getLogger; |
40 | 42 | ||
... | @@ -48,31 +50,32 @@ public class AlarmsWebResource extends AbstractWebResource { | ... | @@ -48,31 +50,32 @@ public class AlarmsWebResource extends AbstractWebResource { |
48 | 50 | ||
49 | private final Logger log = getLogger(getClass()); | 51 | private final Logger log = getLogger(getClass()); |
50 | 52 | ||
51 | - public AlarmsWebResource() { | ||
52 | - } | ||
53 | - | ||
54 | /** | 53 | /** |
55 | - * Get all alarms. Returns a list of all alarms across all devices. | 54 | + * Get alarms. Returns a list of alarms |
56 | * | 55 | * |
57 | - * @param includeCleared include recently cleared alarms in response | 56 | + * @param includeCleared (optional) include recently cleared alarms in response |
57 | + * @param devId (optional) include only for specified device | ||
58 | * @return JSON encoded set of alarms | 58 | * @return JSON encoded set of alarms |
59 | */ | 59 | */ |
60 | @GET | 60 | @GET |
61 | @Produces(MediaType.APPLICATION_JSON) | 61 | @Produces(MediaType.APPLICATION_JSON) |
62 | - public Response getAlarms(@DefaultValue("false") @QueryParam("includeCleared") boolean includeCleared | 62 | + public Response getAlarms(@DefaultValue("false") @QueryParam("includeCleared") boolean includeCleared, |
63 | + @DefaultValue("") @QueryParam("devId") String devId | ||
63 | ) { | 64 | ) { |
64 | 65 | ||
65 | log.info("Requesting all alarms, includeCleared={}", includeCleared); | 66 | log.info("Requesting all alarms, includeCleared={}", includeCleared); |
66 | - final AlarmService service = get(AlarmService.class); | 67 | + AlarmService service = get(AlarmService.class); |
67 | 68 | ||
68 | - final Iterable<Alarm> alarms = includeCleared | 69 | + Iterable<Alarm> alarms; |
70 | + if (StringUtils.isBlank(devId)) { | ||
71 | + alarms = includeCleared | ||
69 | ? service.getAlarms() | 72 | ? service.getAlarms() |
70 | : service.getActiveAlarms(); | 73 | : service.getActiveAlarms(); |
71 | - | 74 | + } else { |
72 | - final ObjectNode result = new ObjectMapper().createObjectNode(); | 75 | + alarms = service.getAlarms(DeviceId.deviceId(devId)); |
73 | - result.set("alarms", | 76 | + } |
74 | - codec(Alarm.class). | 77 | + ObjectNode result = new ObjectMapper().createObjectNode(); |
75 | - encode(alarms, this)); | 78 | + result.set("alarms", new AlarmCodec().encode(alarms, this)); |
76 | return ok(result.toString()).build(); | 79 | return ok(result.toString()).build(); |
77 | 80 | ||
78 | } | 81 | } |
... | @@ -89,11 +92,11 @@ public class AlarmsWebResource extends AbstractWebResource { | ... | @@ -89,11 +92,11 @@ public class AlarmsWebResource extends AbstractWebResource { |
89 | public Response getAlarm(@PathParam("id") String id) { | 92 | public Response getAlarm(@PathParam("id") String id) { |
90 | log.info("HTTP GET alarm for id={}", id); | 93 | log.info("HTTP GET alarm for id={}", id); |
91 | 94 | ||
92 | - final AlarmId alarmId = toAlarmId(id); | 95 | + AlarmId alarmId = toAlarmId(id); |
93 | - final Alarm alarm = get(AlarmService.class).getAlarm(alarmId); | 96 | + Alarm alarm = get(AlarmService.class).getAlarm(alarmId); |
94 | 97 | ||
95 | - final ObjectNode result = mapper().createObjectNode(); | 98 | + ObjectNode result = new ObjectMapper().createObjectNode(); |
96 | - result.set("alarm", codec(Alarm.class).encode(alarm, this)); | 99 | + result.set("alarm", new AlarmCodec().encode(alarm, this)); |
97 | return ok(result.toString()).build(); | 100 | return ok(result.toString()).build(); |
98 | } | 101 | } |
99 | 102 | ||
... | @@ -113,20 +116,22 @@ public class AlarmsWebResource extends AbstractWebResource { | ... | @@ -113,20 +116,22 @@ public class AlarmsWebResource extends AbstractWebResource { |
113 | log.info("PUT NEW ALARM at /{}", alarmIdPath); | 116 | log.info("PUT NEW ALARM at /{}", alarmIdPath); |
114 | 117 | ||
115 | try { | 118 | try { |
116 | - final ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream); | 119 | + ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream); |
117 | log.info("jsonTree={}", jsonTree); | 120 | log.info("jsonTree={}", jsonTree); |
118 | 121 | ||
119 | - final Alarm alarm = codec(Alarm.class).decode(jsonTree, this); | 122 | + Alarm alarm = new AlarmCodec().decode(jsonTree, this); |
120 | 123 | ||
121 | - final AlarmService service = get(AlarmService.class); | 124 | + AlarmService service = get(AlarmService.class); |
122 | 125 | ||
123 | if (Long.parseLong(alarmIdPath) != alarm.id().fingerprint()) { | 126 | if (Long.parseLong(alarmIdPath) != alarm.id().fingerprint()) { |
124 | throw new IllegalArgumentException("id in path is " + Long.parseLong(alarmIdPath) | 127 | throw new IllegalArgumentException("id in path is " + Long.parseLong(alarmIdPath) |
125 | + " but payload uses id=" + alarm.id().fingerprint()); | 128 | + " but payload uses id=" + alarm.id().fingerprint()); |
126 | 129 | ||
127 | } | 130 | } |
128 | - final Alarm updated = service.update(alarm); | 131 | + Alarm updated = service.updateBookkeepingFields( |
129 | - final ObjectNode encoded = new AlarmCodec().encode(updated, this); | 132 | + alarm.id(), alarm.acknowledged(), alarm.assignedUser() |
133 | + ); | ||
134 | + ObjectNode encoded = new AlarmCodec().encode(updated, this); | ||
130 | return ok(encoded.toString()).build(); | 135 | return ok(encoded.toString()).build(); |
131 | 136 | ||
132 | } catch (IOException ioe) { | 137 | } catch (IOException ioe) { |
... | @@ -136,7 +141,7 @@ public class AlarmsWebResource extends AbstractWebResource { | ... | @@ -136,7 +141,7 @@ public class AlarmsWebResource extends AbstractWebResource { |
136 | 141 | ||
137 | private static AlarmId toAlarmId(String id) { | 142 | private static AlarmId toAlarmId(String id) { |
138 | try { | 143 | try { |
139 | - return AlarmId.valueOf(Long.parseLong(id)); | 144 | + return AlarmId.alarmId(Long.parseLong(id)); |
140 | } catch (NumberFormatException ex) { | 145 | } catch (NumberFormatException ex) { |
141 | throw new IllegalArgumentException("Alarm id should be numeric", ex); | 146 | throw new IllegalArgumentException("Alarm id should be numeric", ex); |
142 | } | 147 | } | ... | ... |
... | @@ -25,7 +25,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; | ... | @@ -25,7 +25,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; |
25 | /** | 25 | /** |
26 | * Mock codec context for use in codec unit tests. | 26 | * Mock codec context for use in codec unit tests. |
27 | */ | 27 | */ |
28 | -public class AlarmCodecContext implements CodecContext { | 28 | +public final class AlarmCodecContext implements CodecContext { |
29 | 29 | ||
30 | private final ObjectMapper mapper = new ObjectMapper(); | 30 | private final ObjectMapper mapper = new ObjectMapper(); |
31 | private final CodecManager codecManager = new CodecManager(); | 31 | private final CodecManager codecManager = new CodecManager(); | ... | ... |
... | @@ -36,37 +36,26 @@ import org.onosproject.incubator.net.faultmanagement.alarm.DefaultAlarm; | ... | @@ -36,37 +36,26 @@ import org.onosproject.incubator.net.faultmanagement.alarm.DefaultAlarm; |
36 | public class AlarmCodecTest { | 36 | public class AlarmCodecTest { |
37 | 37 | ||
38 | private final AlarmCodecContext context = new AlarmCodecContext(); | 38 | private final AlarmCodecContext context = new AlarmCodecContext(); |
39 | + private static final AlarmId ALARM_ID = AlarmId.alarmId(44); | ||
39 | 40 | ||
40 | // Use this to check handling for miminal Alarm | 41 | // Use this to check handling for miminal Alarm |
41 | private final Alarm alarmMinimumFields = new DefaultAlarm.Builder( | 42 | private final Alarm alarmMinimumFields = new DefaultAlarm.Builder( |
42 | - new AlarmId(44), | 43 | + DeviceId.deviceId("of:2222000000000000"), "NE unreachable", Alarm.SeverityLevel.CLEARED, 1 |
43 | - DeviceId.deviceId("of:2222000000000000"), | 44 | + ).withId(ALARM_ID).build(); |
44 | - "NE unreachable", | ||
45 | - Alarm.SeverityLevel.CLEARED, | ||
46 | - 1). | ||
47 | - build(); | ||
48 | 45 | ||
49 | // Use this to check handling for fully populated Alarm | 46 | // Use this to check handling for fully populated Alarm |
50 | private final Alarm alarmWithSource = new DefaultAlarm.Builder( | 47 | private final Alarm alarmWithSource = new DefaultAlarm.Builder( |
51 | - new AlarmId(44), | 48 | + DeviceId.deviceId("of:2222000000000000"), "NE unreachable", Alarm.SeverityLevel.CLEARED, 1 |
52 | - DeviceId.deviceId("of:2222000000000000"), | 49 | + ).withId(ALARM_ID).forSource(AlarmEntityId.alarmEntityId("port:1/2/3/4")).withTimeUpdated(2).withTimeCleared(3L). |
53 | - "NE unreachable", | 50 | + withServiceAffecting(true).withAcknowledged(true).withManuallyClearable(true). |
54 | - Alarm.SeverityLevel.CLEARED, 1). | ||
55 | - forSource(AlarmEntityId.alarmEntityId("port:1/2/3/4")). | ||
56 | - withTimeUpdated(2). | ||
57 | - withTimeCleared(3L). | ||
58 | - withServiceAffecting(true). | ||
59 | - withAcknowledged(true). | ||
60 | - withManuallyClearable(true). | ||
61 | withAssignedUser("the assigned user").build(); | 51 | withAssignedUser("the assigned user").build(); |
62 | 52 | ||
63 | @Test | 53 | @Test |
64 | public void alarmCodecTestWithOptionalFieldMissing() { | 54 | public void alarmCodecTestWithOptionalFieldMissing() { |
65 | - //context.registerService(AlarmService.class, new AlarmServiceAdapter()); | 55 | + JsonCodec<Alarm> codec = context.codec(Alarm.class); |
66 | - final JsonCodec<Alarm> codec = context.codec(Alarm.class); | ||
67 | assertThat(codec, is(notNullValue())); | 56 | assertThat(codec, is(notNullValue())); |
68 | 57 | ||
69 | - final ObjectNode alarmJson = codec.encode(alarmMinimumFields, context); | 58 | + ObjectNode alarmJson = codec.encode(alarmMinimumFields, context); |
70 | assertThat(alarmJson, notNullValue()); | 59 | assertThat(alarmJson, notNullValue()); |
71 | assertThat(alarmJson, matchesAlarm(alarmMinimumFields)); | 60 | assertThat(alarmJson, matchesAlarm(alarmMinimumFields)); |
72 | 61 | ||
... | @@ -74,10 +63,10 @@ public class AlarmCodecTest { | ... | @@ -74,10 +63,10 @@ public class AlarmCodecTest { |
74 | 63 | ||
75 | @Test | 64 | @Test |
76 | public void alarmCodecTestWithOptionalField() { | 65 | public void alarmCodecTestWithOptionalField() { |
77 | - final JsonCodec<Alarm> codec = context.codec(Alarm.class); | 66 | + JsonCodec<Alarm> codec = context.codec(Alarm.class); |
78 | assertThat(codec, is(notNullValue())); | 67 | assertThat(codec, is(notNullValue())); |
79 | 68 | ||
80 | - final ObjectNode alarmJson = codec.encode(alarmWithSource, context); | 69 | + ObjectNode alarmJson = codec.encode(alarmWithSource, context); |
81 | assertThat(alarmJson, notNullValue()); | 70 | assertThat(alarmJson, notNullValue()); |
82 | assertThat(alarmJson, matchesAlarm(alarmWithSource)); | 71 | assertThat(alarmJson, matchesAlarm(alarmWithSource)); |
83 | 72 | ||
... | @@ -85,9 +74,9 @@ public class AlarmCodecTest { | ... | @@ -85,9 +74,9 @@ public class AlarmCodecTest { |
85 | 74 | ||
86 | @Test | 75 | @Test |
87 | public void verifyMinimalAlarmIsEncoded() throws Exception { | 76 | public void verifyMinimalAlarmIsEncoded() throws Exception { |
88 | - final JsonCodec<Alarm> alarmCodec = context.codec(Alarm.class); | 77 | + JsonCodec<Alarm> alarmCodec = context.codec(Alarm.class); |
89 | 78 | ||
90 | - final Alarm alarm = getDecodedAlarm(alarmCodec, "alarm-minimal.json"); | 79 | + Alarm alarm = getDecodedAlarm(alarmCodec, "alarm-minimal.json"); |
91 | assertCommon(alarm); | 80 | assertCommon(alarm); |
92 | 81 | ||
93 | assertThat(alarm.timeCleared(), nullValue()); | 82 | assertThat(alarm.timeCleared(), nullValue()); |
... | @@ -97,9 +86,9 @@ public class AlarmCodecTest { | ... | @@ -97,9 +86,9 @@ public class AlarmCodecTest { |
97 | 86 | ||
98 | @Test | 87 | @Test |
99 | public void verifyFullyLoadedAlarmIsEncoded() throws Exception { | 88 | public void verifyFullyLoadedAlarmIsEncoded() throws Exception { |
100 | - final JsonCodec<Alarm> alarmCodec = context.codec(Alarm.class); | 89 | + JsonCodec<Alarm> alarmCodec = context.codec(Alarm.class); |
101 | 90 | ||
102 | - final Alarm alarm = getDecodedAlarm(alarmCodec, "alarm-full.json"); | 91 | + Alarm alarm = getDecodedAlarm(alarmCodec, "alarm-full.json"); |
103 | assertCommon(alarm); | 92 | assertCommon(alarm); |
104 | 93 | ||
105 | assertThat(alarm.timeCleared(), is(2222L)); | 94 | assertThat(alarm.timeCleared(), is(2222L)); |
... | @@ -108,7 +97,7 @@ public class AlarmCodecTest { | ... | @@ -108,7 +97,7 @@ public class AlarmCodecTest { |
108 | } | 97 | } |
109 | 98 | ||
110 | private void assertCommon(Alarm alarm) { | 99 | private void assertCommon(Alarm alarm) { |
111 | - assertThat(alarm.id(), is(new AlarmId(10L))); | 100 | + assertThat(alarm.id(), is(AlarmId.alarmId(10L))); |
112 | assertThat(alarm.description(), is("NE is not reachable")); | 101 | assertThat(alarm.description(), is("NE is not reachable")); |
113 | assertThat(alarm.source(), is(AlarmEntityId.NONE)); | 102 | assertThat(alarm.source(), is(AlarmEntityId.NONE)); |
114 | assertThat(alarm.timeRaised(), is(999L)); | 103 | assertThat(alarm.timeRaised(), is(999L)); |
... | @@ -127,14 +116,14 @@ public class AlarmCodecTest { | ... | @@ -127,14 +116,14 @@ public class AlarmCodecTest { |
127 | * @throws IOException if processing the resource fails to decode | 116 | * @throws IOException if processing the resource fails to decode |
128 | */ | 117 | */ |
129 | private Alarm getDecodedAlarm(JsonCodec<Alarm> codec, String resourceName) throws IOException { | 118 | private Alarm getDecodedAlarm(JsonCodec<Alarm> codec, String resourceName) throws IOException { |
130 | - final InputStream jsonStream = AlarmCodecTest.class | 119 | + try (InputStream jsonStream = AlarmCodecTest.class |
131 | - .getResourceAsStream(resourceName); | 120 | + .getResourceAsStream(resourceName)) { |
132 | - final JsonNode json = context.mapper().readTree(jsonStream); | 121 | + JsonNode json = context.mapper().readTree(jsonStream); |
133 | assertThat(json, notNullValue()); | 122 | assertThat(json, notNullValue()); |
134 | - final Alarm result = codec.decode((ObjectNode) json, context); | 123 | + Alarm result = codec.decode((ObjectNode) json, context); |
135 | assertThat(result, notNullValue()); | 124 | assertThat(result, notNullValue()); |
136 | return result; | 125 | return result; |
137 | } | 126 | } |
138 | - | 127 | + } |
139 | 128 | ||
140 | } | 129 | } | ... | ... |
... | @@ -34,48 +34,48 @@ public final class AlarmJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> | ... | @@ -34,48 +34,48 @@ public final class AlarmJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> |
34 | 34 | ||
35 | @Override | 35 | @Override |
36 | public boolean matchesSafely(JsonNode jsonAlarm, Description description) { | 36 | public boolean matchesSafely(JsonNode jsonAlarm, Description description) { |
37 | - final String jsonAlarmId = jsonAlarm.get("id").asText(); | 37 | + String jsonAlarmId = jsonAlarm.get("id").asText(); |
38 | - final String alarmId = Long.toString(alarm.id().fingerprint()); | 38 | + String alarmId = Long.toString(alarm.id().fingerprint()); |
39 | if (!jsonAlarmId.equals(alarmId)) { | 39 | if (!jsonAlarmId.equals(alarmId)) { |
40 | description.appendText("alarm id was " + jsonAlarmId); | 40 | description.appendText("alarm id was " + jsonAlarmId); |
41 | return false; | 41 | return false; |
42 | } | 42 | } |
43 | 43 | ||
44 | - final String jsonDeviceId = jsonAlarm.get("deviceId").asText(); | 44 | + String jsonDeviceId = jsonAlarm.get("deviceId").asText(); |
45 | - final String alarmDeviceId = alarm.deviceId().toString(); | 45 | + String alarmDeviceId = alarm.deviceId().toString(); |
46 | if (!jsonDeviceId.equals(alarmDeviceId)) { | 46 | if (!jsonDeviceId.equals(alarmDeviceId)) { |
47 | description.appendText("DeviceId was " + jsonDeviceId); | 47 | description.appendText("DeviceId was " + jsonDeviceId); |
48 | return false; | 48 | return false; |
49 | } | 49 | } |
50 | 50 | ||
51 | 51 | ||
52 | - final String jsonDescription = jsonAlarm.get("description").asText(); | 52 | + String jsonDescription = jsonAlarm.get("description").asText(); |
53 | - final String alarmDesc = alarm.description(); | 53 | + String alarmDesc = alarm.description(); |
54 | if (!jsonDescription.equals(alarmDesc)) { | 54 | if (!jsonDescription.equals(alarmDesc)) { |
55 | description.appendText("description was " + jsonDescription); | 55 | description.appendText("description was " + jsonDescription); |
56 | return false; | 56 | return false; |
57 | } | 57 | } |
58 | 58 | ||
59 | - final long jsonTimeRaised = jsonAlarm.get("timeRaised").asLong(); | 59 | + long jsonTimeRaised = jsonAlarm.get("timeRaised").asLong(); |
60 | - final long timeRaised = alarm.timeRaised(); | 60 | + long timeRaised = alarm.timeRaised(); |
61 | if (timeRaised != jsonTimeRaised) { | 61 | if (timeRaised != jsonTimeRaised) { |
62 | description.appendText("timeRaised was " + jsonTimeRaised); | 62 | description.appendText("timeRaised was " + jsonTimeRaised); |
63 | return false; | 63 | return false; |
64 | } | 64 | } |
65 | 65 | ||
66 | 66 | ||
67 | - final long jsonTimeUpdated = jsonAlarm.get("timeUpdated").asLong(); | 67 | + long jsonTimeUpdated = jsonAlarm.get("timeUpdated").asLong(); |
68 | - final long timeUpdated = alarm.timeUpdated(); | 68 | + long timeUpdated = alarm.timeUpdated(); |
69 | if (timeUpdated != jsonTimeUpdated) { | 69 | if (timeUpdated != jsonTimeUpdated) { |
70 | description.appendText("timeUpdated was " + jsonTimeUpdated); | 70 | description.appendText("timeUpdated was " + jsonTimeUpdated); |
71 | return false; | 71 | return false; |
72 | } | 72 | } |
73 | 73 | ||
74 | - final JsonNode jsonTimeClearedNode = jsonAlarm.get("timeCleared"); | 74 | + JsonNode jsonTimeClearedNode = jsonAlarm.get("timeCleared"); |
75 | 75 | ||
76 | if (alarm.timeCleared() != null) { | 76 | if (alarm.timeCleared() != null) { |
77 | - final Long jsonTimeCleared = jsonTimeClearedNode.longValue(); | 77 | + Long jsonTimeCleared = jsonTimeClearedNode.longValue(); |
78 | - final Long timeCleared = alarm.timeCleared(); | 78 | + Long timeCleared = alarm.timeCleared(); |
79 | 79 | ||
80 | if (!timeCleared.equals(jsonTimeCleared)) { | 80 | if (!timeCleared.equals(jsonTimeCleared)) { |
81 | description.appendText("Time Cleared was " + jsonTimeCleared); | 81 | description.appendText("Time Cleared was " + jsonTimeCleared); |
... | @@ -89,18 +89,18 @@ public final class AlarmJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> | ... | @@ -89,18 +89,18 @@ public final class AlarmJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> |
89 | } | 89 | } |
90 | } | 90 | } |
91 | 91 | ||
92 | - final String jsonSeverity = jsonAlarm.get("severity").asText(); | 92 | + String jsonSeverity = jsonAlarm.get("severity").asText(); |
93 | - final String severity = alarm.severity().toString(); | 93 | + String severity = alarm.severity().toString(); |
94 | if (!severity.equals(jsonSeverity)) { | 94 | if (!severity.equals(jsonSeverity)) { |
95 | description.appendText("severity was " + jsonSeverity); | 95 | description.appendText("severity was " + jsonSeverity); |
96 | return false; | 96 | return false; |
97 | } | 97 | } |
98 | 98 | ||
99 | - final JsonNode jsonAlarmNode = jsonAlarm.get("source"); | 99 | + JsonNode jsonAlarmNode = jsonAlarm.get("source"); |
100 | 100 | ||
101 | if (alarm.source() != null) { | 101 | if (alarm.source() != null) { |
102 | - final String jsonSource = jsonAlarmNode.textValue(); | 102 | + String jsonSource = jsonAlarmNode.textValue(); |
103 | - final String source = alarm.source().toString(); | 103 | + String source = alarm.source().toString(); |
104 | 104 | ||
105 | if (!source.equals(jsonSource)) { | 105 | if (!source.equals(jsonSource)) { |
106 | description.appendText("source was " + jsonSource); | 106 | description.appendText("source was " + jsonSource); | ... | ... |
... | @@ -38,10 +38,10 @@ public class AlarmsWebResourceTest extends ResourceTest { | ... | @@ -38,10 +38,10 @@ public class AlarmsWebResourceTest extends ResourceTest { |
38 | @Before | 38 | @Before |
39 | public void setUp() { | 39 | public void setUp() { |
40 | 40 | ||
41 | - final CodecManager codecService = new CodecManager(); | 41 | + CodecManager codecService = new CodecManager(); |
42 | codecService.activate(); | 42 | codecService.activate(); |
43 | 43 | ||
44 | - final ServiceDirectory testDirectory = new TestServiceDirectory() | 44 | + ServiceDirectory testDirectory = new TestServiceDirectory() |
45 | // Currently no alarms-service implemented | 45 | // Currently no alarms-service implemented |
46 | // .add(AlarmsService.class, alarmsService) | 46 | // .add(AlarmsService.class, alarmsService) |
47 | .add(CodecService.class, codecService); | 47 | .add(CodecService.class, codecService); |
... | @@ -51,8 +51,8 @@ public class AlarmsWebResourceTest extends ResourceTest { | ... | @@ -51,8 +51,8 @@ public class AlarmsWebResourceTest extends ResourceTest { |
51 | @Test | 51 | @Test |
52 | @Ignore | 52 | @Ignore |
53 | public void getAllAlarms() { | 53 | public void getAllAlarms() { |
54 | - final WebResource rs = resource(); | 54 | + WebResource rs = resource(); |
55 | - final String response = rs.path("/alarms").get(String.class); | 55 | + String response = rs.path("/alarms").get(String.class); |
56 | // Ensure hard-coded alarms returned okay | 56 | // Ensure hard-coded alarms returned okay |
57 | assertThat(response, containsString("\"NE is not reachable\",")); | 57 | assertThat(response, containsString("\"NE is not reachable\",")); |
58 | assertThat(response, containsString("\"Equipment Missing\",")); | 58 | assertThat(response, containsString("\"Equipment Missing\",")); |
... | @@ -61,8 +61,8 @@ public class AlarmsWebResourceTest extends ResourceTest { | ... | @@ -61,8 +61,8 @@ public class AlarmsWebResourceTest extends ResourceTest { |
61 | @Test | 61 | @Test |
62 | @Ignore | 62 | @Ignore |
63 | public void getAlarm() { | 63 | public void getAlarm() { |
64 | - final WebResource rs = resource(); | 64 | + WebResource rs = resource(); |
65 | - final String response = rs.path("/alarms/1").get(String.class); | 65 | + String response = rs.path("/alarms/1").get(String.class); |
66 | // Ensure hard-coded alarms returned okay | 66 | // Ensure hard-coded alarms returned okay |
67 | assertThat(response, containsString("\"NE is not reachable\",")); | 67 | assertThat(response, containsString("\"NE is not reachable\",")); |
68 | assertThat(response, not(containsString("\"Equipment Missing\","))); | 68 | assertThat(response, not(containsString("\"Equipment Missing\","))); | ... | ... |
1 | <?xml version="1.0" encoding="UTF-8"?> | 1 | <?xml version="1.0" encoding="UTF-8"?> |
2 | <!-- | 2 | <!-- |
3 | - ~ Copyright 2014 Open Networking Laboratory | 3 | +~ Copyright 2015 Open Networking Laboratory |
4 | - ~ | 4 | +~ |
5 | - ~ Licensed under the Apache License, Version 2.0 (the "License"); | 5 | +~ Licensed under the Apache License, Version 2.0 (the "License"); |
6 | - ~ you may not use this file except in compliance with the License. | 6 | +~ you may not use this file except in compliance with the License. |
7 | - ~ You may obtain a copy of the License at | 7 | +~ You may obtain a copy of the License at |
8 | - ~ | 8 | +~ |
9 | - ~ http://www.apache.org/licenses/LICENSE-2.0 | 9 | +~ http://www.apache.org/licenses/LICENSE-2.0 |
10 | - ~ | 10 | +~ |
11 | - ~ Unless required by applicable law or agreed to in writing, software | 11 | +~ Unless required by applicable law or agreed to in writing, software |
12 | - ~ distributed under the License is distributed on an "AS IS" BASIS, | 12 | +~ distributed under the License is distributed on an "AS IS" BASIS, |
13 | - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 13 | +~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
14 | - ~ See the License for the specific language governing permissions and | 14 | +~ See the License for the specific language governing permissions and |
15 | - ~ limitations under the License. | 15 | +~ limitations under the License. |
16 | - --> | 16 | +--> |
17 | <project xmlns="http://maven.apache.org/POM/4.0.0" | 17 | <project xmlns="http://maven.apache.org/POM/4.0.0" |
18 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | 18 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
19 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | 19 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> |
... | @@ -34,6 +34,8 @@ | ... | @@ -34,6 +34,8 @@ |
34 | <modules> | 34 | <modules> |
35 | <module>fmmgr</module> | 35 | <module>fmmgr</module> |
36 | <module>fmweb</module> | 36 | <module>fmweb</module> |
37 | + <module>fmgui</module> | ||
38 | + <module>fmcli</module> | ||
37 | <module>app</module> | 39 | <module>app</module> |
38 | </modules> | 40 | </modules> |
39 | <dependencies> | 41 | <dependencies> | ... | ... |
... | @@ -15,51 +15,64 @@ | ... | @@ -15,51 +15,64 @@ |
15 | */ | 15 | */ |
16 | package org.onosproject.incubator.net.faultmanagement.alarm; | 16 | package org.onosproject.incubator.net.faultmanagement.alarm; |
17 | 17 | ||
18 | +import java.util.Set; | ||
18 | import org.onosproject.event.AbstractEvent; | 19 | import org.onosproject.event.AbstractEvent; |
20 | +import org.onosproject.net.DeviceId; | ||
19 | 21 | ||
20 | /** | 22 | /** |
21 | - * Entity that represents Alarm events. | 23 | + * Entity that represents Alarm events. Note: although the event will itself have a time, consumers may be more |
24 | + * interested in the times embedded in the alarms themselves. | ||
25 | + * | ||
22 | */ | 26 | */ |
23 | -public class AlarmEvent extends AbstractEvent<AlarmEvent.Type, Alarm> { | 27 | +public class AlarmEvent extends AbstractEvent<AlarmEvent.Type, Set<Alarm>> { |
24 | 28 | ||
29 | + private final DeviceId deviceRefreshed; | ||
25 | 30 | ||
26 | /** | 31 | /** |
27 | - * Creates an event of a given type and for the specified alarm and the | 32 | + * Creates an event due to one or more notification. |
28 | - * current time. | ||
29 | * | 33 | * |
30 | - * @param type topology event type | 34 | + * @param alarms the set one or more of alarms. |
31 | - * @param alarm the alarm | ||
32 | */ | 35 | */ |
33 | - public AlarmEvent(Type type, Alarm alarm) { | 36 | + public AlarmEvent(Set<Alarm> alarms) { |
34 | - super(type, alarm); | 37 | + super(Type.NOTIFICATION, alarms); |
38 | + deviceRefreshed = null; | ||
35 | } | 39 | } |
36 | 40 | ||
37 | /** | 41 | /** |
38 | - * Creates an event of a given type and for the specified alarm and time. | 42 | + * Creates an event due to alarm discovery for a device. |
39 | * | 43 | * |
40 | - * @param type link event type | 44 | + * @param alarms the set of alarms. |
41 | - * @param alarm the alarm | 45 | + * @param deviceRefreshed if of refreshed device, populated after a de-discovery |
42 | - * @param time occurrence time | ||
43 | */ | 46 | */ |
44 | - public AlarmEvent(Type type, Alarm alarm, | 47 | + public AlarmEvent(Set<Alarm> alarms, |
45 | - long time) { | 48 | + DeviceId deviceRefreshed) { |
46 | - super(type, alarm, time); | 49 | + super(Type.DEVICE_DISCOVERY, alarms); |
50 | + this.deviceRefreshed = deviceRefreshed; | ||
51 | + | ||
47 | } | 52 | } |
48 | 53 | ||
49 | /** | 54 | /** |
50 | - * Type of alarm events. | 55 | + * Gets which device was refreshed. |
56 | + * | ||
57 | + * @return the refreshed device, or null if event related to a asynchronous notification(s) | ||
51 | */ | 58 | */ |
52 | - public enum Type { | 59 | + public DeviceId getDeviceRefreshed() { |
60 | + return deviceRefreshed; | ||
61 | + } | ||
62 | + | ||
53 | /** | 63 | /** |
54 | - * A Raised Alarm. | 64 | + * Type of alarm event. |
55 | */ | 65 | */ |
56 | - RAISE, | 66 | + public enum Type { |
57 | 67 | ||
58 | /** | 68 | /** |
59 | - * A Cleared Alarm. | 69 | + * Individual alarm(s) updated. |
60 | */ | 70 | */ |
61 | - CLEAR | 71 | + NOTIFICATION, |
72 | + /** | ||
73 | + * Alarm set updated for a given device. | ||
74 | + */ | ||
75 | + DEVICE_DISCOVERY, | ||
62 | } | 76 | } |
63 | 77 | ||
64 | - | ||
65 | } | 78 | } | ... | ... |
... | @@ -16,11 +16,9 @@ | ... | @@ -16,11 +16,9 @@ |
16 | package org.onosproject.incubator.net.faultmanagement.alarm; | 16 | package org.onosproject.incubator.net.faultmanagement.alarm; |
17 | 17 | ||
18 | import com.google.common.annotations.Beta; | 18 | import com.google.common.annotations.Beta; |
19 | - | ||
20 | import java.util.Objects; | 19 | import java.util.Objects; |
21 | - | ||
22 | import static com.google.common.base.MoreObjects.toStringHelper; | 20 | import static com.google.common.base.MoreObjects.toStringHelper; |
23 | - | 21 | +import static com.google.common.base.Preconditions.checkArgument; |
24 | /** | 22 | /** |
25 | * Alarm identifier suitable as an external key. | 23 | * Alarm identifier suitable as an external key. |
26 | * <p> | 24 | * <p> |
... | @@ -30,23 +28,29 @@ import static com.google.common.base.MoreObjects.toStringHelper; | ... | @@ -30,23 +28,29 @@ import static com.google.common.base.MoreObjects.toStringHelper; |
30 | public final class AlarmId { | 28 | public final class AlarmId { |
31 | 29 | ||
32 | private final long id; | 30 | private final long id; |
31 | + public static final AlarmId NONE = new AlarmId(); | ||
33 | 32 | ||
34 | /** | 33 | /** |
35 | * Instantiates a new Alarm id. | 34 | * Instantiates a new Alarm id. |
36 | * | 35 | * |
37 | * @param id the id | 36 | * @param id the id |
38 | */ | 37 | */ |
39 | - public AlarmId(final long id) { | 38 | + private AlarmId(long id) { |
39 | + checkArgument(id != 0L, "id must be non-zero"); | ||
40 | this.id = id; | 40 | this.id = id; |
41 | } | 41 | } |
42 | 42 | ||
43 | + private AlarmId() { | ||
44 | + this.id = 0L; | ||
45 | + } | ||
46 | + | ||
43 | /** | 47 | /** |
44 | * Creates an alarm identifier from the specified long representation. | 48 | * Creates an alarm identifier from the specified long representation. |
45 | * | 49 | * |
46 | * @param value long value | 50 | * @param value long value |
47 | * @return intent identifier | 51 | * @return intent identifier |
48 | */ | 52 | */ |
49 | - public static AlarmId valueOf(final long value) { | 53 | + public static AlarmId alarmId(long value) { |
50 | return new AlarmId(value); | 54 | return new AlarmId(value); |
51 | } | 55 | } |
52 | 56 | ||
... | @@ -65,12 +69,12 @@ public final class AlarmId { | ... | @@ -65,12 +69,12 @@ public final class AlarmId { |
65 | } | 69 | } |
66 | 70 | ||
67 | @Override | 71 | @Override |
68 | - public boolean equals(final Object obj) { | 72 | + public boolean equals(Object obj) { |
69 | if (this == obj) { | 73 | if (this == obj) { |
70 | return true; | 74 | return true; |
71 | } | 75 | } |
72 | if (obj instanceof AlarmId) { | 76 | if (obj instanceof AlarmId) { |
73 | - final AlarmId other = (AlarmId) obj; | 77 | + AlarmId other = (AlarmId) obj; |
74 | return Objects.equals(this.id, other.id); | 78 | return Objects.equals(this.id, other.id); |
75 | } | 79 | } |
76 | return false; | 80 | return false; | ... | ... |
... | @@ -24,14 +24,25 @@ import org.onosproject.net.provider.Provider; | ... | @@ -24,14 +24,25 @@ import org.onosproject.net.provider.Provider; |
24 | public interface AlarmProvider extends Provider { | 24 | public interface AlarmProvider extends Provider { |
25 | 25 | ||
26 | /** | 26 | /** |
27 | - * Triggers an asynchronous discovery of the alarms on the specified device, | 27 | + * Triggers an asynchronous discovery of the alarms on the specified device, intended to refresh internal alarm |
28 | - * intended to refresh internal alarm model for the device. An indirect | 28 | + * model for the device. An indirect result of this should be a event sent later with discovery result ie a set of |
29 | - * result of this should be invocation of | 29 | + * alarms. |
30 | - * {@link org.onosproject.incubator.net.faultmanagement.alarm.AlarmProviderService#updateAlarmList} )} | ||
31 | - * at some later point in time. | ||
32 | * | 30 | * |
33 | * @param deviceId ID of device to be probed | 31 | * @param deviceId ID of device to be probed |
34 | */ | 32 | */ |
35 | void triggerProbe(DeviceId deviceId); | 33 | void triggerProbe(DeviceId deviceId); |
36 | 34 | ||
35 | + /** | ||
36 | + * Register a listener for alarms. | ||
37 | + * | ||
38 | + * @param listener the listener to notify | ||
39 | + */ | ||
40 | + void addAlarmListener(AlarmListener listener); | ||
41 | + | ||
42 | + /** | ||
43 | + * Unregister a listener. | ||
44 | + * | ||
45 | + * @param listener the listener to unregister | ||
46 | + */ | ||
47 | + void removeAlarmListener(AlarmListener listener); | ||
37 | } | 48 | } | ... | ... |
... | @@ -16,6 +16,7 @@ | ... | @@ -16,6 +16,7 @@ |
16 | package org.onosproject.incubator.net.faultmanagement.alarm; | 16 | package org.onosproject.incubator.net.faultmanagement.alarm; |
17 | 17 | ||
18 | 18 | ||
19 | +import com.google.common.annotations.Beta; | ||
19 | import org.onosproject.net.DeviceId; | 20 | import org.onosproject.net.DeviceId; |
20 | import org.onosproject.net.provider.ProviderService; | 21 | import org.onosproject.net.provider.ProviderService; |
21 | 22 | ||
... | @@ -24,6 +25,7 @@ import java.util.Collection; | ... | @@ -24,6 +25,7 @@ import java.util.Collection; |
24 | /** | 25 | /** |
25 | * The interface Alarm provider service. | 26 | * The interface Alarm provider service. |
26 | */ | 27 | */ |
28 | +@Beta | ||
27 | public interface AlarmProviderService extends ProviderService<AlarmProvider> { | 29 | public interface AlarmProviderService extends ProviderService<AlarmProvider> { |
28 | 30 | ||
29 | /** | 31 | /** | ... | ... |
... | @@ -16,60 +16,65 @@ | ... | @@ -16,60 +16,65 @@ |
16 | package org.onosproject.incubator.net.faultmanagement.alarm; | 16 | package org.onosproject.incubator.net.faultmanagement.alarm; |
17 | 17 | ||
18 | import com.google.common.annotations.Beta; | 18 | import com.google.common.annotations.Beta; |
19 | -//import org.onosproject.event.ListenerService; | 19 | +import java.util.Map; |
20 | 20 | ||
21 | import java.util.Set; | 21 | import java.util.Set; |
22 | import org.onosproject.net.ConnectPoint; | 22 | import org.onosproject.net.ConnectPoint; |
23 | import org.onosproject.net.DeviceId; | 23 | import org.onosproject.net.DeviceId; |
24 | 24 | ||
25 | /** | 25 | /** |
26 | - * Service for interacting with the alarm handling of devices. Unless stated | 26 | + * Service for interacting with the alarm handling of devices. Unless stated otherwise, getter methods |
27 | - * otherwise method return active AND recently-cleared alarms. | 27 | + * return active AND recently-cleared alarms. |
28 | */ | 28 | */ |
29 | @Beta | 29 | @Beta |
30 | public interface AlarmService { | 30 | public interface AlarmService { |
31 | -// extends ListenerService<AlarmEvent, AlarmListener> { | ||
32 | 31 | ||
33 | /** | 32 | /** |
34 | - * Alarm should be updated in ONOS's internal representation; only | 33 | + * Update book-keeping (ie administrative) fields for the alarm matching the specified identifier. |
35 | - * administration/book-keeping fields may be updated. Attempting to update | 34 | + * |
36 | - * fields which are mapped directly from device is prohibited. | 35 | + * @param id alarm identifier |
36 | + * @param isAcknowledged new acknowledged state | ||
37 | + * @param assignedUser new assigned user, null clear | ||
38 | + * @return updated alarm (including any recent device-derived changes) | ||
37 | * | 39 | * |
38 | - * @param replacement alarm with updated book-keeping fields | ||
39 | - * @return updated alarm (including any recent device derived changes) | ||
40 | - | ||
41 | - * @throws java.lang.IllegalStateException if attempt to update not allowed | ||
42 | - * fields. | ||
43 | */ | 40 | */ |
44 | - Alarm update(Alarm replacement); | 41 | + Alarm updateBookkeepingFields(AlarmId id, boolean isAcknowledged, String assignedUser); |
45 | 42 | ||
46 | /** | 43 | /** |
47 | - * Returns the number of ACTIVE alarms on a device. | 44 | + * Returns summary of alarms on a given device. |
48 | * | 45 | * |
49 | * @param deviceId the device | 46 | * @param deviceId the device |
50 | - * @return number of alarms | 47 | + * @return map of severity (if applicable) vs alarm counts; empty map if either the device has no alarms or |
48 | + * identified device is not managed. | ||
51 | */ | 49 | */ |
52 | - int getActiveAlarmCount(DeviceId deviceId); | 50 | + Map<Alarm.SeverityLevel, Long> getAlarmCounts(DeviceId deviceId); |
51 | + | ||
52 | + /** | ||
53 | + * Returns summary of alarms on all devices. | ||
54 | + * | ||
55 | + * @return map of severity (if applicable) vs alarm counts; empty map if no alarms. | ||
56 | + */ | ||
57 | + Map<Alarm.SeverityLevel, Long> getAlarmCounts(); | ||
53 | 58 | ||
54 | /** | 59 | /** |
55 | * Returns the alarm with the specified identifier. | 60 | * Returns the alarm with the specified identifier. |
56 | * | 61 | * |
57 | * @param alarmId alarm identifier | 62 | * @param alarmId alarm identifier |
58 | - * @return alarm or null if one with the given identifier is not known | 63 | + * @return alarm matching id; null if no alarm matches the identifier. |
59 | */ | 64 | */ |
60 | Alarm getAlarm(AlarmId alarmId); | 65 | Alarm getAlarm(AlarmId alarmId); |
61 | 66 | ||
62 | /** | 67 | /** |
63 | * Returns all of the alarms. | 68 | * Returns all of the alarms. |
64 | * | 69 | * |
65 | - * @return the alarms | 70 | + * @return set of alarms; empty set if no alarms |
66 | */ | 71 | */ |
67 | Set<Alarm> getAlarms(); | 72 | Set<Alarm> getAlarms(); |
68 | 73 | ||
69 | /** | 74 | /** |
70 | * Returns all of the ACTIVE alarms. Recently cleared alarms excluded. | 75 | * Returns all of the ACTIVE alarms. Recently cleared alarms excluded. |
71 | * | 76 | * |
72 | - * @return the alarms | 77 | + * @return set of alarms; empty set if no alarms |
73 | */ | 78 | */ |
74 | Set<Alarm> getActiveAlarms(); | 79 | Set<Alarm> getActiveAlarms(); |
75 | 80 | ||
... | @@ -77,16 +82,15 @@ public interface AlarmService { | ... | @@ -77,16 +82,15 @@ public interface AlarmService { |
77 | * Returns the alarms with the specified severity. | 82 | * Returns the alarms with the specified severity. |
78 | * | 83 | * |
79 | * @param severity the alarm severity | 84 | * @param severity the alarm severity |
80 | - * @return the active alarms with a particular severity | 85 | + * @return set of alarms with a particular severity; empty set if no alarms |
81 | */ | 86 | */ |
82 | Set<Alarm> getAlarms(Alarm.SeverityLevel severity); | 87 | Set<Alarm> getAlarms(Alarm.SeverityLevel severity); |
83 | 88 | ||
84 | /** | 89 | /** |
85 | - * Returns the alarm for a given device, regardless of source within that | 90 | + * Returns the alarm matching a given device, regardless of source within that device. |
86 | - * device. | ||
87 | * | 91 | * |
88 | - * @param deviceId the device | 92 | + * @param deviceId the device to use when searching alarms. |
89 | - * @return the alarms | 93 | + * @return set of alarms; empty set if no alarms |
90 | */ | 94 | */ |
91 | Set<Alarm> getAlarms(DeviceId deviceId); | 95 | Set<Alarm> getAlarms(DeviceId deviceId); |
92 | 96 | ||
... | @@ -95,7 +99,7 @@ public interface AlarmService { | ... | @@ -95,7 +99,7 @@ public interface AlarmService { |
95 | * | 99 | * |
96 | * @param deviceId the device | 100 | * @param deviceId the device |
97 | * @param source the source within the device | 101 | * @param source the source within the device |
98 | - * @return the alarms | 102 | + * @return set of alarms; empty set if no alarms |
99 | */ | 103 | */ |
100 | Set<Alarm> getAlarms(DeviceId deviceId, AlarmEntityId source); | 104 | Set<Alarm> getAlarms(DeviceId deviceId, AlarmEntityId source); |
101 | 105 | ||
... | @@ -104,7 +108,7 @@ public interface AlarmService { | ... | @@ -104,7 +108,7 @@ public interface AlarmService { |
104 | * | 108 | * |
105 | * @param src one end of the link | 109 | * @param src one end of the link |
106 | * @param dst one end of the link | 110 | * @param dst one end of the link |
107 | - * @return the alarms | 111 | + * @return set of alarms; empty set if no alarms |
108 | */ | 112 | */ |
109 | Set<Alarm> getAlarmsForLink(ConnectPoint src, ConnectPoint dst); | 113 | Set<Alarm> getAlarmsForLink(ConnectPoint src, ConnectPoint dst); |
110 | 114 | ||
... | @@ -113,9 +117,9 @@ public interface AlarmService { | ... | @@ -113,9 +117,9 @@ public interface AlarmService { |
113 | * | 117 | * |
114 | * @param deviceId the device | 118 | * @param deviceId the device |
115 | * @param flowId the flow | 119 | * @param flowId the flow |
116 | - * @return the alarms | 120 | + * @return set of alarms; empty set if no alarms |
117 | */ | 121 | */ |
118 | Set<Alarm> getAlarmsForFlow(DeviceId deviceId, long flowId); | 122 | Set<Alarm> getAlarmsForFlow(DeviceId deviceId, long flowId); |
119 | 123 | ||
120 | -// Support retrieving alarms affecting other ONOS entity types may be added in future release | 124 | + // TODO Support retrieving alarms affecting other entity types may be added in future release |
121 | } | 125 | } | ... | ... |
... | @@ -145,14 +145,16 @@ public final class DefaultAlarm implements Alarm { | ... | @@ -145,14 +145,16 @@ public final class DefaultAlarm implements Alarm { |
145 | 145 | ||
146 | @Override | 146 | @Override |
147 | public int hashCode() { | 147 | public int hashCode() { |
148 | - return Objects.hash(id, deviceId, description, | 148 | + // id or timeRaised or timeUpdated may differ |
149 | - source, timeRaised, timeUpdated, timeCleared, severity, | 149 | + return Objects.hash(deviceId, description, |
150 | + source, timeCleared, severity, | ||
150 | isServiceAffecting, isAcknowledged, | 151 | isServiceAffecting, isAcknowledged, |
151 | isManuallyClearable, assignedUser); | 152 | isManuallyClearable, assignedUser); |
152 | } | 153 | } |
153 | 154 | ||
154 | @Override | 155 | @Override |
155 | public boolean equals(final Object obj) { | 156 | public boolean equals(final Object obj) { |
157 | + // Make sure equals() is tune with hashCode() so works ok in a hashSet ! | ||
156 | if (obj == null) { | 158 | if (obj == null) { |
157 | return false; | 159 | return false; |
158 | } | 160 | } |
... | @@ -160,9 +162,8 @@ public final class DefaultAlarm implements Alarm { | ... | @@ -160,9 +162,8 @@ public final class DefaultAlarm implements Alarm { |
160 | return false; | 162 | return false; |
161 | } | 163 | } |
162 | final DefaultAlarm other = (DefaultAlarm) obj; | 164 | final DefaultAlarm other = (DefaultAlarm) obj; |
163 | - if (!Objects.equals(this.id, other.id)) { | 165 | + |
164 | - return false; | 166 | + // id or timeRaised or timeUpdated may differ |
165 | - } | ||
166 | if (!Objects.equals(this.deviceId, other.deviceId)) { | 167 | if (!Objects.equals(this.deviceId, other.deviceId)) { |
167 | return false; | 168 | return false; |
168 | } | 169 | } |
... | @@ -172,12 +173,7 @@ public final class DefaultAlarm implements Alarm { | ... | @@ -172,12 +173,7 @@ public final class DefaultAlarm implements Alarm { |
172 | if (!Objects.equals(this.source, other.source)) { | 173 | if (!Objects.equals(this.source, other.source)) { |
173 | return false; | 174 | return false; |
174 | } | 175 | } |
175 | - if (this.timeRaised != other.timeRaised) { | 176 | + |
176 | - return false; | ||
177 | - } | ||
178 | - if (this.timeUpdated != other.timeUpdated) { | ||
179 | - return false; | ||
180 | - } | ||
181 | if (!Objects.equals(this.timeCleared, other.timeCleared)) { | 177 | if (!Objects.equals(this.timeCleared, other.timeCleared)) { |
182 | return false; | 178 | return false; |
183 | } | 179 | } |
... | @@ -219,11 +215,11 @@ public final class DefaultAlarm implements Alarm { | ... | @@ -219,11 +215,11 @@ public final class DefaultAlarm implements Alarm { |
219 | 215 | ||
220 | public static class Builder { | 216 | public static class Builder { |
221 | 217 | ||
222 | - // Manadatory fields .. | 218 | + // Manadatory fields when constructing alarm ... |
223 | - private final AlarmId id; | 219 | + private AlarmId id; |
224 | private final DeviceId deviceId; | 220 | private final DeviceId deviceId; |
225 | private final String description; | 221 | private final String description; |
226 | - private final SeverityLevel severity; | 222 | + private SeverityLevel severity; |
227 | private final long timeRaised; | 223 | private final long timeRaised; |
228 | 224 | ||
229 | // Optional fields .. | 225 | // Optional fields .. |
... | @@ -236,8 +232,8 @@ public final class DefaultAlarm implements Alarm { | ... | @@ -236,8 +232,8 @@ public final class DefaultAlarm implements Alarm { |
236 | private String assignedUser = null; | 232 | private String assignedUser = null; |
237 | 233 | ||
238 | public Builder(final Alarm alarm) { | 234 | public Builder(final Alarm alarm) { |
239 | - this(alarm.id(), alarm.deviceId(), alarm.description(), alarm.severity(), alarm.timeRaised()); | 235 | + this(alarm.deviceId(), alarm.description(), alarm.severity(), alarm.timeRaised()); |
240 | - this.source = AlarmEntityId.NONE; | 236 | + this.source = alarm.source(); |
241 | this.timeUpdated = alarm.timeUpdated(); | 237 | this.timeUpdated = alarm.timeUpdated(); |
242 | this.timeCleared = alarm.timeCleared(); | 238 | this.timeCleared = alarm.timeCleared(); |
243 | this.isServiceAffecting = alarm.serviceAffecting(); | 239 | this.isServiceAffecting = alarm.serviceAffecting(); |
... | @@ -247,10 +243,10 @@ public final class DefaultAlarm implements Alarm { | ... | @@ -247,10 +243,10 @@ public final class DefaultAlarm implements Alarm { |
247 | 243 | ||
248 | } | 244 | } |
249 | 245 | ||
250 | - public Builder(final AlarmId id, final DeviceId deviceId, | 246 | + public Builder(final DeviceId deviceId, |
251 | final String description, final SeverityLevel severity, final long timeRaised) { | 247 | final String description, final SeverityLevel severity, final long timeRaised) { |
252 | super(); | 248 | super(); |
253 | - this.id = id; | 249 | + this.id = AlarmId.NONE; |
254 | this.deviceId = deviceId; | 250 | this.deviceId = deviceId; |
255 | this.description = description; | 251 | this.description = description; |
256 | this.severity = severity; | 252 | this.severity = severity; |
... | @@ -274,6 +270,17 @@ public final class DefaultAlarm implements Alarm { | ... | @@ -274,6 +270,17 @@ public final class DefaultAlarm implements Alarm { |
274 | return this; | 270 | return this; |
275 | } | 271 | } |
276 | 272 | ||
273 | + public Builder withId(final AlarmId id) { | ||
274 | + this.id = id; | ||
275 | + return this; | ||
276 | + } | ||
277 | + | ||
278 | + public Builder clear() { | ||
279 | + this.severity = SeverityLevel.CLEARED; | ||
280 | + final long now = System.currentTimeMillis(); | ||
281 | + return withTimeCleared(now).withTimeUpdated(now); | ||
282 | + } | ||
283 | + | ||
277 | public Builder withServiceAffecting(final boolean isServiceAffecting) { | 284 | public Builder withServiceAffecting(final boolean isServiceAffecting) { |
278 | this.isServiceAffecting = isServiceAffecting; | 285 | this.isServiceAffecting = isServiceAffecting; |
279 | return this; | 286 | return this; | ... | ... |
... | @@ -16,19 +16,21 @@ | ... | @@ -16,19 +16,21 @@ |
16 | package org.onosproject.incubator.net.faultmanagement.alarm; | 16 | package org.onosproject.incubator.net.faultmanagement.alarm; |
17 | 17 | ||
18 | import com.google.common.testing.EqualsTester; | 18 | import com.google.common.testing.EqualsTester; |
19 | +import static org.hamcrest.Matchers.containsString; | ||
19 | import org.junit.Test; | 20 | import org.junit.Test; |
20 | 21 | ||
21 | import static org.hamcrest.Matchers.is; | 22 | import static org.hamcrest.Matchers.is; |
22 | import static org.hamcrest.Matchers.not; | 23 | import static org.hamcrest.Matchers.not; |
23 | import static org.junit.Assert.assertEquals; | 24 | import static org.junit.Assert.assertEquals; |
24 | import static org.junit.Assert.assertThat; | 25 | import static org.junit.Assert.assertThat; |
26 | +import static org.junit.Assert.fail; | ||
25 | import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable; | 27 | import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable; |
26 | 28 | ||
27 | /** | 29 | /** |
28 | - * This class tests the immutability, equality, and non-equality of | 30 | + * This class tests the immutability, equality, and non-equality of {@link AlarmId}. |
29 | - * {@link AlarmId}. | ||
30 | */ | 31 | */ |
31 | public class AlarmIdTest { | 32 | public class AlarmIdTest { |
33 | + | ||
32 | private static final long ID_A = 1L; | 34 | private static final long ID_A = 1L; |
33 | private static final long ID_B = 2L; | 35 | private static final long ID_B = 2L; |
34 | private static final long ID_Z = 987654321L; | 36 | private static final long ID_Z = 987654321L; |
... | @@ -46,28 +48,27 @@ public class AlarmIdTest { | ... | @@ -46,28 +48,27 @@ public class AlarmIdTest { |
46 | */ | 48 | */ |
47 | @Test | 49 | @Test |
48 | public void testEquality() { | 50 | public void testEquality() { |
49 | - final AlarmId id1 = new AlarmId(ID_A); | 51 | + final AlarmId id1 = AlarmId.alarmId(ID_A); |
50 | - final AlarmId id2 = new AlarmId(ID_A); | 52 | + final AlarmId id2 = AlarmId.alarmId(ID_A); |
51 | 53 | ||
52 | assertThat(id1, is(id2)); | 54 | assertThat(id1, is(id2)); |
53 | } | 55 | } |
54 | 56 | ||
55 | - | ||
56 | /** | 57 | /** |
57 | * Tests non-equality of {@link AlarmId}. | 58 | * Tests non-equality of {@link AlarmId}. |
58 | */ | 59 | */ |
59 | @Test | 60 | @Test |
60 | public void testNonEquality() { | 61 | public void testNonEquality() { |
61 | - final AlarmId id1 = new AlarmId(ID_A); | 62 | + final AlarmId id1 = AlarmId.alarmId(ID_A); |
62 | - final AlarmId id2 = new AlarmId(ID_B); | 63 | + final AlarmId id2 = AlarmId.alarmId(ID_B); |
63 | 64 | ||
64 | assertThat(id1, is(not(id2))); | 65 | assertThat(id1, is(not(id2))); |
65 | } | 66 | } |
66 | 67 | ||
67 | @Test | 68 | @Test |
68 | public void valueOf() { | 69 | public void valueOf() { |
69 | - final AlarmId id = new AlarmId(0xdeadbeefL); | 70 | + final AlarmId id = AlarmId.alarmId(0xdeadbeefL); |
70 | - assertEquals("incorrect valueOf", id, AlarmId.valueOf(0xdeadbeefL)); | 71 | + assertEquals("incorrect valueOf", id, AlarmId.alarmId(0xdeadbeefL)); |
71 | } | 72 | } |
72 | 73 | ||
73 | /** | 74 | /** |
... | @@ -75,9 +76,9 @@ public class AlarmIdTest { | ... | @@ -75,9 +76,9 @@ public class AlarmIdTest { |
75 | */ | 76 | */ |
76 | @Test | 77 | @Test |
77 | public void testEquals() { | 78 | public void testEquals() { |
78 | - final AlarmId id1 = new AlarmId(11111L); | 79 | + final AlarmId id1 = AlarmId.alarmId(11111L); |
79 | - final AlarmId sameAsId1 = new AlarmId(11111L); | 80 | + final AlarmId sameAsId1 = AlarmId.alarmId(11111L); |
80 | - final AlarmId id2 = new AlarmId(22222L); | 81 | + final AlarmId id2 = AlarmId.alarmId(22222L); |
81 | 82 | ||
82 | new EqualsTester() | 83 | new EqualsTester() |
83 | .addEqualityGroup(id1, sameAsId1) | 84 | .addEqualityGroup(id1, sameAsId1) |
... | @@ -90,9 +91,18 @@ public class AlarmIdTest { | ... | @@ -90,9 +91,18 @@ public class AlarmIdTest { |
90 | */ | 91 | */ |
91 | @Test | 92 | @Test |
92 | public void testConstruction() { | 93 | public void testConstruction() { |
93 | - final AlarmId id1 = new AlarmId(ID_Z); | 94 | + final AlarmId id1 = AlarmId.alarmId(ID_Z); |
94 | assertEquals(id1.fingerprint(), ID_Z); | 95 | assertEquals(id1.fingerprint(), ID_Z); |
95 | 96 | ||
96 | // No default constructor so no need to test it ! | 97 | // No default constructor so no need to test it ! |
98 | + assertEquals(0L, AlarmId.NONE.fingerprint()); | ||
99 | + try { | ||
100 | + final AlarmId bad = AlarmId.alarmId(0L); | ||
101 | + fail("0 is a Reserved value but we created " + bad); | ||
102 | + } catch (IllegalArgumentException ex) { | ||
103 | + assertThat(ex.getMessage(), | ||
104 | + containsString("id must be non-zero")); | ||
105 | + } | ||
106 | + | ||
97 | } | 107 | } |
98 | } | 108 | } | ... | ... |
... | @@ -18,6 +18,7 @@ package org.onosproject.incubator.net.faultmanagement.alarm; | ... | @@ -18,6 +18,7 @@ package org.onosproject.incubator.net.faultmanagement.alarm; |
18 | import static org.hamcrest.MatcherAssert.assertThat; | 18 | import static org.hamcrest.MatcherAssert.assertThat; |
19 | import static org.hamcrest.Matchers.is; | 19 | import static org.hamcrest.Matchers.is; |
20 | import static org.hamcrest.Matchers.notNullValue; | 20 | import static org.hamcrest.Matchers.notNullValue; |
21 | +import static org.hamcrest.Matchers.greaterThan; | ||
21 | import org.junit.Test; | 22 | import org.junit.Test; |
22 | import static org.junit.Assert.*; | 23 | import static org.junit.Assert.*; |
23 | import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable; | 24 | import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable; |
... | @@ -35,13 +36,57 @@ public class DefaultAlarmTest { | ... | @@ -35,13 +36,57 @@ public class DefaultAlarmTest { |
35 | */ | 36 | */ |
36 | @Test | 37 | @Test |
37 | public void testConstruction() { | 38 | public void testConstruction() { |
38 | - final String nameValue = "name3"; | 39 | + final DefaultAlarm a = generate(); |
39 | - final DefaultAlarm a = new DefaultAlarm.Builder(AlarmId.valueOf(4), | ||
40 | - DeviceId.NONE, nameValue, Alarm.SeverityLevel.CLEARED, 3).build(); | ||
41 | - | ||
42 | assertThat(a, is(notNullValue())); | 40 | assertThat(a, is(notNullValue())); |
43 | final DefaultAlarm b = new DefaultAlarm.Builder(a).build(); | 41 | final DefaultAlarm b = new DefaultAlarm.Builder(a).build(); |
44 | - | ||
45 | assertEquals(a, b); | 42 | assertEquals(a, b); |
46 | } | 43 | } |
44 | + | ||
45 | + @Test | ||
46 | + public void testEquals() { | ||
47 | + final DefaultAlarm a = new DefaultAlarm.Builder( | ||
48 | + DeviceId.NONE, "desc", Alarm.SeverityLevel.MINOR, 3).build(); | ||
49 | + final DefaultAlarm b = new DefaultAlarm.Builder( | ||
50 | + DeviceId.NONE, "desc", Alarm.SeverityLevel.MINOR, a.timeRaised() + 1). | ||
51 | + withId(ALARM_ID).withTimeUpdated(a.timeUpdated() + 1).build(); | ||
52 | + assertEquals("id or timeRaised or timeUpdated may differ", a, b); | ||
53 | + | ||
54 | + assertNotEquals(a, new DefaultAlarm.Builder(a).withAcknowledged(!a.acknowledged()).build()); | ||
55 | + assertNotEquals(a, new DefaultAlarm.Builder(a).withManuallyClearable(!a.manuallyClearable()).build()); | ||
56 | + assertNotEquals(a, new DefaultAlarm.Builder(a).withServiceAffecting(!a.serviceAffecting()).build()); | ||
57 | + assertNotEquals(a, new DefaultAlarm.Builder(a).withAssignedUser("Changed" + a.assignedUser()).build()); | ||
58 | + | ||
59 | + } | ||
60 | + | ||
61 | + @Test | ||
62 | + public void testClear() { | ||
63 | + final DefaultAlarm active = generate(); | ||
64 | + final DefaultAlarm cleared = new DefaultAlarm.Builder(active).clear().build(); | ||
65 | + assertNotEquals(active, cleared); | ||
66 | + assertThat(cleared.timeRaised(), is(active.timeRaised())); | ||
67 | + assertThat(cleared.severity(), is(Alarm.SeverityLevel.CLEARED)); | ||
68 | + assertThat(cleared.timeUpdated(), greaterThan(active.timeUpdated())); | ||
69 | + assertNotNull(cleared.timeCleared()); | ||
70 | + | ||
71 | + } | ||
72 | + | ||
73 | + @Test | ||
74 | + public void testId() { | ||
75 | + final DefaultAlarm a = generate(); | ||
76 | + assertThat(a.id(), is(AlarmId.NONE)); | ||
77 | + final DefaultAlarm b = new DefaultAlarm.Builder(a).withId(ALARM_ID).build(); | ||
78 | + | ||
79 | + assertEquals("id ignored in equals", a, b); | ||
80 | + assertNotEquals(ALARM_ID, a.id()); | ||
81 | + assertEquals(ALARM_ID, b.id()); | ||
82 | + assertEquals(ALARM_ENTITY_ID, b.source()); | ||
83 | + | ||
84 | + } | ||
85 | + private static final AlarmEntityId ALARM_ENTITY_ID = AlarmEntityId.alarmEntityId("port:bar"); | ||
86 | + private static final AlarmId ALARM_ID = AlarmId.alarmId(888L); | ||
87 | + | ||
88 | + private static DefaultAlarm generate() { | ||
89 | + return new DefaultAlarm.Builder( | ||
90 | + DeviceId.NONE, "desc", Alarm.SeverityLevel.MINOR, 3).forSource(ALARM_ENTITY_ID).build(); | ||
91 | + } | ||
47 | } | 92 | } | ... | ... |
1 | <?xml version="1.0" encoding="UTF-8"?> | 1 | <?xml version="1.0" encoding="UTF-8"?> |
2 | <!-- | 2 | <!-- |
3 | - ~ Copyright 2014 Open Networking Laboratory | 3 | +~ Copyright 2015 Open Networking Laboratory |
4 | - ~ | 4 | +~ |
5 | - ~ Licensed under the Apache License, Version 2.0 (the "License"); | 5 | +~ Licensed under the Apache License, Version 2.0 (the "License"); |
6 | - ~ you may not use this file except in compliance with the License. | 6 | +~ you may not use this file except in compliance with the License. |
7 | - ~ You may obtain a copy of the License at | 7 | +~ You may obtain a copy of the License at |
8 | - ~ | 8 | +~ |
9 | - ~ http://www.apache.org/licenses/LICENSE-2.0 | 9 | +~ http://www.apache.org/licenses/LICENSE-2.0 |
10 | - ~ | 10 | +~ |
11 | - ~ Unless required by applicable law or agreed to in writing, software | 11 | +~ Unless required by applicable law or agreed to in writing, software |
12 | - ~ distributed under the License is distributed on an "AS IS" BASIS, | 12 | +~ distributed under the License is distributed on an "AS IS" BASIS, |
13 | - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 13 | +~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
14 | - ~ See the License for the specific language governing permissions and | 14 | +~ See the License for the specific language governing permissions and |
15 | - ~ limitations under the License. | 15 | +~ limitations under the License. |
16 | - --> | 16 | +--> |
17 | <project xmlns="http://maven.apache.org/POM/4.0.0" | 17 | <project xmlns="http://maven.apache.org/POM/4.0.0" |
18 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | 18 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
19 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | 19 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> |
... | @@ -31,4 +31,136 @@ | ... | @@ -31,4 +31,136 @@ |
31 | 31 | ||
32 | <description>ONOS SNMP protocol alarm provider</description> | 32 | <description>ONOS SNMP protocol alarm provider</description> |
33 | 33 | ||
34 | + <dependencies> | ||
35 | + <dependency> | ||
36 | + <groupId>com.btisystems</groupId> | ||
37 | + <artifactId>snmp-core</artifactId> | ||
38 | + <version>1.3-SNAPSHOT</version> | ||
39 | + </dependency> | ||
40 | + | ||
41 | + <dependency> | ||
42 | + <groupId>com.btisystems.mibbler.mibs</groupId> | ||
43 | + <artifactId>bti7000</artifactId> | ||
44 | + <version>1.0-SNAPSHOT</version> | ||
45 | + </dependency> | ||
46 | + | ||
47 | + <dependency> | ||
48 | + <groupId>com.btisystems.mibbler.mibs</groupId> | ||
49 | + <artifactId>net-snmp</artifactId> | ||
50 | + <version>1.0-SNAPSHOT</version> | ||
51 | + </dependency> | ||
52 | + | ||
53 | + <dependency> | ||
54 | + <groupId>org.osgi</groupId> | ||
55 | + <artifactId>org.osgi.compendium</artifactId> | ||
56 | + <version>5.0.0</version> | ||
57 | + <type>jar</type> | ||
58 | + </dependency> | ||
59 | + | ||
60 | + <dependency> | ||
61 | + <groupId>org.onosproject</groupId> | ||
62 | + <artifactId>onos-api</artifactId> | ||
63 | + <version>${project.version}</version> | ||
64 | + </dependency> | ||
65 | + | ||
66 | + | ||
67 | + | ||
68 | + <dependency> | ||
69 | + <groupId>org.onosproject</groupId> | ||
70 | + <artifactId>onlab-junit</artifactId> | ||
71 | + <scope>test</scope> | ||
72 | + </dependency> | ||
73 | + | ||
74 | + <dependency> | ||
75 | + <groupId>org.onosproject</groupId> | ||
76 | + <artifactId>onlab-osgi</artifactId> | ||
77 | + <version>${project.version}</version> | ||
78 | + <classifier>tests</classifier> | ||
79 | + <scope>test</scope> | ||
80 | + </dependency> | ||
81 | + | ||
82 | + <dependency> | ||
83 | + <groupId>org.onosproject</groupId> | ||
84 | + <artifactId>onos-api</artifactId> | ||
85 | + <version>${project.version}</version> | ||
86 | + <classifier>tests</classifier> | ||
87 | + <scope>test</scope> | ||
88 | + </dependency> | ||
89 | + | ||
90 | + <dependency> | ||
91 | + <groupId>junit</groupId> | ||
92 | + <artifactId>junit</artifactId> | ||
93 | + <version>4.11</version> | ||
94 | + <scope>test</scope> | ||
95 | + </dependency> | ||
96 | + <dependency> | ||
97 | + <groupId>org.hamcrest</groupId> | ||
98 | + <artifactId>hamcrest-core</artifactId> | ||
99 | + <version>1.3</version> | ||
100 | + <scope>test</scope> | ||
101 | + </dependency> | ||
102 | + <dependency> | ||
103 | + <groupId>org.hamcrest</groupId> | ||
104 | + <artifactId>hamcrest-library</artifactId> | ||
105 | + <version>1.3</version> | ||
106 | + <scope>test</scope> | ||
107 | + </dependency> | ||
108 | + <dependency> | ||
109 | + <groupId>org.easymock</groupId> | ||
110 | + <artifactId>easymock</artifactId> | ||
111 | + <scope>test</scope> | ||
112 | + </dependency> | ||
113 | + </dependencies> | ||
114 | + | ||
115 | + <build> | ||
116 | + <plugins> | ||
117 | + <plugin> | ||
118 | + <groupId>org.apache.maven.plugins</groupId> | ||
119 | + <artifactId>maven-shade-plugin</artifactId> | ||
120 | + <version>2.3</version> | ||
121 | + <configuration> | ||
122 | + <filters> | ||
123 | + <filter> | ||
124 | + <artifact>com.btisystems:snmp-core</artifact> | ||
125 | + <excludes> | ||
126 | + <exclude>**</exclude> | ||
127 | + </excludes> | ||
128 | + </filter> | ||
129 | + <filter> | ||
130 | + <artifact>com.btisystems.mibbler.mibs:bti7000</artifact> | ||
131 | + <excludes> | ||
132 | + <exclude>**</exclude> | ||
133 | + </excludes> | ||
134 | + </filter> | ||
135 | + <filter> | ||
136 | + <artifact>com.btisystems.mibbler.mibs:net-snmp</artifact> | ||
137 | + <excludes> | ||
138 | + <exclude>**</exclude> | ||
139 | + </excludes> | ||
140 | + </filter> | ||
141 | + </filters> | ||
142 | + </configuration> | ||
143 | + <executions> | ||
144 | + <execution> | ||
145 | + <phase>package</phase> | ||
146 | + <goals> | ||
147 | + <goal>shade</goal> | ||
148 | + </goals> | ||
149 | + </execution> | ||
150 | + </executions> | ||
151 | + </plugin> | ||
152 | + <plugin> | ||
153 | + <groupId>org.apache.felix</groupId> | ||
154 | + <artifactId>maven-scr-plugin</artifactId> | ||
155 | + </plugin> | ||
156 | + <plugin> | ||
157 | + <groupId>org.apache.felix</groupId> | ||
158 | + <artifactId>maven-bundle-plugin</artifactId> | ||
159 | + </plugin> | ||
160 | + <plugin> | ||
161 | + <groupId>org.onosproject</groupId> | ||
162 | + <artifactId>onos-maven-plugin</artifactId> | ||
163 | + </plugin> | ||
164 | + </plugins> | ||
165 | + </build> | ||
34 | </project> | 166 | </project> | ... | ... |
1 | +/* | ||
2 | + * | ||
3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | + * you may not use this file except in compliance with the License. | ||
5 | + * You may obtain a copy of the License at | ||
6 | + * | ||
7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | + * | ||
9 | + * Unless required by applicable law or agreed to in writing, software | ||
10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | + * See the License for the specific language governing permissions and | ||
13 | + * limitations under the License. | ||
14 | + */ | ||
15 | +package org.onosproject.provider.snmp.alarm.impl; | ||
16 | + | ||
17 | +import com.btisystems.mibbler.mibs.bti7000.bti7000_13_2_0.I_Device; | ||
18 | +import com.btisystems.mibbler.mibs.bti7000.bti7000_13_2_0._OidRegistry; | ||
19 | +import com.btisystems.mibbler.mibs.bti7000.bti7000_13_2_0.btisystems.btiproducts.bti7000.objects.conditions.ActAlarmTable; | ||
20 | +import com.btisystems.mibbler.mibs.bti7000.interfaces.btisystems.btiproducts.bti7000.objects.conditions.IActAlarmTable; | ||
21 | +import com.btisystems.pronx.ems.core.model.ClassRegistry; | ||
22 | +import com.btisystems.pronx.ems.core.model.IClassRegistry; | ||
23 | +import com.btisystems.pronx.ems.core.model.NetworkDevice; | ||
24 | +import com.btisystems.pronx.ems.core.snmp.ISnmpSession; | ||
25 | +import java.io.IOException; | ||
26 | +import java.util.Arrays; | ||
27 | +import java.util.Calendar; | ||
28 | +import java.util.Collection; | ||
29 | +import java.util.Date; | ||
30 | +import java.util.GregorianCalendar; | ||
31 | +import java.util.HashSet; | ||
32 | +import java.util.Set; | ||
33 | +import java.util.TimeZone; | ||
34 | +import org.apache.commons.lang.StringUtils; | ||
35 | +import org.onosproject.incubator.net.faultmanagement.alarm.Alarm; | ||
36 | +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmEntityId; | ||
37 | +import org.onosproject.incubator.net.faultmanagement.alarm.DefaultAlarm; | ||
38 | +import org.onosproject.net.DeviceId; | ||
39 | +import org.slf4j.Logger; | ||
40 | +import static org.slf4j.LoggerFactory.getLogger; | ||
41 | +import org.snmp4j.smi.OID; | ||
42 | +import org.snmp4j.smi.OctetString; | ||
43 | + | ||
44 | +/** | ||
45 | + * BTI 7000 specific implementation to provide a list of current alarms. | ||
46 | + */ | ||
47 | +public class Bti7000SnmpAlarmProvider implements SnmpDeviceAlarmProvider { | ||
48 | + private final Logger log = getLogger(getClass()); | ||
49 | + protected static final IClassRegistry CLASS_REGISTRY = new ClassRegistry(_OidRegistry.oidRegistry, I_Device.class); | ||
50 | + | ||
51 | + static final int ALARM_SEVERITY_MINOR = 2; | ||
52 | + static final int ALARM_SEVERITY_MAJOR = 3; | ||
53 | + static final int ALARM_SEVERITY_CRITICAL = 4; | ||
54 | + | ||
55 | + @Override | ||
56 | + public Collection<Alarm> getAlarms(ISnmpSession session, DeviceId deviceID) { | ||
57 | + log.info("Getting alarms for BTI 7000 device at {}", deviceID); | ||
58 | + Set<Alarm> alarms = new HashSet<>(); | ||
59 | + NetworkDevice networkDevice = new NetworkDevice(CLASS_REGISTRY, | ||
60 | + session.getAddress().getHostAddress()); | ||
61 | + | ||
62 | + try { | ||
63 | + session.walkDevice(networkDevice, Arrays.asList( | ||
64 | + new OID[]{CLASS_REGISTRY.getClassToOidMap().get(ActAlarmTable.class)})); | ||
65 | + | ||
66 | + IActAlarmTable deviceAlarms = (IActAlarmTable) networkDevice.getRootObject() | ||
67 | + .getEntity(CLASS_REGISTRY.getClassToOidMap().get(ActAlarmTable.class)); | ||
68 | + if ((deviceAlarms != null) && (deviceAlarms.getActAlarmEntry() != null) | ||
69 | + && (!deviceAlarms.getActAlarmEntry().isEmpty())) { | ||
70 | + | ||
71 | + deviceAlarms.getActAlarmEntry().values().stream().forEach((alarm) -> { | ||
72 | + DefaultAlarm.Builder alarmBuilder = new DefaultAlarm.Builder( | ||
73 | + deviceID, alarm.getActAlarmDescription(), | ||
74 | + mapAlarmSeverity(alarm.getActAlarmSeverity()), | ||
75 | + getLocalDateAndTime(alarm.getActAlarmDateAndTime(), null, null).getTime()) | ||
76 | + .forSource(AlarmEntityId.alarmEntityId("other:" + alarm.getActAlarmInstanceIdx())); | ||
77 | + alarms.add(alarmBuilder.build()); | ||
78 | + }); | ||
79 | + | ||
80 | + } | ||
81 | + log.info("Conditions retrieved: {}", deviceAlarms); | ||
82 | + | ||
83 | + } catch (IOException ex) { | ||
84 | + log.error("Error reading alarms for device {}.", deviceID, ex); | ||
85 | + } | ||
86 | + | ||
87 | + return alarms; | ||
88 | + } | ||
89 | + | ||
90 | + private Alarm.SeverityLevel mapAlarmSeverity(int intAlarmSeverity) { | ||
91 | + Alarm.SeverityLevel mappedSeverity; | ||
92 | + switch (intAlarmSeverity) { | ||
93 | + case ALARM_SEVERITY_MINOR: | ||
94 | + mappedSeverity = Alarm.SeverityLevel.MINOR; | ||
95 | + break; | ||
96 | + case ALARM_SEVERITY_MAJOR: | ||
97 | + mappedSeverity = Alarm.SeverityLevel.MAJOR; | ||
98 | + break; | ||
99 | + case ALARM_SEVERITY_CRITICAL: | ||
100 | + mappedSeverity = Alarm.SeverityLevel.CRITICAL; | ||
101 | + break; | ||
102 | + default: | ||
103 | + mappedSeverity = Alarm.SeverityLevel.MINOR; | ||
104 | + log.warn("Unexpected alarm severity: {}", intAlarmSeverity); | ||
105 | + } | ||
106 | + return mappedSeverity; | ||
107 | + } | ||
108 | + /** | ||
109 | + * Converts an SNMP string representation into a {@link Date} object, | ||
110 | + * and applies time zone conversion to provide the time on the local machine, ie PSM server. | ||
111 | + * | ||
112 | + * @param actAlarmDateAndTime MIB-II DateAndTime formatted. May optionally contain | ||
113 | + * a timezone offset in 3 extra bytes | ||
114 | + * @param sysInfoTimeZone Must be supplied if actAlarmDateAndTime is just local time (with no timezone) | ||
115 | + * @param swVersion Must be supplied if actAlarmDateAndTime is just local time (with no timezone) | ||
116 | + * @return adjusted {@link Date} or a simple conversion if other fields are null. | ||
117 | + */ | ||
118 | + public static Date getLocalDateAndTime(String actAlarmDateAndTime, String sysInfoTimeZone, | ||
119 | + String swVersion) { | ||
120 | + if (StringUtils.isBlank(actAlarmDateAndTime)) { | ||
121 | + return null; | ||
122 | + } | ||
123 | + | ||
124 | + GregorianCalendar decodedDateAndTimeCal = btiMakeCalendar(OctetString.fromHexString(actAlarmDateAndTime)); | ||
125 | + if ((sysInfoTimeZone == null) || (swVersion == null)) { | ||
126 | + return decodedDateAndTimeCal.getTime(); | ||
127 | + } | ||
128 | + | ||
129 | + TimeZone javaTimeZone = getTimeZone(); | ||
130 | + decodedDateAndTimeCal.setTimeZone(javaTimeZone); | ||
131 | + | ||
132 | + GregorianCalendar localTime = new GregorianCalendar(); | ||
133 | + localTime.setTimeInMillis(decodedDateAndTimeCal.getTimeInMillis()); | ||
134 | + | ||
135 | + return localTime.getTime(); | ||
136 | + } | ||
137 | + | ||
138 | + /** | ||
139 | + * This method is similar to SNMP4J approach with some fixes for the 11-bytes version (ie the one with timezone | ||
140 | + * offset). | ||
141 | + * | ||
142 | + * For original makeCalendar refer @see http://www.snmp4j.org/agent/doc/org/snmp4j/agent/mo/snmp/DateAndTime.html | ||
143 | + * | ||
144 | + * Creates a <code>GregorianCalendar</code> from a properly formatted SNMP4J DateAndTime <code>OctetString</code>. | ||
145 | + * | ||
146 | + * @param dateAndTimeValue an OctetString conforming to the DateAndTime TC. | ||
147 | + * @return the corresponding <code>GregorianCalendar</code> instance. | ||
148 | + * | ||
149 | + */ | ||
150 | + public static GregorianCalendar btiMakeCalendar(OctetString dateAndTimeValue) { | ||
151 | + int year = (dateAndTimeValue.get(0) & 0xFF) * 256 | ||
152 | + + (dateAndTimeValue.get(1) & 0xFF); | ||
153 | + int month = (dateAndTimeValue.get(2) & 0xFF); | ||
154 | + int date = (dateAndTimeValue.get(3) & 0xFF); | ||
155 | + int hour = (dateAndTimeValue.get(4) & 0xFF); | ||
156 | + int minute = (dateAndTimeValue.get(5) & 0xFF); | ||
157 | + int second = (dateAndTimeValue.get(6) & 0xFF); | ||
158 | + int deci = (dateAndTimeValue.get(7) & 0xFF); | ||
159 | + GregorianCalendar gc = | ||
160 | + new GregorianCalendar(year, month - 1, date, hour, minute, second); | ||
161 | + gc.set(Calendar.MILLISECOND, deci * 100); | ||
162 | + | ||
163 | + if (dateAndTimeValue.length() == 11) { | ||
164 | + char directionOfOffset = (char) dateAndTimeValue.get(8); | ||
165 | + int hoursOffset = directionOfOffset == '+' | ||
166 | + ? dateAndTimeValue.get(9) : -dateAndTimeValue.get(9); | ||
167 | + org.joda.time.DateTimeZone offset = | ||
168 | + org.joda.time.DateTimeZone.forOffsetHoursMinutes(hoursOffset, dateAndTimeValue.get(10)); | ||
169 | + org.joda.time.DateTime dt = | ||
170 | + new org.joda.time.DateTime(year, month, date, hour, minute, second, offset); | ||
171 | + return dt.toGregorianCalendar(); | ||
172 | + } | ||
173 | + return gc; | ||
174 | + } | ||
175 | + | ||
176 | + private static TimeZone getTimeZone() { | ||
177 | + return Calendar.getInstance().getTimeZone(); | ||
178 | + } | ||
179 | +} |
1 | +/* | ||
2 | + * | ||
3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | + * you may not use this file except in compliance with the License. | ||
5 | + * You may obtain a copy of the License at | ||
6 | + * | ||
7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | + * | ||
9 | + * Unless required by applicable law or agreed to in writing, software | ||
10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | + * See the License for the specific language governing permissions and | ||
13 | + * limitations under the License. | ||
14 | + */ | ||
15 | +package org.onosproject.provider.snmp.alarm.impl; | ||
16 | + | ||
17 | +import com.btisystems.mibbler.mibs.netsnmp.netsnmp.I_Device; | ||
18 | +import com.btisystems.mibbler.mibs.netsnmp.netsnmp._OidRegistry; | ||
19 | +import com.btisystems.mibbler.mibs.netsnmp.netsnmp.mib_2.interfaces.IfTable; | ||
20 | +import com.btisystems.pronx.ems.core.model.ClassRegistry; | ||
21 | +import com.btisystems.pronx.ems.core.model.IClassRegistry; | ||
22 | +import com.btisystems.pronx.ems.core.model.NetworkDevice; | ||
23 | +import com.btisystems.pronx.ems.core.snmp.ISnmpSession; | ||
24 | +import java.io.IOException; | ||
25 | +import java.util.Arrays; | ||
26 | +import java.util.Collection; | ||
27 | +import java.util.HashSet; | ||
28 | +import java.util.Set; | ||
29 | +import org.onosproject.incubator.net.faultmanagement.alarm.Alarm; | ||
30 | +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmEntityId; | ||
31 | +import org.onosproject.incubator.net.faultmanagement.alarm.DefaultAlarm; | ||
32 | +import org.onosproject.net.DeviceId; | ||
33 | +import org.slf4j.Logger; | ||
34 | +import static org.slf4j.LoggerFactory.getLogger; | ||
35 | +import org.snmp4j.smi.OID; | ||
36 | + | ||
37 | +/** | ||
38 | + * Net SNMP specific implementation to provide a list of current alarms. | ||
39 | + */ | ||
40 | +public class NetSnmpAlarmProvider implements SnmpDeviceAlarmProvider { | ||
41 | + private final Logger log = getLogger(getClass()); | ||
42 | + protected static final IClassRegistry CLASS_REGISTRY = | ||
43 | + new ClassRegistry(_OidRegistry.oidRegistry, I_Device.class); | ||
44 | + @Override | ||
45 | + public Collection<Alarm> getAlarms(ISnmpSession session, DeviceId deviceId) { | ||
46 | + Set<Alarm> alarms = new HashSet<>(); | ||
47 | + | ||
48 | + NetworkDevice networkDevice = new NetworkDevice(CLASS_REGISTRY, | ||
49 | + session.getAddress().getHostAddress()); | ||
50 | + try { | ||
51 | + session.walkDevice(networkDevice, Arrays.asList(new OID[]{ | ||
52 | + CLASS_REGISTRY.getClassToOidMap().get(IfTable.class)})); | ||
53 | + | ||
54 | + IfTable interfaceTable = (IfTable) networkDevice.getRootObject() | ||
55 | + .getEntity(CLASS_REGISTRY.getClassToOidMap().get(IfTable.class)); | ||
56 | + if (interfaceTable != null) { | ||
57 | + interfaceTable.getEntries().values().stream().forEach((ifEntry) -> { | ||
58 | + //TODO will raise alarm for each interface as a demo. | ||
59 | + // if (ifEntry.getIfAdminStatus() == 1 && ifEntry.getIfOperStatus() == 2){ | ||
60 | + alarms.add(new DefaultAlarm.Builder(deviceId, "Link Down.", | ||
61 | + Alarm.SeverityLevel.CRITICAL, System.currentTimeMillis()) | ||
62 | + .forSource(AlarmEntityId.alarmEntityId("port:" + ifEntry.getIfDescr())).build()); | ||
63 | + // } | ||
64 | + log.info("Interface: " + ifEntry); | ||
65 | + }); | ||
66 | + } | ||
67 | + } catch (IOException ex) { | ||
68 | + log.error("Error reading alarms for device {}.", deviceId, ex); | ||
69 | + } | ||
70 | + return alarms; | ||
71 | + } | ||
72 | +} |
1 | -/* | ||
2 | - * Copyright 2014-2015 Open Networking Laboratory | ||
3 | - * | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - */ | ||
16 | -package org.onosproject.provider.snmp.alarm.impl; | ||
17 | - | ||
18 | -import org.apache.felix.scr.annotations.Component; | ||
19 | -import org.onosproject.net.DeviceId; | ||
20 | -import org.onosproject.incubator.net.faultmanagement.alarm.AlarmProvider; | ||
21 | -import org.onosproject.net.provider.AbstractProvider; | ||
22 | -import org.onosproject.net.provider.ProviderId; | ||
23 | -import org.slf4j.Logger; | ||
24 | - | ||
25 | -import static org.slf4j.LoggerFactory.getLogger; | ||
26 | - | ||
27 | -/** | ||
28 | - * Provider which uses an SNMP controller to detect network device alarms. The class leverages functionality from | ||
29 | - * | ||
30 | - * @see <a href="https://github.com/btisystems/snmp-core">https://github.com/btisystems/snmp-core</a> | ||
31 | - * @see <a href="https://github.com/btisystems/mibbler">https://github.com/btisystems/mibbler</a> | ||
32 | - */ | ||
33 | -@Component(immediate = true) | ||
34 | -public class SNMPAlarmProvider extends AbstractProvider implements AlarmProvider { | ||
35 | - | ||
36 | - private static final Logger LOG = getLogger(SNMPAlarmProvider.class); | ||
37 | - | ||
38 | - /** | ||
39 | - * Creates a SNMP alarm provider, dummy class provided as template, tbd later. | ||
40 | - */ | ||
41 | - public SNMPAlarmProvider() { | ||
42 | - super(new ProviderId("snmp", "org.onosproject.provider.alarm")); | ||
43 | - } | ||
44 | - | ||
45 | - @Override | ||
46 | - public void triggerProbe(DeviceId deviceId) { | ||
47 | - | ||
48 | - // TODO in shout term should this just be synchronous and return result? | ||
49 | - LOG.info("Run a SNMP discovery for device at {} when done invoke on AlarmProviderService", deviceId); | ||
50 | - | ||
51 | - // TODO Look up AlarmProviderService | ||
52 | - // TODO Decide threading | ||
53 | - // TODO Decide shouldn't it be generic not alarm-specific ? Its user responsible for passing in OID list ? | ||
54 | - // Same for its callack AlarmProviderService ? | ||
55 | - } | ||
56 | - | ||
57 | -} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.provider.snmp.alarm.impl; | ||
17 | + | ||
18 | +import com.btisystems.pronx.ems.core.snmp.DefaultSnmpConfigurationFactory; | ||
19 | +import com.btisystems.pronx.ems.core.snmp.ISnmpConfiguration; | ||
20 | +import com.btisystems.pronx.ems.core.snmp.ISnmpSession; | ||
21 | +import com.btisystems.pronx.ems.core.snmp.ISnmpSessionFactory; | ||
22 | +import com.btisystems.pronx.ems.core.snmp.SnmpSessionFactory; | ||
23 | +import com.btisystems.pronx.ems.core.snmp.V2cSnmpConfiguration; | ||
24 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
25 | +import com.google.common.collect.Sets; | ||
26 | +import java.io.IOException; | ||
27 | +import static org.slf4j.LoggerFactory.getLogger; | ||
28 | + | ||
29 | +import java.util.Collection; | ||
30 | +import java.util.HashMap; | ||
31 | +import java.util.HashSet; | ||
32 | +import java.util.Map; | ||
33 | +import java.util.Set; | ||
34 | +import java.util.concurrent.ExecutorService; | ||
35 | +import java.util.concurrent.Executors; | ||
36 | + | ||
37 | +import org.apache.felix.scr.annotations.Activate; | ||
38 | +import org.apache.felix.scr.annotations.Component; | ||
39 | +import org.apache.felix.scr.annotations.Deactivate; | ||
40 | +import org.apache.felix.scr.annotations.Modified; | ||
41 | +import org.onosproject.incubator.net.faultmanagement.alarm.Alarm; | ||
42 | +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmEvent; | ||
43 | +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmListener; | ||
44 | +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmProvider; | ||
45 | + | ||
46 | +import org.onosproject.net.DeviceId; | ||
47 | +import org.onosproject.net.provider.AbstractProvider; | ||
48 | +import org.onosproject.net.provider.ProviderId; | ||
49 | +import org.osgi.service.component.ComponentContext; | ||
50 | +import org.slf4j.Logger; | ||
51 | +import org.apache.felix.scr.annotations.Reference; | ||
52 | +import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
53 | +import static org.onlab.util.Tools.groupedThreads; | ||
54 | +import org.onosproject.core.ApplicationId; | ||
55 | +import org.onosproject.core.CoreService; | ||
56 | +import org.onosproject.incubator.net.faultmanagement.alarm.DefaultAlarm; | ||
57 | +import org.onosproject.net.device.DeviceEvent; | ||
58 | +import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_ADDED; | ||
59 | +import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED; | ||
60 | +import org.onosproject.net.device.DeviceListener; | ||
61 | +import org.onosproject.net.device.DeviceService; | ||
62 | + | ||
63 | +/** | ||
64 | + * SNMP alarms provider. | ||
65 | + */ | ||
66 | +@Component(immediate = true) | ||
67 | +public class SnmpAlarmProviderService extends AbstractProvider implements AlarmProvider { | ||
68 | + | ||
69 | + private final Logger log = getLogger(getClass()); | ||
70 | + | ||
71 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
72 | + protected CoreService coreService; | ||
73 | + | ||
74 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
75 | + protected DeviceService deviceService; | ||
76 | + | ||
77 | + private ApplicationId appId; | ||
78 | + | ||
79 | + private final ISnmpSessionFactory sessionFactory; | ||
80 | + | ||
81 | + // TODO convert to standard ONOS listener service approach ? | ||
82 | + protected Set<AlarmListener> alarmEventListener = Sets.newHashSet(); | ||
83 | + | ||
84 | + private ExecutorService eventHandlingExecutor; | ||
85 | + | ||
86 | + // TODO Could be replaced with a service lookup, and bundles per device variant. | ||
87 | + Map<String, SnmpDeviceAlarmProvider> providers = new HashMap<>(); | ||
88 | + | ||
89 | + public SnmpAlarmProviderService() { | ||
90 | + super(new ProviderId("snmp", "org.onosproject.provider.alarm")); | ||
91 | + sessionFactory = new SnmpSessionFactory( | ||
92 | + new DefaultSnmpConfigurationFactory(new V2cSnmpConfiguration())); | ||
93 | + providers.put("1.3.6.1.4.1.18070.2.2", new Bti7000SnmpAlarmProvider()); | ||
94 | + providers.put("1.3.6.1.4.1.20408", new NetSnmpAlarmProvider()); | ||
95 | + } | ||
96 | + | ||
97 | + @Activate | ||
98 | + public void activate(ComponentContext context) { | ||
99 | + appId = coreService.registerApplication("org.onosproject.snmp"); | ||
100 | + eventHandlingExecutor = Executors.newSingleThreadExecutor( | ||
101 | + groupedThreads("onos/alarms", "event-handler")); | ||
102 | + deviceService.addListener(new InternalDeviceListener()); | ||
103 | + log.info("activated SNMP provider with appId = {} and context props {}", appId, context.getProperties()); | ||
104 | + modified(context); | ||
105 | + | ||
106 | + log.info("Started"); | ||
107 | + } | ||
108 | + | ||
109 | + @Deactivate | ||
110 | + public void deactivate() { | ||
111 | + log.info("deactivate SNMP provider {}", appId); | ||
112 | + } | ||
113 | + | ||
114 | + @Modified | ||
115 | + public void modified(ComponentContext context) { | ||
116 | + log.info("modified {}", context); | ||
117 | + | ||
118 | + if (context == null) { | ||
119 | + log.info("No configuration file"); | ||
120 | + } | ||
121 | + | ||
122 | + } | ||
123 | + | ||
124 | + @Override | ||
125 | + public void triggerProbe(DeviceId deviceId) { | ||
126 | + log.info("SNMP walk request for alarms at deviceId={}", deviceId); | ||
127 | + if (!isSnmpDevice(deviceId)) { | ||
128 | + log.info("Ignore non-snmp device!"); | ||
129 | + return; | ||
130 | + } | ||
131 | + String[] deviceComponents = deviceId.toString().split(":"); | ||
132 | + Set<Alarm> alarms = new HashSet<>(Sets.newHashSet()); | ||
133 | + | ||
134 | + if (deviceComponents.length > 1) { | ||
135 | + String ipAddress = deviceComponents[1]; | ||
136 | + String port = deviceComponents[2]; | ||
137 | + ISnmpConfiguration config = new V2cSnmpConfiguration(); | ||
138 | + config.setPort(Integer.parseInt(port)); | ||
139 | + | ||
140 | + try (ISnmpSession session = getSessionFactory().createSession(config, ipAddress)) { | ||
141 | + // Each session will be auto-closed. | ||
142 | + String deviceOID = session.identifyDevice(); | ||
143 | + alarms.addAll(getAlarmsForDevice(deviceOID, session, deviceId)); | ||
144 | + log.info("SNMP walk completed ok for deviceId={}", deviceId); | ||
145 | + } catch (IOException | RuntimeException ex) { | ||
146 | + log.error("Failed to walk device.", ex.getMessage()); | ||
147 | + log.debug("Detailed problem was ", ex); | ||
148 | + alarms.add( | ||
149 | + buildWalkFailedAlarm(deviceId) | ||
150 | + ); | ||
151 | + } | ||
152 | + } | ||
153 | + | ||
154 | + AlarmEvent alarmEvent = new AlarmEvent(alarms, deviceId); | ||
155 | + | ||
156 | + alarmEventListener.stream().forEach((listener) -> { | ||
157 | + listener.event(alarmEvent); | ||
158 | + log.info("Successfully event with discovered alarms for deviceId={} to {}", deviceId, listener); | ||
159 | + }); | ||
160 | + | ||
161 | + } | ||
162 | + | ||
163 | + private static DefaultAlarm buildWalkFailedAlarm(DeviceId deviceId) { | ||
164 | + return new DefaultAlarm.Builder( | ||
165 | + deviceId, "SNMP alarm retrieval failed", | ||
166 | + Alarm.SeverityLevel.CRITICAL, | ||
167 | + System.currentTimeMillis()).build(); | ||
168 | + } | ||
169 | + | ||
170 | + protected ISnmpSessionFactory getSessionFactory() { | ||
171 | + return sessionFactory; | ||
172 | + } | ||
173 | + | ||
174 | + private Collection<Alarm> getAlarmsForDevice(String deviceOID, ISnmpSession session, | ||
175 | + DeviceId deviceID) throws IOException { | ||
176 | + Collection<Alarm> alarms = new HashSet<>(); | ||
177 | + if (providers.containsKey(deviceOID)) { | ||
178 | + alarms.addAll(providers.get(deviceOID).getAlarms(session, deviceID)); | ||
179 | + } | ||
180 | + return alarms; | ||
181 | + } | ||
182 | + | ||
183 | + @Override | ||
184 | + public void addAlarmListener(AlarmListener listener) { | ||
185 | + alarmEventListener.add(checkNotNull(listener, "Listener cannot be null")); | ||
186 | + } | ||
187 | + | ||
188 | + @Override | ||
189 | + public void removeAlarmListener(AlarmListener listener) { | ||
190 | + alarmEventListener.remove(checkNotNull(listener, "Listener cannot be null")); | ||
191 | + } | ||
192 | + | ||
193 | + /** | ||
194 | + * Internal listener for device service events. | ||
195 | + */ | ||
196 | + private class InternalDeviceListener implements DeviceListener { | ||
197 | + | ||
198 | + @Override | ||
199 | + public void event(DeviceEvent event) { | ||
200 | + log.info("InternalDeviceListener has got event from device-service{} with ", event); | ||
201 | + eventHandlingExecutor.execute(() -> { | ||
202 | + try { | ||
203 | + DeviceId deviceId = event.subject().id(); | ||
204 | + log.info("From device {}", deviceId); | ||
205 | + if (!isSnmpDevice(deviceId)) { | ||
206 | + log.info("Ignore non-snmp device event for {}", deviceId); | ||
207 | + return; | ||
208 | + } | ||
209 | + | ||
210 | + switch (event.type()) { | ||
211 | + case DEVICE_ADDED: | ||
212 | + case DEVICE_UPDATED: | ||
213 | + case DEVICE_AVAILABILITY_CHANGED: | ||
214 | + if (deviceService.isAvailable(event.subject().id())) { | ||
215 | + triggerProbe(deviceId); | ||
216 | + } | ||
217 | + break; | ||
218 | + case DEVICE_REMOVED: | ||
219 | + case DEVICE_SUSPENDED: | ||
220 | + default: | ||
221 | + // Could potentially remove all alarms when eg DEVICE_REMOVED or DEVICE_SUSPENDED | ||
222 | + // however for now ignore and fall through | ||
223 | + break; | ||
224 | + } | ||
225 | + } catch (Exception e) { | ||
226 | + log.warn("Failed to process {}", event, e); | ||
227 | + } | ||
228 | + }); | ||
229 | + } | ||
230 | + | ||
231 | + } | ||
232 | + | ||
233 | + private static boolean isSnmpDevice(DeviceId deviceId) { | ||
234 | + return deviceId.uri().getScheme().equalsIgnoreCase("snmp"); | ||
235 | + } | ||
236 | +} |
1 | +/* | ||
2 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
3 | + * you may not use this file except in compliance with the License. | ||
4 | + * You may obtain a copy of the License at | ||
5 | + * | ||
6 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
7 | + * | ||
8 | + * Unless required by applicable law or agreed to in writing, software | ||
9 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
10 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
11 | + * See the License for the specific language governing permissions and | ||
12 | + * limitations under the License. | ||
13 | + */ | ||
14 | +package org.onosproject.provider.snmp.alarm.impl; | ||
15 | + | ||
16 | +import com.btisystems.pronx.ems.core.snmp.ISnmpSession; | ||
17 | +import java.util.Collection; | ||
18 | +import org.onosproject.incubator.net.faultmanagement.alarm.Alarm; | ||
19 | +import org.onosproject.net.DeviceId; | ||
20 | + | ||
21 | +public interface SnmpDeviceAlarmProvider { | ||
22 | + /** | ||
23 | + * Implemented by device specific implementations which query the current | ||
24 | + * alarms from a device. | ||
25 | + * @param snmpSession SNMP Session | ||
26 | + * @param deviceId device identifier | ||
27 | + * @return device alarms | ||
28 | + */ | ||
29 | + Collection<Alarm> getAlarms(ISnmpSession snmpSession, DeviceId deviceId); | ||
30 | +} |
1 | /* | 1 | /* |
2 | +<<<<<<< HEAD | ||
3 | + * Copyright 2015 Open Networking Laboratory | ||
4 | +======= | ||
2 | * Copyright 2014 Open Networking Laboratory | 5 | * Copyright 2014 Open Networking Laboratory |
6 | +>>>>>>> master | ||
3 | * | 7 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 8 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | 9 | * you may not use this file except in compliance with the License. |
... | @@ -15,6 +19,6 @@ | ... | @@ -15,6 +19,6 @@ |
15 | */ | 19 | */ |
16 | 20 | ||
17 | /** | 21 | /** |
18 | - * Provider that uses SNMP as a means of discovering alarms on devices. | 22 | + * Provider that will support SNMP alarm discoveries. |
19 | */ | 23 | */ |
20 | package org.onosproject.provider.snmp.alarm.impl; | 24 | package org.onosproject.provider.snmp.alarm.impl; | ... | ... |
1 | +/* | ||
2 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
3 | + * you may not use this file except in compliance with the License. | ||
4 | + * You may obtain a copy of the License at | ||
5 | + * | ||
6 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
7 | + * | ||
8 | + * Unless required by applicable law or agreed to in writing, software | ||
9 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
10 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
11 | + * See the License for the specific language governing permissions and | ||
12 | + * limitations under the License. | ||
13 | + */ | ||
14 | +package org.onosproject.provider.snmp.alarm.impl; | ||
15 | + | ||
16 | +import com.btisystems.mibbler.mibs.bti7000.bti7000_13_2_0.btisystems.btiproducts.bti7000.objects.conditions.ActAlarmTable; | ||
17 | +import com.btisystems.mibbler.mibs.bti7000.interfaces.btisystems.btiproducts.bti7000.objects.conditions.actalarmtable.IActAlarmEntry; | ||
18 | +import com.btisystems.pronx.ems.core.model.NetworkDevice; | ||
19 | +import com.btisystems.pronx.ems.core.snmp.ISnmpSession; | ||
20 | +import java.io.IOException; | ||
21 | +import java.net.InetAddress; | ||
22 | +import java.net.UnknownHostException; | ||
23 | +import java.util.Arrays; | ||
24 | +import java.util.Collection; | ||
25 | +import org.easymock.Capture; | ||
26 | +import static org.easymock.EasyMock.capture; | ||
27 | +import static org.easymock.EasyMock.createMock; | ||
28 | +import static org.easymock.EasyMock.eq; | ||
29 | +import static org.easymock.EasyMock.expect; | ||
30 | +import static org.easymock.EasyMock.isA; | ||
31 | +import static org.easymock.EasyMock.replay; | ||
32 | +import static org.easymock.EasyMock.verify; | ||
33 | +import org.junit.Before; | ||
34 | +import org.junit.Test; | ||
35 | +import static org.junit.Assert.*; | ||
36 | +import org.onosproject.incubator.net.faultmanagement.alarm.Alarm; | ||
37 | +import org.onosproject.net.DeviceId; | ||
38 | +import org.snmp4j.smi.OID; | ||
39 | + | ||
40 | + | ||
41 | +public class Bti7000SnmpAlarmProviderTest { | ||
42 | + private Bti7000SnmpAlarmProvider alarmProvider; | ||
43 | + private ISnmpSession mockSession; | ||
44 | + private ActAlarmTable alarmsTable; | ||
45 | + | ||
46 | + public Bti7000SnmpAlarmProviderTest() { | ||
47 | + } | ||
48 | + | ||
49 | + @Before | ||
50 | + public void setUp() { | ||
51 | + mockSession = createMock(ISnmpSession.class); | ||
52 | + | ||
53 | + alarmProvider = new Bti7000SnmpAlarmProvider(); | ||
54 | + } | ||
55 | + | ||
56 | + @Test | ||
57 | + public void shouldWalkDevice() throws UnknownHostException, IOException { | ||
58 | + expect(mockSession.getAddress()).andReturn(InetAddress.getLoopbackAddress()); | ||
59 | + expect(mockSession.walkDevice(isA(NetworkDevice.class), | ||
60 | + eq(Arrays.asList(new OID[]{ | ||
61 | + Bti7000SnmpAlarmProvider.CLASS_REGISTRY.getClassToOidMap().get(ActAlarmTable.class)})))) | ||
62 | + .andReturn(null); | ||
63 | + | ||
64 | + replay(mockSession); | ||
65 | + | ||
66 | + assertNotNull(alarmProvider.getAlarms(mockSession, DeviceId.deviceId("snmp:1.1.1.1"))); | ||
67 | + | ||
68 | + verify(mockSession); | ||
69 | + } | ||
70 | + | ||
71 | + @Test | ||
72 | + public void shouldFindAlarms() throws UnknownHostException, IOException { | ||
73 | + alarmsTable = new ActAlarmTable(); | ||
74 | + alarmsTable.createEntry("14.1.3.6.1.4.1.18070.2.2.2.2.20.0.1.13.1.3.6.1.4.1." | ||
75 | + + "18070.2.2.1.4.14.1.7.49.46.55.46.50.46.53"); | ||
76 | + IActAlarmEntry entry = alarmsTable.getEntries().values().iterator().next(); | ||
77 | + entry.setActAlarmDescription("XFP Missing."); | ||
78 | + entry.setActAlarmDateAndTime("07:df:0c:01:03:0d:30:00"); | ||
79 | + entry.setActAlarmSeverity(1); | ||
80 | + | ||
81 | + Capture<NetworkDevice> networkDeviceCapture = new Capture<>(); | ||
82 | + | ||
83 | + expect(mockSession.getAddress()).andReturn(InetAddress.getLoopbackAddress()); | ||
84 | + expect(mockSession.walkDevice(capture(networkDeviceCapture), | ||
85 | + eq(Arrays.asList(new OID[]{ | ||
86 | + Bti7000SnmpAlarmProvider.CLASS_REGISTRY.getClassToOidMap().get(ActAlarmTable.class)})))) | ||
87 | + .andAnswer(() -> { | ||
88 | + networkDeviceCapture.getValue().getRootObject().setObject(alarmsTable); | ||
89 | + return null; | ||
90 | + }); | ||
91 | + | ||
92 | + replay(mockSession); | ||
93 | + | ||
94 | + Collection<Alarm> alarms = alarmProvider.getAlarms(mockSession, DeviceId.deviceId("snmp:1.1.1.1")); | ||
95 | + assertEquals(1, alarms.size()); | ||
96 | + assertEquals("XFP Missing.", alarms.iterator().next().description()); | ||
97 | + verify(mockSession); | ||
98 | + } | ||
99 | + | ||
100 | + @Test | ||
101 | + public void shouldHandleException() throws UnknownHostException, IOException { | ||
102 | + expect(mockSession.getAddress()).andReturn(InetAddress.getLoopbackAddress()); | ||
103 | + expect(mockSession.walkDevice(isA(NetworkDevice.class), | ||
104 | + eq(Arrays.asList(new OID[]{ | ||
105 | + Bti7000SnmpAlarmProvider.CLASS_REGISTRY.getClassToOidMap().get(ActAlarmTable.class)})))) | ||
106 | + .andThrow(new IOException()); | ||
107 | + | ||
108 | + replay(mockSession); | ||
109 | + | ||
110 | + assertNotNull(alarmProvider.getAlarms(mockSession, DeviceId.deviceId("snmp:1.1.1.1"))); | ||
111 | + | ||
112 | + verify(mockSession); | ||
113 | + } | ||
114 | + | ||
115 | +} |
1 | +/* | ||
2 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
3 | + * you may not use this file except in compliance with the License. | ||
4 | + * You may obtain a copy of the License at | ||
5 | + * | ||
6 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
7 | + * | ||
8 | + * Unless required by applicable law or agreed to in writing, software | ||
9 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
10 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
11 | + * See the License for the specific language governing permissions and | ||
12 | + * limitations under the License. | ||
13 | + */ | ||
14 | +package org.onosproject.provider.snmp.alarm.impl; | ||
15 | + | ||
16 | +import com.btisystems.mibbler.mibs.netsnmp.interfaces.mib_2.interfaces.iftable.IIfEntry; | ||
17 | +import com.btisystems.mibbler.mibs.netsnmp.netsnmp.mib_2.interfaces.IfTable; | ||
18 | +import com.btisystems.pronx.ems.core.model.NetworkDevice; | ||
19 | +import com.btisystems.pronx.ems.core.snmp.ISnmpSession; | ||
20 | +import java.io.IOException; | ||
21 | +import java.net.InetAddress; | ||
22 | +import java.net.UnknownHostException; | ||
23 | +import java.util.Arrays; | ||
24 | +import java.util.Collection; | ||
25 | +import org.easymock.Capture; | ||
26 | +import static org.easymock.EasyMock.capture; | ||
27 | +import static org.easymock.EasyMock.createMock; | ||
28 | +import static org.easymock.EasyMock.eq; | ||
29 | +import static org.easymock.EasyMock.expect; | ||
30 | +import static org.easymock.EasyMock.isA; | ||
31 | +import static org.easymock.EasyMock.replay; | ||
32 | +import static org.easymock.EasyMock.verify; | ||
33 | +import org.junit.Before; | ||
34 | +import org.junit.Test; | ||
35 | +import static org.junit.Assert.*; | ||
36 | +import org.onosproject.incubator.net.faultmanagement.alarm.Alarm; | ||
37 | +import org.onosproject.net.DeviceId; | ||
38 | +import org.snmp4j.smi.OID; | ||
39 | + | ||
40 | + | ||
41 | +public class NetSnmpSnmpAlarmProviderTest { | ||
42 | + private NetSnmpAlarmProvider alarmProvider; | ||
43 | + private ISnmpSession mockSession; | ||
44 | + private IfTable interfaceTable; | ||
45 | + | ||
46 | + public NetSnmpSnmpAlarmProviderTest() { | ||
47 | + } | ||
48 | + | ||
49 | + @Before | ||
50 | + public void setUp() { | ||
51 | + mockSession = createMock(ISnmpSession.class); | ||
52 | + | ||
53 | + alarmProvider = new NetSnmpAlarmProvider(); | ||
54 | + } | ||
55 | + | ||
56 | + @Test | ||
57 | + public void shouldWalkDevice() throws UnknownHostException, IOException { | ||
58 | + expect(mockSession.getAddress()).andReturn(InetAddress.getLoopbackAddress()); | ||
59 | + expect(mockSession.walkDevice(isA(NetworkDevice.class), | ||
60 | + eq(Arrays.asList(new OID[]{ | ||
61 | + NetSnmpAlarmProvider.CLASS_REGISTRY.getClassToOidMap().get(IfTable.class)})))) | ||
62 | + .andReturn(null); | ||
63 | + | ||
64 | + replay(mockSession); | ||
65 | + | ||
66 | + assertNotNull(alarmProvider.getAlarms(mockSession, DeviceId.deviceId("snmp:1.1.1.1"))); | ||
67 | + | ||
68 | + verify(mockSession); | ||
69 | + } | ||
70 | + | ||
71 | + @Test | ||
72 | + public void shouldFindAlarms() throws UnknownHostException, IOException { | ||
73 | + interfaceTable = new IfTable(); | ||
74 | + interfaceTable.createEntry("1"); | ||
75 | + IIfEntry entry = interfaceTable.getEntry("1"); | ||
76 | + entry.setIfDescr("eth1"); | ||
77 | + entry.setIfAdminStatus(1); | ||
78 | + entry.setIfOperStatus(2); | ||
79 | + | ||
80 | + Capture<NetworkDevice> networkDeviceCapture = new Capture<>(); | ||
81 | + | ||
82 | + expect(mockSession.getAddress()).andReturn(InetAddress.getLoopbackAddress()); | ||
83 | + expect(mockSession.walkDevice(capture(networkDeviceCapture), | ||
84 | + eq(Arrays.asList(new OID[]{ | ||
85 | + NetSnmpAlarmProvider.CLASS_REGISTRY.getClassToOidMap().get(IfTable.class)})))) | ||
86 | + .andAnswer(() -> { | ||
87 | + networkDeviceCapture.getValue().getRootObject().setObject(interfaceTable); | ||
88 | + return null; | ||
89 | + }); | ||
90 | + | ||
91 | + replay(mockSession); | ||
92 | + | ||
93 | + Collection<Alarm> alarms = alarmProvider.getAlarms(mockSession, DeviceId.deviceId("snmp:1.1.1.1")); | ||
94 | + assertEquals(1, alarms.size()); | ||
95 | + assertEquals("Link Down.", alarms.iterator().next().description()); | ||
96 | + verify(mockSession); | ||
97 | + } | ||
98 | + | ||
99 | + @Test | ||
100 | + public void shouldHandleException() throws UnknownHostException, IOException { | ||
101 | + expect(mockSession.getAddress()).andReturn(InetAddress.getLoopbackAddress()); | ||
102 | + expect(mockSession.walkDevice(isA(NetworkDevice.class), | ||
103 | + eq(Arrays.asList(new OID[]{ | ||
104 | + NetSnmpAlarmProvider.CLASS_REGISTRY.getClassToOidMap().get(IfTable.class)})))) | ||
105 | + .andThrow(new IOException()); | ||
106 | + | ||
107 | + replay(mockSession); | ||
108 | + | ||
109 | + assertNotNull(alarmProvider.getAlarms(mockSession, DeviceId.deviceId("snmp:1.1.1.1"))); | ||
110 | + | ||
111 | + verify(mockSession); | ||
112 | + } | ||
113 | + | ||
114 | +} |
1 | +/* | ||
2 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
3 | + * you may not use this file except in compliance with the License. | ||
4 | + * You may obtain a copy of the License at | ||
5 | + * | ||
6 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
7 | + * | ||
8 | + * Unless required by applicable law or agreed to in writing, software | ||
9 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
10 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
11 | + * See the License for the specific language governing permissions and | ||
12 | + * limitations under the License. | ||
13 | + */ | ||
14 | +package org.onosproject.provider.snmp.alarm.impl; | ||
15 | + | ||
16 | +import com.btisystems.pronx.ems.core.snmp.ISnmpConfiguration; | ||
17 | +import com.btisystems.pronx.ems.core.snmp.ISnmpSession; | ||
18 | +import com.btisystems.pronx.ems.core.snmp.ISnmpSessionFactory; | ||
19 | +import java.io.IOException; | ||
20 | +import java.util.HashSet; | ||
21 | +import org.easymock.EasyMock; | ||
22 | +import static org.easymock.EasyMock.expect; | ||
23 | +import static org.easymock.EasyMock.replay; | ||
24 | +import static org.easymock.EasyMock.verify; | ||
25 | +import org.junit.Assert; | ||
26 | +import org.junit.Before; | ||
27 | +import org.junit.Test; | ||
28 | +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmEvent; | ||
29 | +import org.onosproject.net.DeviceId; | ||
30 | + | ||
31 | +public class SnmpDeviceAlarmProviderTest { | ||
32 | + private SnmpAlarmProviderService alarmProvider; | ||
33 | + private ISnmpSessionFactory mockSessionFactory; | ||
34 | + private ISnmpSession mockSession; | ||
35 | + private SnmpDeviceAlarmProvider mockProvider; | ||
36 | + private AlarmEvent alarmEvent; | ||
37 | + | ||
38 | + public SnmpDeviceAlarmProviderTest() {} | ||
39 | + | ||
40 | + @Before | ||
41 | + public void setUp() { | ||
42 | + mockSessionFactory = EasyMock.createMock(ISnmpSessionFactory.class); | ||
43 | + mockSession = EasyMock.createMock(ISnmpSession.class); | ||
44 | + mockProvider = EasyMock.createMock(SnmpDeviceAlarmProvider.class); | ||
45 | + | ||
46 | + alarmProvider = new SnmpAlarmProviderService() { | ||
47 | + @Override | ||
48 | + protected ISnmpSessionFactory getSessionFactory() { | ||
49 | + return mockSessionFactory; | ||
50 | + } | ||
51 | + }; | ||
52 | + | ||
53 | + alarmProvider.addAlarmListener((AlarmEvent event) -> { | ||
54 | + alarmEvent = event; | ||
55 | + }); | ||
56 | + } | ||
57 | + | ||
58 | + @Test | ||
59 | + public void shouldPopulateAlarmsForNetSnmp() throws IOException { | ||
60 | + alarmProvider.providers.put("1.2.3.4", mockProvider); | ||
61 | + expect(mockSessionFactory.createSession(EasyMock.isA(ISnmpConfiguration.class), | ||
62 | + EasyMock.eq("1.1.1.1"))).andReturn(mockSession); | ||
63 | + expect(mockSession.identifyDevice()).andReturn("1.2.3.4"); | ||
64 | + expect(mockProvider.getAlarms(mockSession, DeviceId.deviceId("snmp:1.1.1.1:161"))) | ||
65 | + .andReturn(new HashSet<>()); | ||
66 | + | ||
67 | + mockSession.close(); | ||
68 | + EasyMock.expectLastCall().once(); | ||
69 | + | ||
70 | + replay(mockSessionFactory, mockSession, mockProvider); | ||
71 | + | ||
72 | + alarmProvider.triggerProbe(DeviceId.deviceId("snmp:1.1.1.1:161")); | ||
73 | + | ||
74 | + verify(mockSessionFactory, mockSession, mockProvider); | ||
75 | + Assert.assertNotNull(alarmEvent); | ||
76 | + } | ||
77 | + | ||
78 | +} |
providers/snmp/app/app.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<!-- | ||
3 | + ~ Copyright 2015 Open Networking Laboratory | ||
4 | + ~ | ||
5 | + ~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + ~ you may not use this file except in compliance with the License. | ||
7 | + ~ You may obtain a copy of the License at | ||
8 | + ~ | ||
9 | + ~ http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + ~ | ||
11 | + ~ Unless required by applicable law or agreed to in writing, software | ||
12 | + ~ distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + ~ See the License for the specific language governing permissions and | ||
15 | + ~ limitations under the License. | ||
16 | + --> | ||
17 | +<app name="org.onosproject.snmp" origin="BTI Systems" version="${project.version}" | ||
18 | + featuresRepo="mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features" | ||
19 | + features="${project.artifactId}"> | ||
20 | + <description>${project.description}</description> | ||
21 | + <artifact>mvn:${project.groupId}/onos-snmp-provider-device/${project.version}</artifact> | ||
22 | + <artifact>mvn:${project.groupId}/onos-snmp-provider-alarm/${project.version}</artifact> | ||
23 | +</app> |
providers/snmp/app/features.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> | ||
2 | +<!-- | ||
3 | + ~ Copyright 2015 Open Networking Laboratory | ||
4 | + ~ | ||
5 | + ~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + ~ you may not use this file except in compliance with the License. | ||
7 | + ~ You may obtain a copy of the License at | ||
8 | + ~ | ||
9 | + ~ http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + ~ | ||
11 | + ~ Unless required by applicable law or agreed to in writing, software | ||
12 | + ~ distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + ~ See the License for the specific language governing permissions and | ||
15 | + ~ limitations under the License. | ||
16 | + --> | ||
17 | +<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}"> | ||
18 | + <feature name="${project.artifactId}" version="${project.version}" | ||
19 | + description="${project.description}"> | ||
20 | + <feature>onos-api</feature> | ||
21 | + <bundle>mvn:io.netty/netty/3.9.2.Final</bundle> | ||
22 | + <bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.snmp4j/2.3.4_1</bundle> | ||
23 | + <bundle>mvn:${project.groupId}/onos-snmp-provider-device/${project.version}</bundle> | ||
24 | + <bundle>mvn:com.btisystems/snmp-core/1.3-SNAPSHOT</bundle> | ||
25 | + <bundle>mvn:com.btisystems.mibbler.mibs/bti7000/1.0-SNAPSHOT</bundle> | ||
26 | + <bundle>mvn:com.btisystems.mibbler.mibs/net-snmp/1.0-SNAPSHOT</bundle> | ||
27 | + </feature> | ||
28 | +</features> | ||
29 | + |
providers/snmp/app/pom.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<!-- | ||
3 | + ~ Copyright 2015 Open Networking Laboratory | ||
4 | + ~ | ||
5 | + ~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + ~ you may not use this file except in compliance with the License. | ||
7 | + ~ You may obtain a copy of the License at | ||
8 | + ~ | ||
9 | + ~ http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + ~ | ||
11 | + ~ Unless required by applicable law or agreed to in writing, software | ||
12 | + ~ distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + ~ See the License for the specific language governing permissions and | ||
15 | + ~ limitations under the License. | ||
16 | + --> | ||
17 | +<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
18 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
19 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
20 | + <modelVersion>4.0.0</modelVersion> | ||
21 | + | ||
22 | + <parent> | ||
23 | + <groupId>org.onosproject</groupId> | ||
24 | + <artifactId>onos-snmp-providers</artifactId> | ||
25 | + <version>1.4.0-SNAPSHOT</version> | ||
26 | + <relativePath>../pom.xml</relativePath> | ||
27 | + </parent> | ||
28 | + | ||
29 | + <artifactId>onos-snmp-app</artifactId> | ||
30 | + <packaging>pom</packaging> | ||
31 | + | ||
32 | + <description>SNMP protocol southbound providers</description> | ||
33 | + | ||
34 | + <dependencies> | ||
35 | + <dependency> | ||
36 | + <groupId>org.onosproject</groupId> | ||
37 | + <artifactId>onos-snmp-provider-device</artifactId> | ||
38 | + <version>${project.version}</version> | ||
39 | + </dependency> | ||
40 | + <dependency> | ||
41 | + <groupId>org.onosproject</groupId> | ||
42 | + <artifactId>onos-snmp-provider-alarm</artifactId> | ||
43 | + <version>${project.version}</version> | ||
44 | + </dependency> | ||
45 | + </dependencies> | ||
46 | + | ||
47 | +</project> |
providers/snmp/device/pom.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<!-- | ||
3 | + ~ Copyright 2015 Open Networking Laboratory | ||
4 | + ~ | ||
5 | + ~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + ~ you may not use this file except in compliance with the License. | ||
7 | + ~ You may obtain a copy of the License at | ||
8 | + ~ | ||
9 | + ~ http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + ~ | ||
11 | + ~ Unless required by applicable law or agreed to in writing, software | ||
12 | + ~ distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + ~ See the License for the specific language governing permissions and | ||
15 | + ~ limitations under the License. | ||
16 | +--> | ||
17 | +<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
18 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
19 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
20 | + <modelVersion>4.0.0</modelVersion> | ||
21 | + | ||
22 | + <parent> | ||
23 | + <groupId>org.onosproject</groupId> | ||
24 | + <artifactId>onos-snmp-providers</artifactId> | ||
25 | + <version>1.4.0-SNAPSHOT</version> | ||
26 | + <relativePath>../pom.xml</relativePath> | ||
27 | + </parent> | ||
28 | + | ||
29 | + <artifactId>onos-snmp-provider-device</artifactId> | ||
30 | + <packaging>bundle</packaging> | ||
31 | + | ||
32 | + <description>ONOS SNMP protocol device provider</description> | ||
33 | + | ||
34 | + <dependencies> | ||
35 | + <dependency> | ||
36 | + <groupId>org.osgi</groupId> | ||
37 | + <artifactId>org.osgi.compendium</artifactId> | ||
38 | + </dependency> | ||
39 | + <!-- <dependency> | ||
40 | + <groupId>javax.ws.rs</groupId> | ||
41 | + <artifactId>jsr311-api</artifactId> | ||
42 | + <version>1.1.1</version> | ||
43 | + </dependency> | ||
44 | + <dependency> | ||
45 | + <groupId>org.onosproject</groupId> | ||
46 | + <artifactId>onos-incubator-api</artifactId> | ||
47 | + </dependency> | ||
48 | + <dependency> | ||
49 | + <groupId>org.onosproject</groupId> | ||
50 | + <artifactId>onos-core-serializers</artifactId> | ||
51 | + <version>${project.version}</version> | ||
52 | + </dependency>--> | ||
53 | + </dependencies> | ||
54 | + <build> | ||
55 | + <plugins> | ||
56 | + <plugin> | ||
57 | + <groupId>org.apache.felix</groupId> | ||
58 | + <artifactId>maven-scr-plugin</artifactId> | ||
59 | + </plugin> | ||
60 | + </plugins> | ||
61 | + </build> | ||
62 | + | ||
63 | +</project> | ||
64 | + | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +/* | ||
2 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
3 | + * you may not use this file except in compliance with the License. | ||
4 | + * You may obtain a copy of the License at | ||
5 | + * | ||
6 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
7 | + * | ||
8 | + * Unless required by applicable law or agreed to in writing, software | ||
9 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
10 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
11 | + * See the License for the specific language governing permissions and | ||
12 | + * limitations under the License. | ||
13 | + */ | ||
14 | +package org.onosproject.provider.snmp.device.impl; | ||
15 | + | ||
16 | +import com.btisystems.mibbler.mibs.bti7000.bti7000_13_2_0.I_Device; | ||
17 | +import com.btisystems.mibbler.mibs.bti7000.bti7000_13_2_0._OidRegistry; | ||
18 | +import com.btisystems.pronx.ems.core.model.ClassRegistry; | ||
19 | +import com.btisystems.pronx.ems.core.model.IClassRegistry; | ||
20 | +import com.btisystems.pronx.ems.core.model.NetworkDevice; | ||
21 | +import com.btisystems.pronx.ems.core.snmp.ISnmpSession; | ||
22 | +import java.io.IOException; | ||
23 | +import java.util.Arrays; | ||
24 | +import org.onosproject.net.device.DefaultDeviceDescription; | ||
25 | +import org.onosproject.net.device.DeviceDescription; | ||
26 | +import org.slf4j.Logger; | ||
27 | +import static org.slf4j.LoggerFactory.getLogger; | ||
28 | +import org.snmp4j.smi.OID; | ||
29 | + | ||
30 | +/** | ||
31 | + * A vendor-specific implementation supporting BTI Systems BTI-7000 equipment. | ||
32 | + */ | ||
33 | +public class Bti7000DeviceDescriptionProvider implements SnmpDeviceDescriptionProvider { | ||
34 | + private final Logger log = getLogger(getClass()); | ||
35 | + protected static final IClassRegistry CLASS_REGISTRY = | ||
36 | + new ClassRegistry(_OidRegistry.oidRegistry, I_Device.class); | ||
37 | + private static final String UNKNOWN = "unknown"; | ||
38 | + | ||
39 | + @Override | ||
40 | + public DeviceDescription populateDescription(ISnmpSession session, DeviceDescription description) { | ||
41 | + NetworkDevice networkDevice = new NetworkDevice(CLASS_REGISTRY, | ||
42 | + session.getAddress().getHostAddress()); | ||
43 | + try { | ||
44 | + session.walkDevice(networkDevice, Arrays.asList(new OID[]{ | ||
45 | + CLASS_REGISTRY.getClassToOidMap().get( | ||
46 | + com.btisystems.mibbler.mibs.bti7000.bti7000_13_2_0.mib_2.System.class)})); | ||
47 | + | ||
48 | + com.btisystems.mibbler.mibs.bti7000.bti7000_13_2_0.mib_2.System systemTree = | ||
49 | + (com.btisystems.mibbler.mibs.bti7000.bti7000_13_2_0.mib_2.System) | ||
50 | + networkDevice.getRootObject().getEntity(CLASS_REGISTRY.getClassToOidMap().get( | ||
51 | + com.btisystems.mibbler.mibs.bti7000.bti7000_13_2_0.mib_2.System.class)); | ||
52 | + if (systemTree != null) { | ||
53 | + String[] systemComponents = systemTree.getSysDescr().split(";"); | ||
54 | + return new DefaultDeviceDescription(description.deviceUri(), description.type(), | ||
55 | + systemComponents[0], systemComponents[2], systemComponents[3], | ||
56 | + UNKNOWN, description.chassisId()); | ||
57 | + } | ||
58 | + } catch (IOException ex) { | ||
59 | + log.error("Error reading details for device {}.", session.getAddress(), ex); | ||
60 | + } | ||
61 | + return description; | ||
62 | + } | ||
63 | + | ||
64 | +} |
providers/snmp/device/src/main/java/org/onosproject/provider/snmp/device/impl/DeviceState.java
0 → 100644
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.provider.snmp.device.impl; | ||
18 | + /** | ||
19 | + * The Device State is used to determine whether the device is active or inactive. This state information will help | ||
20 | + * Device Creator to add or delete the device from the core. | ||
21 | + */ | ||
22 | + public enum DeviceState { | ||
23 | + /* Used to specify Active state of the device */ | ||
24 | + | ||
25 | + ACTIVE, | ||
26 | + /* Used to specify inactive state of the device */ | ||
27 | + INACTIVE, | ||
28 | + /* Used to specify invalid state of the device */ | ||
29 | + INVALID | ||
30 | + } |
1 | +/* | ||
2 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
3 | + * you may not use this file except in compliance with the License. | ||
4 | + * You may obtain a copy of the License at | ||
5 | + * | ||
6 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
7 | + * | ||
8 | + * Unless required by applicable law or agreed to in writing, software | ||
9 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
10 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
11 | + * See the License for the specific language governing permissions and | ||
12 | + * limitations under the License. | ||
13 | + */ | ||
14 | +package org.onosproject.provider.snmp.device.impl; | ||
15 | + | ||
16 | +import com.btisystems.mibbler.mibs.netsnmp.netsnmp.I_Device; | ||
17 | +import com.btisystems.mibbler.mibs.netsnmp.netsnmp._OidRegistry; | ||
18 | +import com.btisystems.pronx.ems.core.model.ClassRegistry; | ||
19 | +import com.btisystems.pronx.ems.core.model.IClassRegistry; | ||
20 | +import com.btisystems.pronx.ems.core.model.NetworkDevice; | ||
21 | +import com.btisystems.pronx.ems.core.snmp.ISnmpSession; | ||
22 | +import java.io.IOException; | ||
23 | +import java.util.Arrays; | ||
24 | +import org.apache.commons.lang.StringUtils; | ||
25 | +import org.onosproject.net.device.DefaultDeviceDescription; | ||
26 | +import org.onosproject.net.device.DeviceDescription; | ||
27 | +import org.slf4j.Logger; | ||
28 | +import static org.slf4j.LoggerFactory.getLogger; | ||
29 | +import org.snmp4j.smi.OID; | ||
30 | + | ||
31 | +/** | ||
32 | + * A agent-specific implementation supporting NET-SNMP agents. | ||
33 | + */ | ||
34 | +public class NetSnmpDeviceDescriptionProvider implements SnmpDeviceDescriptionProvider { | ||
35 | + private final Logger log = getLogger(getClass()); | ||
36 | + protected static final IClassRegistry CLASS_REGISTRY = | ||
37 | + new ClassRegistry(_OidRegistry.oidRegistry, I_Device.class); | ||
38 | + private static final String UNKNOWN = "unknown"; | ||
39 | + | ||
40 | + @Override | ||
41 | + public DeviceDescription populateDescription(ISnmpSession session, DeviceDescription description) { | ||
42 | + NetworkDevice networkDevice = new NetworkDevice(CLASS_REGISTRY, | ||
43 | + session.getAddress().getHostAddress()); | ||
44 | + try { | ||
45 | + session.walkDevice(networkDevice, Arrays.asList(new OID[]{ | ||
46 | + CLASS_REGISTRY.getClassToOidMap().get( | ||
47 | + com.btisystems.mibbler.mibs.netsnmp.netsnmp.mib_2.System.class)})); | ||
48 | + | ||
49 | + com.btisystems.mibbler.mibs.netsnmp.netsnmp.mib_2.System systemTree = | ||
50 | + (com.btisystems.mibbler.mibs.netsnmp.netsnmp.mib_2.System) | ||
51 | + networkDevice.getRootObject().getEntity(CLASS_REGISTRY.getClassToOidMap().get( | ||
52 | + com.btisystems.mibbler.mibs.netsnmp.netsnmp.mib_2.System.class)); | ||
53 | + if (systemTree != null) { | ||
54 | + // TODO SNMP sys-contacts may be verbose; ONOS-GUI doesn't abbreviate fields neatly; | ||
55 | + // so cut it here until supported in prop displayer | ||
56 | + String manufacturer = StringUtils.abbreviate(systemTree.getSysContact(), 20); | ||
57 | + return new DefaultDeviceDescription(description.deviceUri(), description.type(), manufacturer, | ||
58 | + UNKNOWN, UNKNOWN, UNKNOWN, description.chassisId()); | ||
59 | + } | ||
60 | + } catch (IOException ex) { | ||
61 | + log.error("Error reading details for device {}.", session.getAddress(), ex); | ||
62 | + } | ||
63 | + return description; | ||
64 | + } | ||
65 | + | ||
66 | +} |
providers/snmp/device/src/main/java/org/onosproject/provider/snmp/device/impl/SnmpDevice.java
0 → 100644
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.provider.snmp.device.impl; | ||
17 | + | ||
18 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
19 | +import static org.slf4j.LoggerFactory.getLogger; | ||
20 | + | ||
21 | + | ||
22 | +import org.slf4j.Logger; | ||
23 | + | ||
24 | +/** | ||
25 | + * This is a logical representation of actual SNMP device, carrying all the necessary information to connect and execute | ||
26 | + * SNMP operations. | ||
27 | + */ | ||
28 | +public class SnmpDevice { | ||
29 | + | ||
30 | + private final Logger log = getLogger(SnmpDevice.class); | ||
31 | + | ||
32 | + | ||
33 | + private static final int DEFAULT_SNMP_PORT = 161; | ||
34 | + | ||
35 | + private final String snmpHost; | ||
36 | + private int snmpPort = DEFAULT_SNMP_PORT; | ||
37 | + private final String community; | ||
38 | + private boolean reachable = false; | ||
39 | + | ||
40 | + private DeviceState deviceState = DeviceState.INVALID; | ||
41 | + | ||
42 | + protected SnmpDevice(String snmpHost, int snmpPort, String community) { | ||
43 | + | ||
44 | + this.snmpHost = checkNotNull(snmpHost, "SNMP Device IP cannot be null"); | ||
45 | + this.snmpPort = checkNotNull(snmpPort, "SNMP Device snmp port cannot be null"); | ||
46 | + this.community = community; | ||
47 | + } | ||
48 | + | ||
49 | + /** | ||
50 | + * This will try to connect to SNMP device. | ||
51 | + * | ||
52 | + */ | ||
53 | + public void init() { | ||
54 | + | ||
55 | + reachable = true; | ||
56 | + } | ||
57 | + | ||
58 | + /** | ||
59 | + * This would return host IP and host Port, used by this particular SNMP Device. | ||
60 | + * | ||
61 | + * @return Device Information. | ||
62 | + */ | ||
63 | + public String deviceInfo() { | ||
64 | + return new StringBuilder("host: ").append(snmpHost).append(". port: ") | ||
65 | + .append(snmpPort).toString(); | ||
66 | + } | ||
67 | + | ||
68 | + /** | ||
69 | + * This will terminate the device connection. | ||
70 | + */ | ||
71 | + public void disconnect() { | ||
72 | + log.info("disconnect"); | ||
73 | + reachable = false; | ||
74 | + } | ||
75 | + | ||
76 | + /** | ||
77 | + * This api is intended to know whether the device is connected or not. | ||
78 | + * | ||
79 | + * @return true if connected | ||
80 | + */ | ||
81 | + public boolean isReachable() { | ||
82 | + return reachable; | ||
83 | + } | ||
84 | + | ||
85 | + /** | ||
86 | + * This will return the IP used connect ssh on the device. | ||
87 | + * | ||
88 | + * @return SNMP Device IP | ||
89 | + */ | ||
90 | + public String getSnmpHost() { | ||
91 | + return snmpHost; | ||
92 | + } | ||
93 | + | ||
94 | + /** | ||
95 | + * This will return the SSH Port used connect the device. | ||
96 | + * | ||
97 | + * @return SSH Port number | ||
98 | + */ | ||
99 | + public int getSnmpPort() { | ||
100 | + return snmpPort; | ||
101 | + } | ||
102 | + | ||
103 | + public String getCommunity() { | ||
104 | + return community; | ||
105 | + } | ||
106 | + | ||
107 | + /** | ||
108 | + * Retrieve current state of the device. | ||
109 | + * | ||
110 | + * @return Current Device State | ||
111 | + */ | ||
112 | + public DeviceState getDeviceState() { | ||
113 | + return deviceState; | ||
114 | + } | ||
115 | + | ||
116 | + /** | ||
117 | + * This is set the state information for the device. | ||
118 | + * | ||
119 | + * @param deviceState Next Device State | ||
120 | + */ | ||
121 | + public void setDeviceState(DeviceState deviceState) { | ||
122 | + this.deviceState = deviceState; | ||
123 | + } | ||
124 | + | ||
125 | + /** | ||
126 | + * Check whether the device is in Active state. | ||
127 | + * | ||
128 | + * @return true if the device is Active | ||
129 | + */ | ||
130 | + public boolean isActive() { | ||
131 | + return deviceState == DeviceState.ACTIVE; | ||
132 | + } | ||
133 | + | ||
134 | +} |
1 | +/* | ||
2 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
3 | + * you may not use this file except in compliance with the License. | ||
4 | + * You may obtain a copy of the License at | ||
5 | + * | ||
6 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
7 | + * | ||
8 | + * Unless required by applicable law or agreed to in writing, software | ||
9 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
10 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
11 | + * See the License for the specific language governing permissions and | ||
12 | + * limitations under the License. | ||
13 | + */ | ||
14 | +package org.onosproject.provider.snmp.device.impl; | ||
15 | + | ||
16 | +import com.btisystems.pronx.ems.core.snmp.ISnmpSession; | ||
17 | +import org.onosproject.net.device.DeviceDescription; | ||
18 | + | ||
19 | +/** | ||
20 | + * Abstraction of an entity which updates a device description with information retrieved via SNMP. | ||
21 | + */ | ||
22 | +public interface SnmpDeviceDescriptionProvider { | ||
23 | + | ||
24 | + /** | ||
25 | + * Generated an updated device description. | ||
26 | + * | ||
27 | + * @param session SNMP session | ||
28 | + * @param description old device description | ||
29 | + * @return new updated description | ||
30 | + */ | ||
31 | + DeviceDescription populateDescription(ISnmpSession session, DeviceDescription description); | ||
32 | + | ||
33 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.provider.snmp.device.impl; | ||
17 | + | ||
18 | +import com.btisystems.pronx.ems.core.snmp.DefaultSnmpConfigurationFactory; | ||
19 | +import com.btisystems.pronx.ems.core.snmp.ISnmpConfiguration; | ||
20 | +import com.btisystems.pronx.ems.core.snmp.ISnmpConfigurationFactory; | ||
21 | +import com.btisystems.pronx.ems.core.snmp.ISnmpSession; | ||
22 | +import com.btisystems.pronx.ems.core.snmp.ISnmpSessionFactory; | ||
23 | +import com.btisystems.pronx.ems.core.snmp.SnmpSessionFactory; | ||
24 | +import com.btisystems.pronx.ems.core.snmp.V2cSnmpConfiguration; | ||
25 | +import static com.google.common.base.Strings.isNullOrEmpty; | ||
26 | +import java.io.IOException; | ||
27 | +import static org.onlab.util.Tools.delay; | ||
28 | +import static org.onlab.util.Tools.get; | ||
29 | +import static org.onlab.util.Tools.groupedThreads; | ||
30 | +import static org.slf4j.LoggerFactory.getLogger; | ||
31 | + | ||
32 | +import java.net.URI; | ||
33 | +import java.net.URISyntaxException; | ||
34 | +import java.util.Dictionary; | ||
35 | +import java.util.HashMap; | ||
36 | +import java.util.Map; | ||
37 | +import java.util.concurrent.ConcurrentHashMap; | ||
38 | +import java.util.concurrent.ExecutorService; | ||
39 | +import java.util.concurrent.Executors; | ||
40 | +import java.util.concurrent.TimeUnit; | ||
41 | + | ||
42 | +import org.apache.felix.scr.annotations.Activate; | ||
43 | +import org.apache.felix.scr.annotations.Component; | ||
44 | +import org.apache.felix.scr.annotations.Deactivate; | ||
45 | +import org.apache.felix.scr.annotations.Modified; | ||
46 | +import org.apache.felix.scr.annotations.Property; | ||
47 | +import org.apache.felix.scr.annotations.Reference; | ||
48 | +import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
49 | +import org.onlab.packet.ChassisId; | ||
50 | +import org.onosproject.cfg.ComponentConfigService; | ||
51 | +import org.onosproject.cluster.ClusterService; | ||
52 | +import org.onosproject.net.Device; | ||
53 | +import org.onosproject.net.DeviceId; | ||
54 | +import org.onosproject.net.MastershipRole; | ||
55 | +import org.onosproject.net.device.DefaultDeviceDescription; | ||
56 | +import org.onosproject.net.device.DeviceDescription; | ||
57 | +import org.onosproject.net.device.DeviceProvider; | ||
58 | +import org.onosproject.net.device.DeviceProviderRegistry; | ||
59 | +import org.onosproject.net.device.DeviceProviderService; | ||
60 | +import org.onosproject.net.device.DeviceService; | ||
61 | +import org.onosproject.net.provider.AbstractProvider; | ||
62 | +import org.onosproject.net.provider.ProviderId; | ||
63 | +import org.osgi.service.component.ComponentContext; | ||
64 | +import org.slf4j.Logger; | ||
65 | + | ||
66 | +/** | ||
67 | + * Provider which will try to fetch the details of SNMP devices from the core and run a capability discovery on each of | ||
68 | + * the device. | ||
69 | + */ | ||
70 | +@Component(immediate = true) | ||
71 | +public class SnmpDeviceProvider extends AbstractProvider | ||
72 | + implements DeviceProvider { | ||
73 | + | ||
74 | + private final Logger log = getLogger(SnmpDeviceProvider.class); | ||
75 | + | ||
76 | + private static final String UNKNOWN = "unknown"; | ||
77 | + | ||
78 | + protected Map<DeviceId, SnmpDevice> snmpDeviceMap = new ConcurrentHashMap<>(); | ||
79 | + | ||
80 | + private DeviceProviderService providerService; | ||
81 | + | ||
82 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
83 | + protected DeviceProviderRegistry providerRegistry; | ||
84 | + | ||
85 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
86 | + protected DeviceService deviceService; | ||
87 | + | ||
88 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
89 | + protected ClusterService clusterService; | ||
90 | + | ||
91 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
92 | + protected ComponentConfigService cfgService; | ||
93 | + | ||
94 | + private final ExecutorService deviceBuilder = Executors | ||
95 | + .newFixedThreadPool(1, groupedThreads("onos/snmp", "device-creator")); | ||
96 | + | ||
97 | + // Delay between events in ms. | ||
98 | + private static final int EVENTINTERVAL = 5; | ||
99 | + | ||
100 | + private static final String SCHEME = "snmp"; | ||
101 | + | ||
102 | + @Property(name = "devConfigs", value = "", label = "Instance-specific configurations") | ||
103 | + private String devConfigs = null; | ||
104 | + | ||
105 | + @Property(name = "devPasswords", value = "", label = "Instance-specific password") | ||
106 | + private String devPasswords = null; | ||
107 | + | ||
108 | + //TODO Could be replaced with a service lookup, and bundles per device variant. | ||
109 | + Map<String, SnmpDeviceDescriptionProvider> providers = new HashMap<>(); | ||
110 | + | ||
111 | + private final ISnmpSessionFactory sessionFactory; | ||
112 | + | ||
113 | + /** | ||
114 | + * Creates a provider with the supplier identifier. | ||
115 | + */ | ||
116 | + public SnmpDeviceProvider() { | ||
117 | + super(new ProviderId("snmp", "org.onosproject.provider.device")); | ||
118 | + sessionFactory = new SnmpSessionFactory( | ||
119 | + new DefaultSnmpConfigurationFactory(new V2cSnmpConfiguration())); | ||
120 | + providers.put("1.3.6.1.4.1.18070.2.2", new Bti7000DeviceDescriptionProvider()); | ||
121 | + providers.put("1.3.6.1.4.1.20408", new NetSnmpDeviceDescriptionProvider()); | ||
122 | + } | ||
123 | + | ||
124 | + @Activate | ||
125 | + public void activate(ComponentContext context) { | ||
126 | + log.info("activating for snmp devices ..."); | ||
127 | + cfgService.registerProperties(getClass()); | ||
128 | + providerService = providerRegistry.register(this); | ||
129 | + modified(context); | ||
130 | + log.info("activated ok"); | ||
131 | + } | ||
132 | + | ||
133 | + @Deactivate | ||
134 | + public void deactivate(ComponentContext context) { | ||
135 | + | ||
136 | + log.info("deactivating for snmp devices ..."); | ||
137 | + | ||
138 | + cfgService.unregisterProperties(getClass(), false); | ||
139 | + try { | ||
140 | + snmpDeviceMap | ||
141 | + .entrySet().stream().forEach((deviceEntry) -> { | ||
142 | + deviceBuilder.submit(new DeviceCreator(deviceEntry.getValue(), false)); | ||
143 | + }); | ||
144 | + deviceBuilder.awaitTermination(1000, TimeUnit.MILLISECONDS); | ||
145 | + } catch (InterruptedException e) { | ||
146 | + log.error("Device builder did not terminate"); | ||
147 | + } | ||
148 | + deviceBuilder.shutdownNow(); | ||
149 | + snmpDeviceMap.clear(); | ||
150 | + providerRegistry.unregister(this); | ||
151 | + providerService = null; | ||
152 | + log.info("Stopped"); | ||
153 | + } | ||
154 | + | ||
155 | + @Modified | ||
156 | + public void modified(ComponentContext context) { | ||
157 | + log.info("modified ..."); | ||
158 | + | ||
159 | + if (context == null) { | ||
160 | + log.info("No configuration file"); | ||
161 | + return; | ||
162 | + } | ||
163 | + Dictionary<?, ?> properties = context.getProperties(); | ||
164 | + | ||
165 | + log.info("properties={}", context.getProperties()); | ||
166 | + | ||
167 | + String deviceCfgValue = get(properties, "devConfigs"); | ||
168 | + log.info("Settings: devConfigs={}", deviceCfgValue); | ||
169 | + if (!isNullOrEmpty(deviceCfgValue)) { | ||
170 | + addOrRemoveDevicesConfig(deviceCfgValue); | ||
171 | + } | ||
172 | + log.info("... modified"); | ||
173 | + | ||
174 | + } | ||
175 | + | ||
176 | + private void addOrRemoveDevicesConfig(String deviceConfig) { | ||
177 | + for (String deviceEntry : deviceConfig.split(",")) { | ||
178 | + SnmpDevice device = processDeviceEntry(deviceEntry); | ||
179 | + if (device != null) { | ||
180 | + log.info("Device Detail:host={}, port={}, state={}", | ||
181 | + new Object[]{device.getSnmpHost(), | ||
182 | + device.getSnmpPort(), | ||
183 | + device.getDeviceState().name()} | ||
184 | + ); | ||
185 | + if (device.isActive()) { | ||
186 | + deviceBuilder.submit(new DeviceCreator(device, true)); | ||
187 | + } else { | ||
188 | + deviceBuilder.submit(new DeviceCreator(device, false)); | ||
189 | + } | ||
190 | + } | ||
191 | + } | ||
192 | + } | ||
193 | + | ||
194 | + private SnmpDevice processDeviceEntry(String deviceEntry) { | ||
195 | + if (deviceEntry == null) { | ||
196 | + log.info("No content for Device Entry, so cannot proceed further."); | ||
197 | + return null; | ||
198 | + } | ||
199 | + log.info("Trying to convert {} to a SNMP Device Object", deviceEntry); | ||
200 | + SnmpDevice device = null; | ||
201 | + try { | ||
202 | + String userInfo = deviceEntry.substring(0, deviceEntry | ||
203 | + .lastIndexOf('@')); | ||
204 | + String hostInfo = deviceEntry.substring(deviceEntry | ||
205 | + .lastIndexOf('@') + 1); | ||
206 | + String[] infoSplit = userInfo.split(":"); | ||
207 | + String username = infoSplit[0]; | ||
208 | + String password = infoSplit[1]; | ||
209 | + infoSplit = hostInfo.split(":"); | ||
210 | + String hostIp = infoSplit[0]; | ||
211 | + Integer hostPort; | ||
212 | + try { | ||
213 | + hostPort = Integer.parseInt(infoSplit[1]); | ||
214 | + } catch (NumberFormatException nfe) { | ||
215 | + log.error("Bad Configuration Data: Failed to parse host port number string: " | ||
216 | + + infoSplit[1]); | ||
217 | + throw nfe; | ||
218 | + } | ||
219 | + String deviceState = infoSplit[2]; | ||
220 | + if (isNullOrEmpty(username) || isNullOrEmpty(password) | ||
221 | + || isNullOrEmpty(hostIp) || hostPort == 0) { | ||
222 | + log.warn("Bad Configuration Data: both user and device information parts of Configuration " | ||
223 | + + deviceEntry + " should be non-nullable"); | ||
224 | + } else { | ||
225 | + device = new SnmpDevice(hostIp, hostPort, password); | ||
226 | + if (!isNullOrEmpty(deviceState)) { | ||
227 | + if (deviceState.toUpperCase().equals(DeviceState.ACTIVE.name())) { | ||
228 | + device.setDeviceState(DeviceState.ACTIVE); | ||
229 | + } else if (deviceState.toUpperCase() | ||
230 | + .equals(DeviceState.INACTIVE.name())) { | ||
231 | + device.setDeviceState(DeviceState.INACTIVE); | ||
232 | + } else { | ||
233 | + log.warn("Device State Information can not be empty, so marking the state as INVALID"); | ||
234 | + device.setDeviceState(DeviceState.INVALID); | ||
235 | + } | ||
236 | + } else { | ||
237 | + log.warn("The device entry do not specify state information, so marking the state as INVALID"); | ||
238 | + device.setDeviceState(DeviceState.INVALID); | ||
239 | + } | ||
240 | + } | ||
241 | + } catch (ArrayIndexOutOfBoundsException aie) { | ||
242 | + log.error("Error while reading config infromation from the config file: " | ||
243 | + + "The user, host and device state infomation should be " | ||
244 | + + "in the order 'userInfo@hostInfo:deviceState'" | ||
245 | + + deviceEntry, aie); | ||
246 | + } catch (Exception e) { | ||
247 | + log.error("Error while parsing config information for the device entry: " | ||
248 | + + deviceEntry, e); | ||
249 | + } | ||
250 | + return device; | ||
251 | + } | ||
252 | + | ||
253 | + @Override | ||
254 | + public void triggerProbe(DeviceId deviceId) { | ||
255 | + // TODO SNMP devices should be polled at scheduled intervals to retrieve their | ||
256 | + // reachability status and other details e.g.swVersion, serialNumber,chassis, | ||
257 | + } | ||
258 | + | ||
259 | + @Override | ||
260 | + public void roleChanged(DeviceId deviceId, MastershipRole newRole) { | ||
261 | + | ||
262 | + } | ||
263 | + | ||
264 | + @Override | ||
265 | + public boolean isReachable(DeviceId deviceId) { | ||
266 | + SnmpDevice snmpDevice = snmpDeviceMap.get(deviceId); | ||
267 | + if (snmpDevice == null) { | ||
268 | + log.warn("BAD REQUEST: the requested device id: " | ||
269 | + + deviceId.toString() | ||
270 | + + " is not associated to any SNMP Device"); | ||
271 | + return false; | ||
272 | + } | ||
273 | + return snmpDevice.isReachable(); | ||
274 | + } | ||
275 | + | ||
276 | + /** | ||
277 | + * This class is intended to add or remove Configured SNMP Devices. Functionality relies on 'createFlag' and | ||
278 | + * 'SnmpDevice' content. The functionality runs as a thread and depending on the 'createFlag' value it will create | ||
279 | + * or remove Device entry from the core. | ||
280 | + */ | ||
281 | + private class DeviceCreator implements Runnable { | ||
282 | + | ||
283 | + private SnmpDevice device; | ||
284 | + private boolean createFlag; | ||
285 | + | ||
286 | + public DeviceCreator(SnmpDevice device, boolean createFlag) { | ||
287 | + this.device = device; | ||
288 | + this.createFlag = createFlag; | ||
289 | + } | ||
290 | + | ||
291 | + @Override | ||
292 | + public void run() { | ||
293 | + if (createFlag) { | ||
294 | + log.info("Trying to create Device Info on ONOS core"); | ||
295 | + advertiseDevices(); | ||
296 | + } else { | ||
297 | + log.info("Trying to remove Device Info on ONOS core"); | ||
298 | + removeDevices(); | ||
299 | + } | ||
300 | + } | ||
301 | + | ||
302 | + /** | ||
303 | + * For each SNMP Device, remove the entry from the device store. | ||
304 | + */ | ||
305 | + private void removeDevices() { | ||
306 | + if (device == null) { | ||
307 | + log.warn("The Request SNMP Device is null, cannot proceed further"); | ||
308 | + return; | ||
309 | + } | ||
310 | + try { | ||
311 | + DeviceId did = getDeviceId(); | ||
312 | + if (!snmpDeviceMap.containsKey(did)) { | ||
313 | + log.error("BAD Request: 'Currently device is not discovered, " | ||
314 | + + "so cannot remove/disconnect the device: " | ||
315 | + + device.deviceInfo() + "'"); | ||
316 | + return; | ||
317 | + } | ||
318 | + providerService.deviceDisconnected(did); | ||
319 | + device.disconnect(); | ||
320 | + snmpDeviceMap.remove(did); | ||
321 | + delay(EVENTINTERVAL); | ||
322 | + } catch (URISyntaxException uriSyntaxExcpetion) { | ||
323 | + log.error("Syntax Error while creating URI for the device: " | ||
324 | + + device.deviceInfo() | ||
325 | + + " couldn't remove the device from the store", | ||
326 | + uriSyntaxExcpetion); | ||
327 | + } | ||
328 | + } | ||
329 | + | ||
330 | + /** | ||
331 | + * Initialize SNMP Device object, and notify core saying device connected. | ||
332 | + */ | ||
333 | + private void advertiseDevices() { | ||
334 | + try { | ||
335 | + if (device == null) { | ||
336 | + log.warn("The Request SNMP Device is null, cannot proceed further"); | ||
337 | + return; | ||
338 | + } | ||
339 | + device.init(); | ||
340 | + DeviceId did = getDeviceId(); | ||
341 | + ChassisId cid = new ChassisId(); | ||
342 | + | ||
343 | + | ||
344 | + DeviceDescription desc = new DefaultDeviceDescription( | ||
345 | + did.uri(), Device.Type.OTHER, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, cid); | ||
346 | + | ||
347 | + desc = populateDescriptionFromDevice(did, desc); | ||
348 | + | ||
349 | + log.info("Persisting Device " + did.uri().toString()); | ||
350 | + | ||
351 | + snmpDeviceMap.put(did, device); | ||
352 | + providerService.deviceConnected(did, desc); | ||
353 | + log.info("Done with Device Info Creation on ONOS core. Device Info: " | ||
354 | + + device.deviceInfo() + " " + did.uri().toString()); | ||
355 | + delay(EVENTINTERVAL); | ||
356 | + } catch (URISyntaxException e) { | ||
357 | + log.error("Syntax Error while creating URI for the device: " | ||
358 | + + device.deviceInfo() | ||
359 | + + " couldn't persist the device onto the store", e); | ||
360 | + } catch (Exception e) { | ||
361 | + log.error("Error while initializing session for the device: " | ||
362 | + + (device != null ? device.deviceInfo() : null), e); | ||
363 | + } | ||
364 | + } | ||
365 | + | ||
366 | + private DeviceDescription populateDescriptionFromDevice(DeviceId did, DeviceDescription desc) { | ||
367 | + String[] deviceComponents = did.toString().split(":"); | ||
368 | + if (deviceComponents.length > 1) { | ||
369 | + String ipAddress = deviceComponents[1]; | ||
370 | + String port = deviceComponents[2]; | ||
371 | + | ||
372 | + ISnmpConfiguration config = new V2cSnmpConfiguration(); | ||
373 | + config.setPort(Integer.parseInt(port)); | ||
374 | + | ||
375 | + try (ISnmpSession session = sessionFactory.createSession(config, ipAddress)) { | ||
376 | + // Each session will be auto-closed. | ||
377 | + String deviceOID = session.identifyDevice(); | ||
378 | + | ||
379 | + if (providers.containsKey(deviceOID)) { | ||
380 | + desc = providers.get(deviceOID).populateDescription(session, desc); | ||
381 | + } | ||
382 | + | ||
383 | + } catch (IOException | RuntimeException ex) { | ||
384 | + log.error("Failed to walk device.", ex.getMessage()); | ||
385 | + log.debug("Detailed problem was ", ex); | ||
386 | + } | ||
387 | + } | ||
388 | + return desc; | ||
389 | + } | ||
390 | + | ||
391 | + /** | ||
392 | + * This will build a device id for the device. | ||
393 | + */ | ||
394 | + private DeviceId getDeviceId() throws URISyntaxException { | ||
395 | + String additionalSSP = new StringBuilder( | ||
396 | + device.getSnmpHost()).append(":") | ||
397 | + .append(device.getSnmpPort()).toString(); | ||
398 | + return DeviceId.deviceId(new URI(SCHEME, additionalSSP, | ||
399 | + null)); | ||
400 | + } | ||
401 | + } | ||
402 | + | ||
403 | + protected ISnmpSessionFactory getSessionFactory(ISnmpConfigurationFactory configurationFactory) { | ||
404 | + return new SnmpSessionFactory(configurationFactory); | ||
405 | + } | ||
406 | +} |
providers/snmp/device/src/main/java/org/onosproject/provider/snmp/device/impl/package-info.java
0 → 100644
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +/** | ||
18 | + * Provider that uses SNMP capability request as a means of infrastructure device discovery. | ||
19 | + */ | ||
20 | +package org.onosproject.provider.snmp.device.impl; | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | <?xml version="1.0" encoding="UTF-8"?> | 1 | <?xml version="1.0" encoding="UTF-8"?> |
2 | <!-- | 2 | <!-- |
3 | - ~ Copyright 2014 Open Networking Laboratory | 3 | + ~ Copyright 2015 Open Networking Laboratory |
4 | ~ | 4 | ~ |
5 | ~ Licensed under the Apache License, Version 2.0 (the "License"); | 5 | ~ Licensed under the Apache License, Version 2.0 (the "License"); |
6 | ~ you may not use this file except in compliance with the License. | 6 | ~ you may not use this file except in compliance with the License. |
... | @@ -29,10 +29,55 @@ | ... | @@ -29,10 +29,55 @@ |
29 | <artifactId>onos-snmp-providers</artifactId> | 29 | <artifactId>onos-snmp-providers</artifactId> |
30 | <packaging>pom</packaging> | 30 | <packaging>pom</packaging> |
31 | 31 | ||
32 | - <description>ONOS SNMP Protocol Adapters</description> | 32 | + <description>ONOS SNMP protocol adapters</description> |
33 | 33 | ||
34 | <modules> | 34 | <modules> |
35 | + <module>device</module> | ||
36 | + <module>app</module> | ||
35 | <module>alarm</module> | 37 | <module>alarm</module> |
36 | </modules> | 38 | </modules> |
37 | 39 | ||
40 | + <dependencies> | ||
41 | + <dependency> | ||
42 | + <groupId>org.apache.servicemix.bundles</groupId> | ||
43 | + <artifactId>org.apache.servicemix.bundles.snmp4j</artifactId> | ||
44 | + <version>2.3.4_1</version> | ||
45 | + <exclusions> | ||
46 | + <exclusion> | ||
47 | + <artifactId>log4j</artifactId> | ||
48 | + <groupId>log4j</groupId> | ||
49 | + </exclusion> | ||
50 | + </exclusions> | ||
51 | + </dependency> | ||
52 | + | ||
53 | + <dependency> | ||
54 | + <groupId>com.btisystems</groupId> | ||
55 | + <artifactId>snmp-core</artifactId> | ||
56 | + <version>1.3-SNAPSHOT</version> | ||
57 | + </dependency> | ||
58 | + | ||
59 | + <dependency> | ||
60 | + <groupId>com.btisystems.mibbler.mibs</groupId> | ||
61 | + <artifactId>bti7000</artifactId> | ||
62 | + <version>1.0-SNAPSHOT</version> | ||
63 | + </dependency> | ||
64 | + | ||
65 | + <dependency> | ||
66 | + <groupId>com.btisystems.mibbler.mibs</groupId> | ||
67 | + <artifactId>net-snmp</artifactId> | ||
68 | + <version>1.0-SNAPSHOT</version> | ||
69 | + </dependency> | ||
70 | + </dependencies> | ||
71 | + <repositories> | ||
72 | + <repository> | ||
73 | + <!-- TODO move over to release snmp-core when it becomes available.--> | ||
74 | + <id>oss.sonatype.org-snapshot</id> | ||
75 | + <url>http://oss.sonatype.org/content/repositories/snapshots</url> | ||
76 | + <snapshots> | ||
77 | + <enabled>true</enabled> | ||
78 | + </snapshots> | ||
79 | + </repository> | ||
80 | + </repositories> | ||
81 | + | ||
82 | + | ||
38 | </project> | 83 | </project> | ... | ... |
tools/package/etc/samples/org.onosproject.provider.snmp.device.impl.SnmpDeviceProvider.cfg
0 → 100644
1 | +# | ||
2 | +# devices which support SNMP, these may support SNMP fault-management. | ||
3 | +# demo.snmplabs.com is a publically available SNMP agent-simulator accessible via the internet, see http://snmpsim.sourceforge.net/public-snmp-simulator.html | ||
4 | +# | ||
5 | +devConfigs = bti7000:public@172.27.7.109:161:active,net-snmp:public@demo.snmplabs.com:161:active,net-snmp:public@demo.snmplabs.com:1161:active,net-snmp:public@demo.snmplabs.com:2161:active,net-snmp:public@demo.snmplabs.com:3161:active |
-
Please register or login to post a comment