RD: Implemented Device management [WIP]
This commit is contained in:
parent
dd6312d8f3
commit
ce0645e534
@ -66,6 +66,11 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-mongodb</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<dependencyManagement>
|
||||
|
@ -0,0 +1,19 @@
|
||||
package eu.nebulous.resource.discovery;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class ResourceDiscoveryConfig {
|
||||
@Bean
|
||||
public static ObjectMapper objectMapper() {
|
||||
return new ObjectMapper()
|
||||
.registerModule(new JavaTimeModule())
|
||||
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
package eu.nebulous.resource.discovery;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@ -16,7 +15,6 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.security.config.Customizer.withDefaults;
|
||||
|
@ -0,0 +1,14 @@
|
||||
|
||||
package eu.nebulous.resource.discovery.monitor;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
//@EnableAsync
|
||||
//@EnableScheduling
|
||||
@RequiredArgsConstructor
|
||||
public class DeviceProcessor {
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package eu.nebulous.resource.discovery.monitor.controller;
|
||||
|
||||
import eu.nebulous.resource.discovery.monitor.model.ArchivedDevice;
|
||||
import eu.nebulous.resource.discovery.monitor.model.Device;
|
||||
import eu.nebulous.resource.discovery.monitor.model.DeviceException;
|
||||
import eu.nebulous.resource.discovery.monitor.service.DeviceManagementService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/monitor/archived")
|
||||
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
|
||||
public class ArchivedDeviceManagementController {
|
||||
private final DeviceManagementService deviceService;
|
||||
|
||||
@GetMapping(value = "/device/all", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public List<ArchivedDevice> listDevicesAll() {
|
||||
return deviceService.getArchivedAll();
|
||||
}
|
||||
|
||||
@GetMapping(value = "/device/owner/{owner}", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public List<ArchivedDevice> listDevicesForOwner(@PathVariable String owner) {
|
||||
return deviceService.getArchivedByOwner(owner);
|
||||
}
|
||||
|
||||
@GetMapping(value = "/device/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public Device getDevice(@PathVariable String id) {
|
||||
return deviceService.getArchivedById(id)
|
||||
.orElseThrow(() -> new DeviceException("Not found archived device with id: "+id));
|
||||
}
|
||||
|
||||
@GetMapping(value = "/device/ipaddress/{ipAddress}", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public List<ArchivedDevice> getDeviceByIpAddress(@PathVariable String ipAddress) {
|
||||
return deviceService.getArchivedByIpAddress(ipAddress);
|
||||
}
|
||||
|
||||
@GetMapping(value = "/device/{id}/unarchive", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public String unarchiveDevice(@PathVariable String id) {
|
||||
deviceService.unarchiveDevice(id);
|
||||
return "UNARCHIVED";
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package eu.nebulous.resource.discovery.monitor.controller;
|
||||
|
||||
import eu.nebulous.resource.discovery.monitor.model.Device;
|
||||
import eu.nebulous.resource.discovery.monitor.model.DeviceException;
|
||||
import eu.nebulous.resource.discovery.monitor.service.DeviceConversionService;
|
||||
import eu.nebulous.resource.discovery.monitor.service.DeviceManagementService;
|
||||
import eu.nebulous.resource.discovery.registration.IRegistrationRequestProcessor;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/monitor")
|
||||
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
|
||||
public class DeviceManagementController {
|
||||
private final DeviceManagementService deviceService;
|
||||
private final DeviceConversionService deviceConversionService;
|
||||
private final IRegistrationRequestProcessor deviceRequestProcessor;
|
||||
|
||||
@GetMapping(value = "/device/all", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public List<Device> listDevicesAll() {
|
||||
return deviceService.getAll();
|
||||
}
|
||||
|
||||
@GetMapping(value = "/device/owner/{owner}", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public List<Device> listDevicesForOwner(@PathVariable String owner) {
|
||||
return deviceService.getByOwner(owner);
|
||||
}
|
||||
|
||||
@GetMapping(value = "/device/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public Device getDevice(@PathVariable String id) {
|
||||
return deviceService.getById(id)
|
||||
.orElseThrow(() -> new DeviceException("Not found device with id: "+id));
|
||||
}
|
||||
|
||||
@GetMapping(value = "/device/ipaddress/{ipAddress}", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public Device getDeviceByIpAddress(@PathVariable String ipAddress) {
|
||||
return deviceService.getByIpAddress(ipAddress)
|
||||
.orElseThrow(() -> new DeviceException("Not found device with IP address: "+ipAddress));
|
||||
}
|
||||
|
||||
@PutMapping(value = "/device", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public Device createDevice(@RequestBody Device device) {
|
||||
return deviceService.save(device);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/device/{id}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public Device updateDevice(@PathVariable String id, @RequestBody Device device) {
|
||||
if (! StringUtils.equals(id, device.getId()))
|
||||
throw new DeviceException(
|
||||
"Id does not match the id in device: "+id+" <> "+device.getId());
|
||||
return deviceService.update(device);
|
||||
}
|
||||
|
||||
@DeleteMapping(value = "/device/{id}")
|
||||
public void deleteDevice(@PathVariable String id) {
|
||||
deviceService.deleteById(id);
|
||||
}
|
||||
|
||||
@GetMapping(value = "/device/{id}/archive", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public String archiveDevice(@PathVariable String id) {
|
||||
deviceService.archiveDevice(id);
|
||||
return "ARCHIVED";
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package eu.nebulous.resource.discovery.monitor.model;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
@Slf4j
|
||||
@Document(collection = "archived_device")
|
||||
public class ArchivedDevice extends Device {
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package eu.nebulous.resource.discovery.monitor.model;
|
||||
|
||||
import eu.nebulous.resource.discovery.registration.model.RegistrationRequest;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@Document(collection = "device")
|
||||
public class Device {
|
||||
private String id;
|
||||
private String os;
|
||||
private String name;
|
||||
private String owner;
|
||||
private String ipAddress;
|
||||
private String username;
|
||||
private char[] password;
|
||||
private char[] publicKey;
|
||||
private Map<String, String> deviceInfo;
|
||||
|
||||
private RegistrationRequest request;
|
||||
private String requestId;
|
||||
private Instant creationDate;
|
||||
private Instant lastUpdateDate;
|
||||
private Instant archiveDate;
|
||||
private DeviceStatus status;
|
||||
|
||||
private String nodeReference;
|
||||
@Setter(AccessLevel.NONE)
|
||||
private List<String> messages = new ArrayList<>();
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
|
||||
package eu.nebulous.resource.discovery.monitor.model;
|
||||
|
||||
public class DeviceException extends RuntimeException {
|
||||
public DeviceException(String message) { super(message); }
|
||||
public DeviceException(Throwable t) { super(t); }
|
||||
public DeviceException(String message, Throwable t) { super(message, t); }
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package eu.nebulous.resource.discovery.monitor.model;
|
||||
|
||||
public enum DeviceStatus {
|
||||
NEW_DEVICE, ON_HOLD,
|
||||
ONBOARDING, ONBOARDED, ONBOARD_ERROR,
|
||||
HEALTHY, BUSY, IDLE,
|
||||
OFFBOARDING, OFFBOARDED, OFFBOARD_ERROR
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package eu.nebulous.resource.discovery.monitor.repository;
|
||||
|
||||
import eu.nebulous.resource.discovery.monitor.model.ArchivedDevice;
|
||||
import eu.nebulous.resource.discovery.monitor.model.Device;
|
||||
import eu.nebulous.resource.discovery.registration.model.RegistrationRequest;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface ArchivedDeviceRepository extends MongoRepository<ArchivedDevice, String> {
|
||||
List<ArchivedDevice> findByOwner(String owner);
|
||||
List<ArchivedDevice> findByIpAddress(String ipAddress);
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package eu.nebulous.resource.discovery.monitor.repository;
|
||||
|
||||
import eu.nebulous.resource.discovery.monitor.model.Device;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface DeviceRepository extends MongoRepository<Device, String> {
|
||||
List<Device> findByOwner(String owner);
|
||||
Optional<Device> findByIpAddress(String ipAddress);
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package eu.nebulous.resource.discovery.monitor.service;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import eu.nebulous.resource.discovery.monitor.model.ArchivedDevice;
|
||||
import eu.nebulous.resource.discovery.monitor.model.Device;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class DeviceConversionService {
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
public ArchivedDevice toArchivedDevice(@NonNull Device device) {
|
||||
return objectMapper
|
||||
.convertValue(device, ArchivedDevice.class);
|
||||
}
|
||||
|
||||
public Device toDevice(@NonNull ArchivedDevice archivedDevice) {
|
||||
return objectMapper
|
||||
.convertValue(archivedDevice, Device.class);
|
||||
}
|
||||
}
|
@ -0,0 +1,154 @@
|
||||
package eu.nebulous.resource.discovery.monitor.service;
|
||||
|
||||
import eu.nebulous.resource.discovery.monitor.model.ArchivedDevice;
|
||||
import eu.nebulous.resource.discovery.monitor.model.Device;
|
||||
import eu.nebulous.resource.discovery.monitor.model.DeviceException;
|
||||
import eu.nebulous.resource.discovery.monitor.model.DeviceStatus;
|
||||
import eu.nebulous.resource.discovery.monitor.repository.ArchivedDeviceRepository;
|
||||
import eu.nebulous.resource.discovery.monitor.repository.DeviceRepository;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class DeviceManagementService {
|
||||
private final DeviceRepository deviceRepository;
|
||||
private final ArchivedDeviceRepository archivedDeviceRepository;
|
||||
private final DeviceConversionService deviceConversionService;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
public List<Device> getAll() {
|
||||
return Collections.unmodifiableList(deviceRepository.findAll());
|
||||
}
|
||||
|
||||
public List<Device> getByOwner(@NonNull String owner) {
|
||||
return deviceRepository.findByOwner(owner);
|
||||
}
|
||||
|
||||
public Optional<Device> getById(@NonNull String id) {
|
||||
return deviceRepository.findById(id);
|
||||
}
|
||||
|
||||
public Optional<Device> getByIpAddress(@NonNull String ipAddress) {
|
||||
return deviceRepository.findByIpAddress(ipAddress);
|
||||
}
|
||||
|
||||
public @NonNull Device save(@NonNull Device device) {
|
||||
DeviceStatus status = device.getStatus();
|
||||
if (status == null) {
|
||||
device.setStatus(DeviceStatus.NEW_DEVICE);
|
||||
}
|
||||
if (status != null && status != DeviceStatus.NEW_DEVICE) {
|
||||
throw new DeviceException("Cannot save a new device with status "+status);
|
||||
}
|
||||
if (StringUtils.isBlank(device.getId())) {
|
||||
device.setId( UUID.randomUUID().toString() );
|
||||
} else {
|
||||
throw new DeviceException(
|
||||
"New device already has an Id: " + device.getId());
|
||||
}
|
||||
if (getById(device.getOs()).isPresent())
|
||||
throw new DeviceException(
|
||||
"A device with the same Id already exists in repository: "+device.getId());
|
||||
if (getByIpAddress(device.getIpAddress()).isPresent())
|
||||
throw new DeviceException(
|
||||
"A device with the same IP address already exists in repository: "+device.getIpAddress());
|
||||
device.setCreationDate(Instant.now());
|
||||
checkDevice(device);
|
||||
|
||||
deviceRepository.save(device);
|
||||
return device;
|
||||
}
|
||||
|
||||
public Device update(@NonNull Device device) {
|
||||
Optional<Device> result = getById(device.getId());
|
||||
if (result.isEmpty())
|
||||
throw new DeviceException(
|
||||
"Device with the Id does not exists in repository: "+device.getId());
|
||||
checkDevice(device);
|
||||
|
||||
device.setLastUpdateDate(Instant.now());
|
||||
deviceRepository.save(device);
|
||||
|
||||
return getById(device.getId()).orElseThrow(() ->
|
||||
new DeviceException("Device update failed for Device Id: "+device.getId()));
|
||||
}
|
||||
|
||||
private void checkDevice(@NonNull Device device) {
|
||||
List<String> errors = new ArrayList<>();
|
||||
if (StringUtils.isBlank(device.getId())) errors.add("Null or blank Id");
|
||||
if (StringUtils.isBlank(device.getOwner())) errors.add("Null or blank Owner");
|
||||
if (device.getCreationDate()==null) errors.add("Null Creation date");
|
||||
if (device.getStatus()==null) errors.add("Null Status");
|
||||
if (!errors.isEmpty()) {
|
||||
throw new DeviceException(
|
||||
String.format("Device spec has errors: %s\n%s",
|
||||
String.join(", ", errors), device));
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteById(@NonNull String id) {
|
||||
Optional<Device> result = getById(id);
|
||||
if (result.isEmpty())
|
||||
throw new DeviceException(
|
||||
"Device with the Id does not exists in repository: "+id);
|
||||
deviceRepository.delete(result.get());
|
||||
result.get().setLastUpdateDate(Instant.now());
|
||||
}
|
||||
|
||||
public void delete(@NonNull Device device) {
|
||||
deviceRepository.deleteById(device.getId());
|
||||
device.setLastUpdateDate(Instant.now());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
public List<ArchivedDevice> getArchivedAll() {
|
||||
return Collections.unmodifiableList(archivedDeviceRepository.findAll());
|
||||
}
|
||||
|
||||
public List<ArchivedDevice> getArchivedByOwner(@NonNull String owner) {
|
||||
return archivedDeviceRepository.findByOwner(owner);
|
||||
}
|
||||
|
||||
public Optional<ArchivedDevice> getArchivedById(@NonNull String id) {
|
||||
return archivedDeviceRepository.findById(id);
|
||||
}
|
||||
|
||||
public List<ArchivedDevice> getArchivedByIpAddress(@NonNull String ipAddress) {
|
||||
return archivedDeviceRepository.findByIpAddress(ipAddress);
|
||||
}
|
||||
|
||||
public void archiveDevice(String id) {
|
||||
archiveRequestBySystem(id);
|
||||
}
|
||||
|
||||
public void archiveRequestBySystem(String id) {
|
||||
Optional<Device> result = getById(id);
|
||||
if (result.isEmpty())
|
||||
throw new DeviceException(
|
||||
"Device with the Id does not exists in repository: " + id);
|
||||
result.get().setArchiveDate(Instant.now());
|
||||
archivedDeviceRepository.save(deviceConversionService.toArchivedDevice(result.get()));
|
||||
deviceRepository.delete(result.get());
|
||||
}
|
||||
|
||||
public void unarchiveDevice(String id) {
|
||||
Optional<ArchivedDevice> result = getArchivedById(id);
|
||||
if (result.isEmpty())
|
||||
throw new DeviceException(
|
||||
"Archived device with Id does not exists in repository: "+id);
|
||||
|
||||
result.get().setArchiveDate(null);
|
||||
deviceRepository.save(deviceConversionService.toDevice(result.get()));
|
||||
archivedDeviceRepository.deleteById(result.get().getId());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user