use of org.eclipse.hono.service.management.device.DeviceStatus in project hono by eclipse.
the class AbstractAutoProvisioningEventSender method updateAutoProvisioningNotificationSent.
/**
* Update the device registration information that the auto-provisioning notification has been successfully sent.
*
* @param tenantId The tenant identifier.
* @param deviceId The edge device identifier.
* @param device The edge device registration information.
* @param deviceVersion The version of the device registration information to check before update,
* may be {@link Optional#empty()}.
* @param span The span to be used for tracing this operation.
* @return A future indicating the outcome of the operation.
* @throws NullPointerException if any of the parameters are {@code null}.
*/
protected Future<Void> updateAutoProvisioningNotificationSent(final String tenantId, final String deviceId, final Device device, final Optional<String> deviceVersion, final Span span) {
Objects.requireNonNull(tenantId);
Objects.requireNonNull(deviceId);
Objects.requireNonNull(device);
Objects.requireNonNull(deviceVersion);
Objects.requireNonNull(span);
Optional.ofNullable(device.getStatus()).ifPresentOrElse(status -> {
if (LOG.isTraceEnabled()) {
LOG.trace("updating existing device status:{}{}", System.lineSeparator(), JsonObject.mapFrom(status).encodePrettily());
}
status.setAutoProvisioningNotificationSent(true);
}, () -> {
final var newStatus = new DeviceStatus().setAutoProvisioningNotificationSent(true);
if (LOG.isTraceEnabled()) {
LOG.trace("setting new device status:{}{}", System.lineSeparator(), JsonObject.mapFrom(newStatus).encodePrettily());
}
device.setStatus(newStatus);
});
return deviceManagementService.updateDevice(tenantId, deviceId, device, deviceVersion, span).compose(result -> {
if (HttpURLConnection.HTTP_NO_CONTENT == result.getStatus()) {
span.log("successfully marked device's auto-provisioning notification as having been sent");
LOG.debug("successfully marked device's auto-provisioning notification as having been sent " + "[tenant-id: {}, device-id: {}, device-version: {}]", tenantId, deviceId, deviceVersion.orElse(null));
return Future.succeededFuture();
} else {
LOG.warn("failed to mark device's auto-provisioning notification as having been sent " + "[tenant-id: {}, device-id: {}, device-version: {}, status: {}]", tenantId, deviceId, deviceVersion.orElse(null), result.getStatus());
Tags.HTTP_STATUS.set(span, result.getStatus());
deviceVersion.ifPresent(version -> span.setTag("device-registration-version", version));
TracingHelper.logError(span, "failed to mark device's auto-provisioning notification as having been sent");
return Future.failedFuture(ServiceInvocationException.create(tenantId, result.getStatus(), "failed to mark device's auto-provisioning notification as having been sent", null));
}
});
}
use of org.eclipse.hono.service.management.device.DeviceStatus in project hono by eclipse.
the class AbstractRegistrationService method assertRegistration.
/**
* {@inheritDoc}
* <p>
* Subclasses may override this method in order to implement a more sophisticated approach for asserting
* registration status, e.g. using cached information etc. This method relies on
* {@link #getRegistrationInformation(DeviceKey, Span)} to retrieve the information registered for
* the given device.
*/
@Override
public Future<RegistrationResult> assertRegistration(final String tenantId, final String deviceId, final String gatewayId, final Span span) {
Objects.requireNonNull(tenantId);
Objects.requireNonNull(deviceId);
Objects.requireNonNull(gatewayId);
Objects.requireNonNull(span);
return this.tenantInformationService.getTenant(tenantId, span).compose(tenant -> {
final Future<RegistrationResult> deviceInfoTracker = getRegistrationInformation(DeviceKey.from(tenantId, deviceId), span);
final Future<RegistrationResult> gatewayInfoTracker = getRegistrationInformation(DeviceKey.from(tenantId, gatewayId), span);
return CompositeFuture.all(deviceInfoTracker, gatewayInfoTracker).compose(ok -> {
final RegistrationResult deviceResult = deviceInfoTracker.result();
final RegistrationResult gatewayResult = gatewayInfoTracker.result();
if (deviceResult.isNotFound() && !gatewayResult.isNotFound() && isDeviceEnabled(gatewayResult) && hasAuthorityForAutoRegistration(gatewayResult) && supportsEdgeDeviceAutoProvisioning()) {
final Device device = new Device().setEnabled(true).setVia(Collections.singletonList(gatewayId)).setStatus(new DeviceStatus().setAutoProvisioned(true));
final JsonArray memberOf = gatewayResult.getPayload().getJsonObject(RegistrationConstants.FIELD_DATA).getJsonArray(RegistryManagementConstants.FIELD_MEMBER_OF);
Optional.ofNullable(memberOf).ifPresent(array -> device.setViaGroups(array.stream().filter(String.class::isInstance).map(String.class::cast).collect(Collectors.toList())));
LOG.debug("auto-provisioning device {} for gateway {}", deviceId, gatewayId);
return edgeDeviceAutoProvisioner.performAutoProvisioning(tenantId, tenant, deviceId, gatewayId, device, span.context()).compose(newDevice -> {
final JsonObject deviceData = JsonObject.mapFrom(newDevice);
return createSuccessfulRegistrationResult(tenantId, deviceId, deviceData, span);
}).recover(this::convertToRegistrationResult);
} else if (!isDeviceEnabled(deviceResult)) {
if (deviceResult.isNotFound()) {
LOG.debug("no such device");
TracingHelper.logError(span, "no such device");
} else {
LOG.debug("device not enabled");
TracingHelper.logError(span, "device not enabled");
}
return Future.succeededFuture(RegistrationResult.from(HttpURLConnection.HTTP_NOT_FOUND));
} else if (!isDeviceEnabled(gatewayResult)) {
if (gatewayResult.isNotFound()) {
LOG.debug("no such gateway");
TracingHelper.logError(span, "no such gateway");
} else {
LOG.debug("gateway not enabled");
TracingHelper.logError(span, "gateway not enabled");
}
return Future.succeededFuture(RegistrationResult.from(HttpURLConnection.HTTP_FORBIDDEN));
} else {
final JsonObject deviceData = deviceResult.getPayload().getJsonObject(RegistrationConstants.FIELD_DATA, new JsonObject());
final JsonObject gatewayData = gatewayResult.getPayload().getJsonObject(RegistrationConstants.FIELD_DATA, new JsonObject());
if (LOG.isDebugEnabled()) {
LOG.debug("Device data: {}", deviceData.encodePrettily());
LOG.debug("Gateway data: {}", gatewayData.encodePrettily());
}
if (isGatewayAuthorized(gatewayId, gatewayData, deviceId, deviceData)) {
if (supportsEdgeDeviceAutoProvisioning()) {
final Device device = deviceData.mapTo(Device.class);
return edgeDeviceAutoProvisioner.sendDelayedAutoProvisioningNotificationIfNeeded(tenantId, tenant, deviceId, gatewayId, device, span).compose(v -> createSuccessfulRegistrationResult(tenantId, deviceId, deviceData, span));
} else {
return createSuccessfulRegistrationResult(tenantId, deviceId, deviceData, span);
}
} else {
LOG.debug("gateway not authorized");
TracingHelper.logError(span, "gateway not authorized");
return Future.succeededFuture(RegistrationResult.from(HttpURLConnection.HTTP_FORBIDDEN));
}
}
});
}).recover(this::convertToRegistrationResult);
}
use of org.eclipse.hono.service.management.device.DeviceStatus in project hono by eclipse.
the class CredentialsApiTests method testAutoProvisioningSucceeds.
private void testAutoProvisioningSucceeds(final VertxTestContext ctx, final Tenant tenant, final X509Certificate cert, final boolean isGateway, final String expectedDeviceId) throws CertificateEncodingException {
final Checkpoint autoProvisioningEventReceived = ctx.checkpoint(1);
final Checkpoint autoProvisioningCompleted = ctx.checkpoint(1);
// GIVEN a client context that contains a client certificate
final JsonObject clientCtx = new JsonObject().put(CredentialsConstants.FIELD_CLIENT_CERT, cert.getEncoded());
final String authId = cert.getSubjectX500Principal().getName(X500Principal.RFC2253);
tenantId = getHelper().getRandomTenantId();
getHelper().applicationClient.createEventConsumer(tenantId, msg -> ctx.verify(() -> {
// VERIFY that the auto-provisioning event for the device has been received
verifyAutoProvisioningEventNotification(tenantId, expectedDeviceId, msg);
autoProvisioningEventReceived.flag();
}), close -> {
}).compose(ok -> getHelper().registry.addTenant(tenantId, tenant)).compose(ok -> getClient().get(tenantId, CredentialsConstants.SECRETS_TYPE_X509_CERT, authId, clientCtx, spanContext)).compose(result -> {
if (LOG.isDebugEnabled()) {
LOG.debug("received get Credentials result from Credentials service:{}{}", System.lineSeparator(), JsonObject.mapFrom(result).encodePrettily());
}
// VERIFY the newly created credentials
ctx.verify(() -> {
assertThat(result).isNotNull();
assertThat(result.isEnabled()).isTrue();
assertThat(result.getDeviceId()).isNotNull();
assertThat(result.getAuthId()).isEqualTo(authId);
assertThat(result.getType()).isEqualTo(CredentialsConstants.SECRETS_TYPE_X509_CERT);
assertThat(result.getSecrets()).isNotNull();
assertThat(result.getSecrets()).hasSize(1);
if (expectedDeviceId != null) {
// VERIFY the generated device-id
assertThat(result.getDeviceId()).isEqualTo(expectedDeviceId);
}
});
// WHEN getting device registration information
return getHelper().registry.getRegistrationInfo(tenantId, result.getDeviceId());
}).onComplete(ctx.succeeding(result -> {
ctx.verify(() -> {
final JsonObject resultBody = result.bodyAsJsonObject();
if (LOG.isDebugEnabled()) {
LOG.debug("received get Device result from Registry Management API:{}{}", System.lineSeparator(), resultBody.encodePrettily());
}
// VERIFY that the device/gateway has been registered as well
final Device device = resultBody.mapTo(Device.class);
assertThat(device.isEnabled()).isTrue();
if (isGateway) {
// VERIFY that the gateway related attributes are set
assertThat(device.getAuthorities()).contains(RegistryManagementConstants.AUTHORITY_AUTO_PROVISIONING_ENABLED);
}
// VERIFY that the property "auto-provisioning-notification-sent" is updated to true.
final DeviceStatus deviceStatus = resultBody.getJsonObject(RegistryManagementConstants.FIELD_STATUS).mapTo(DeviceStatus.class);
assertWithMessage("device auto-provisioned").that(deviceStatus.isAutoProvisioned()).isTrue();
assertWithMessage("auto-provisioning notification for device sent").that(deviceStatus.isAutoProvisioningNotificationSent()).isTrue();
});
autoProvisioningCompleted.flag();
}));
}
use of org.eclipse.hono.service.management.device.DeviceStatus in project hono by eclipse.
the class DeviceManagementIT method testUpdateDeviceSucceeds.
/**
* Verifies that the registration information provided when updating
* a device replaces the existing information.
*
* @param ctx The vert.x test context.
*/
@Test
public void testUpdateDeviceSucceeds(final VertxTestContext ctx) {
final JsonObject originalData = new JsonObject().put("ext", new JsonObject().put("key1", "value1").put("key2", "value2")).put(RegistrationConstants.FIELD_ENABLED, Boolean.TRUE);
final JsonObject updatedData = new JsonObject().put("ext", new JsonObject().put("newKey1", "newValue1")).put(RegistrationConstants.FIELD_ENABLED, Boolean.FALSE);
final AtomicReference<String> latestVersion = new AtomicReference<>();
final AtomicReference<Instant> creationTime = new AtomicReference<>();
registry.registerDevice(tenantId, deviceId, originalData.mapTo(Device.class)).compose(httpResponse -> {
latestVersion.set(httpResponse.getHeader(HttpHeaders.ETAG.toString()));
ctx.verify(() -> assertThat(latestVersion.get()).isNotNull());
return registry.getRegistrationInfo(tenantId, deviceId);
}).compose(httpResponse -> {
final String resourceVersion = httpResponse.getHeader(HttpHeaders.ETAG.toString());
ctx.verify(() -> {
assertThat(latestVersion.get()).isEqualTo(resourceVersion);
final var deviceStatus = getDeviceStatus(httpResponse.bodyAsJsonObject());
assertThat(deviceStatus).isNotNull();
assertThat(deviceStatus.getCreationTime()).isNotNull();
assertThat(deviceStatus.getLastUpdate()).isNull();
creationTime.set(deviceStatus.getCreationTime());
});
return registry.updateDevice(tenantId, deviceId, updatedData);
}).compose(httpResponse -> {
final String updatedVersion = httpResponse.getHeader(HttpHeaders.ETAG.toString());
ctx.verify(() -> {
assertThat(updatedVersion).isNotNull();
assertThat(updatedVersion).isNotEqualTo(latestVersion.get());
latestVersion.set(updatedVersion);
});
return registry.getRegistrationInfo(tenantId, deviceId);
}).onComplete(ctx.succeeding(httpResponse -> {
final String resourceVersion = httpResponse.getHeader(HttpHeaders.ETAG.toString());
ctx.verify(() -> {
assertThat(latestVersion.get()).isEqualTo(resourceVersion);
assertRegistrationInformation(httpResponse, updatedData.mapTo(Device.class), creationTime.get(), true);
});
ctx.completeNow();
}));
}
Aggregations