CHANGE 1:
Patch to show API for Alarms in Fault Management.
AlarmsWebResource.java & Alarm.java show what the external REST API for alarms would look like.
See more info at https://wiki.onosproject.org/display/ONOS/Fault+Management
Everything else is very early and work-in-progress/mostly just stubbed out, and not ready for review but all advice welcome.

CHANGE 2:
[ONOS-3203] Update re. comments on FM API draft.
Comments were from Thomas Vachuska regarding https://gerrit.onosproject.org/#/c/6180/
Change-Id: If8d330d1b18b503e89849587e2d4388bf67becc0
diff --git a/apps/faultmanagement/fmweb/src/main/java/org/onosproject/faultmanagement/web/AlarmCodec.java b/apps/faultmanagement/fmweb/src/main/java/org/onosproject/faultmanagement/web/AlarmCodec.java
new file mode 100644
index 0000000..a764c90
--- /dev/null
+++ b/apps/faultmanagement/fmweb/src/main/java/org/onosproject/faultmanagement/web/AlarmCodec.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.faultmanagement.web;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import org.onosproject.net.DeviceId;
+import org.onosproject.incubator.net.faultmanagement.alarm.Alarm;
+import org.onosproject.incubator.net.faultmanagement.alarm.AlarmEntityId;
+import org.onosproject.incubator.net.faultmanagement.alarm.AlarmId;
+import org.onosproject.incubator.net.faultmanagement.alarm.DefaultAlarm;
+import org.slf4j.Logger;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Implementation of encoder for Alarm codec.
+ */
+public final class AlarmCodec extends JsonCodec<Alarm> {
+
+    private final Logger log = getLogger(getClass());
+
+    @Override
+    public ObjectNode encode(final Alarm alarm, final CodecContext context) {
+        checkNotNull(alarm, "Alarm cannot be null");
+
+        return context.mapper().createObjectNode()
+                .put("id", alarm.id().fingerprint())
+                .put("deviceId", alarm.deviceId().toString())
+                .put("description", alarm.description())
+                .put("source",
+                        alarm.source() == null ? null
+                                : alarm.source().toString())
+                .put("timeRaised", alarm.timeRaised())
+                .put("timeUpdated", alarm.timeUpdated())
+                .put("timeCleared", alarm.timeCleared())
+                .put("severity", alarm.severity().toString())
+                .put("serviceAffecting", alarm.serviceAffecting())
+                .put("acknowledged", alarm.acknowledged())
+                .put("manuallyClearable", alarm.manuallyClearable())
+                .put("assignedUser", alarm.assignedUser());
+
+    }
+
+    @Override
+    public Alarm decode(final ObjectNode json, final CodecContext context) {
+        if (json == null || !json.isObject()) {
+            return null;
+        }
+
+        log.debug("id={}, full json={} ", json.get("id"), json);
+        final Long id = json.get("id").asLong();
+
+        final DeviceId deviceId = DeviceId.deviceId(json.get("deviceId").asText());
+        final String description = json.get("description").asText();
+        final Long timeRaised = json.get("timeRaised").asLong();
+        final Long timeUpdated = json.get("timeUpdated").asLong();
+
+        final JsonNode jsonTimeCleared = json.get("timeCleared");
+        final Long timeCleared = jsonTimeCleared == null || jsonTimeCleared.isNull() ? null : jsonTimeCleared.asLong();
+
+        final Alarm.SeverityLevel severity
+                = Alarm.SeverityLevel.valueOf(json.get("severity").asText().toUpperCase());
+
+        final Boolean serviceAffecting = json.get("serviceAffecting").asBoolean();
+        final Boolean acknowledged = json.get("acknowledged").asBoolean();
+        final Boolean manuallyClearable = json.get("manuallyClearable").asBoolean();
+
+        final JsonNode jsonAssignedUser = json.get("assignedUser");
+        final String assignedUser
+                = jsonAssignedUser == null || jsonAssignedUser.isNull() ? null : jsonAssignedUser.asText();
+
+        return new DefaultAlarm.Builder(
+                AlarmId.valueOf(id), deviceId, description, severity, timeRaised).forSource(AlarmEntityId.NONE).
+                withTimeUpdated(timeUpdated).
+                withTimeCleared(timeCleared).
+                withServiceAffecting(serviceAffecting).
+                withAcknowledged(acknowledged).
+                withManuallyClearable(manuallyClearable).
+                withAssignedUser(assignedUser).
+                build();
+
+    }
+}
diff --git a/apps/faultmanagement/fmweb/src/main/java/org/onosproject/faultmanagement/web/AlarmsWebResource.java b/apps/faultmanagement/fmweb/src/main/java/org/onosproject/faultmanagement/web/AlarmsWebResource.java
new file mode 100644
index 0000000..56c891c
--- /dev/null
+++ b/apps/faultmanagement/fmweb/src/main/java/org/onosproject/faultmanagement/web/AlarmsWebResource.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.faultmanagement.web;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import java.io.InputStream;
+import org.onosproject.rest.AbstractWebResource;
+
+import javax.ws.rs.core.Response;
+import org.onosproject.incubator.net.faultmanagement.alarm.Alarm;
+import org.onosproject.incubator.net.faultmanagement.alarm.AlarmId;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import org.onosproject.codec.CodecService;
+import org.onosproject.incubator.net.faultmanagement.alarm.AlarmService;
+import org.slf4j.Logger;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Alarms on devices or ONOS.
+ */
+@Path("alarms")
+public class AlarmsWebResource extends AbstractWebResource {
+
+    public static final String ALARM_NOT_FOUND = "Alarm is not found";
+
+    private final Logger log = getLogger(getClass());
+
+    public AlarmsWebResource() {
+        get(CodecService.class).registerCodec(Alarm.class, new AlarmCodec());
+    }
+
+    /**
+     * Get all alarms. Returns a list of all alarms across all devices.
+     *
+     * @param includeCleared include recently cleared alarms in response
+     * @return JSON encoded set of alarms
+     */
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response getAlarms(@DefaultValue("false") @QueryParam("includeCleared") final boolean includeCleared
+    ) {
+
+        log.info("Requesting all alarms, includeCleared={}", includeCleared);
+        final AlarmService service = get(AlarmService.class);
+
+        final Iterable<Alarm> alarms = includeCleared
+                ? service.getAlarms()
+                : service.getActiveAlarms();
+
+        final ObjectNode result = new ObjectMapper().createObjectNode();
+        result.set("alarms",
+                codec(Alarm.class).
+                encode(alarms, this));
+        return ok(result.toString()).build();
+
+    }
+
+    /**
+     * Get specified alarm. Returns details of the specified alarm.
+     *
+     * @param id ONOS allocated identifier
+     * @return JSON encoded alarm
+     */
+    @GET
+    @Path("{id}")
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response getAlarm(@PathParam("id") final String id) {
+        log.info("HTTP GET alarm for id={}", id);
+
+        final AlarmId alarmId = toAlarmId(id);
+        final Alarm alarm = get(AlarmService.class).getAlarm(alarmId);
+
+        final ObjectNode result = mapper().createObjectNode();
+        result.set("alarm", codec(Alarm.class).encode(alarm, this));
+        return ok(result.toString()).build();
+    }
+
+    /**
+     * Update book-keeping fields on the alarm. Returns an up-to-date version of the alarm. Some of its fields may have
+     * been updated since the REST client last retrieved the alarm being updated.
+     *
+     * @param alarmIdPath
+     * @param stream input JSON
+     * @return updated JSON encoded alarm
+     */
+    @PUT
+    @Path("{alarm_id}")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response update(@PathParam("alarm_id") final String alarmIdPath, final InputStream stream) {
+        log.info("PUT NEW ALARM at /{}", alarmIdPath);
+
+        try {
+            final ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+            log.info("jsonTree={}", jsonTree);
+
+            final Alarm alarm = codec(Alarm.class).decode(jsonTree, this);
+
+            final AlarmService service = get(AlarmService.class);
+
+            if (Long.parseLong(alarmIdPath) != alarm.id().fingerprint()) {
+                throw new IllegalArgumentException("id in path is " + Long.parseLong(alarmIdPath)
+                        + " but payload uses id=" + alarm.id().fingerprint());
+
+            }
+            final Alarm updated = service.update(alarm);
+            final ObjectNode encoded = new AlarmCodec().encode(updated, this);
+            return ok(encoded.toString()).build();
+
+        } catch (IOException ioe) {
+            throw new IllegalArgumentException(ioe);
+        }
+    }
+
+    private static AlarmId toAlarmId(final String id) {
+        try {
+            return AlarmId.valueOf(Long.parseLong(id));
+        } catch (NumberFormatException ex) {
+            throw new IllegalArgumentException("Alarm id should be numeric", ex);
+        }
+
+    }
+
+}
diff --git a/apps/faultmanagement/fmweb/src/main/java/org/onosproject/faultmanagement/web/package-info.java b/apps/faultmanagement/fmweb/src/main/java/org/onosproject/faultmanagement/web/package-info.java
new file mode 100644
index 0000000..9c29123
--- /dev/null
+++ b/apps/faultmanagement/fmweb/src/main/java/org/onosproject/faultmanagement/web/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Fault management web support.
+ */
+package org.onosproject.faultmanagement.web;