Merge pull request #117 from bsinno/hawkbit-sandbox

Hawkbit sandbox
This commit is contained in:
Kai Zimmermann
2016-04-04 13:48:38 +02:00
36 changed files with 390 additions and 72 deletions

View File

@@ -14,6 +14,11 @@ see [hawkBit Wiki](https://github.com/eclipse/hawkbit/wiki)
* Having issues with hawkBit? Open a [GitHub issue](https://github.com/eclipse/hawkbit/issues).
* You can also check out our [Project Homepage](https://projects.eclipse.org/projects/iot.hawkbit) for further contact options.
# hawkBit sandbox
We offer a sandbox installation that is free for everyone to try out hawkBit. However, keep in mind that the sandbox database will be reset from time to time. It is also not possible to upload any artifacts into the sandbox. But you can use it to try out the Management UI, Management API and DDI API.
https://hawkbit.eu-gb.mybluemix.net/UI/
# Compile, Run and Getting Started

20
deployHawkBitSandbox.sh Normal file
View File

@@ -0,0 +1,20 @@
#
# Copyright (c) 2015 Bosch Software Innovations GmbH and others.
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
# This script allows the deployment of the complete hawkBit sandbox including
# data example to a cloud foundry enviroment. Expects existing CF CLI
# installation and login to be existing already.
cd examples/hawkbit-example-app/target/
cf push
cd ../..
java -jar hawkbit-mgmt-api-client/target/hawkbit-mgmt-api-client-0.2.0-SNAPSHOT.jar --hawkbit.url=hawkbit.eu-gb.mybluemix.net
cd hawkbit-device-simulator/target/
cf push
cd ../../..

View File

@@ -2,7 +2,7 @@
The device simulator handles software update commands from the update server.
## Run
## Run on your own workstation
```
java -jar examples/hawkbit-device-simulator/target/hawkbit-device-simulator-*-SNAPSHOT.jar
```
@@ -11,6 +11,11 @@ Or:
run org.eclipse.hawkbit.simulator.DeviceSimulator
```
## Deploy to cloud foundry environment
- Go to ```target``` subfolder.
- Run ```cf push```
## Notes
The simulator has user authentication enabled in **cloud profile**. Default credentials:

View File

@@ -0,0 +1,22 @@
#
# Copyright (c) 2015 Bosch Software Innovations GmbH and others.
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
---
applications:
- name: hawkbit-simulator
memory: 1024M
instances: 1
buildpack: https://github.com/cloudfoundry/java-buildpack
path: ${project.build.finalName}.jar
services:
- dmf-rabbit
env:
SPRING_PROFILES_ACTIVE: cloud,amqp
CF_STAGING_TIMEOUT: 15
CF_STARTUP_TIMEOUT: 15

View File

@@ -42,6 +42,19 @@
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>cf</directory>
<filtering>true</filtering>
<targetPath>${project.build.directory}</targetPath>
<includes>
<include>manifest.yml</include>
</includes>
</resource>
</resources>
</build>
<dependencies>

View File

@@ -14,6 +14,7 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol;
import org.eclipse.hawkbit.simulator.amqp.SpSenderService;
import org.eclipse.hawkbit.simulator.event.InitUpdate;
import org.eclipse.hawkbit.simulator.event.ProgressUpdate;
@@ -34,6 +35,9 @@ public class DeviceSimulatorUpdater {
@Autowired
private SpSenderService spSenderService;
@Autowired
private SimulatedDeviceFactory deviceFactory;
@Autowired
private EventBus eventbus;
@@ -58,7 +62,13 @@ public class DeviceSimulatorUpdater {
*/
public void startUpdate(final String tenant, final String id, final long actionId, final String swVersion,
final UpdaterCallback callback) {
final AbstractSimulatedDevice device = repository.get(tenant, id);
AbstractSimulatedDevice device = repository.get(tenant, id);
// plug and play - non existing device will be auto created
if (device == null) {
device = repository.add(deviceFactory.createSimulatedDevice(id, tenant, Protocol.DMF_AMQP, -1, null, null));
}
device.setProgress(0.0);
device.setSwversion(swVersion);
eventbus.post(new InitUpdate(device));

View File

@@ -55,7 +55,7 @@ public class SimulationController {
* number of delay in milliseconds to delay polling of DDI
* devices
* @param gatewayToken
* the hawkbit-update-server gatwaytoken in case authentication
* the hawkbit-update-server gatewaytoken in case authentication
* is enforced in hawkbit
* @return a response string that devices has been created
* @throws MalformedURLException
@@ -68,7 +68,7 @@ public class SimulationController {
@RequestParam(value = "endpoint", defaultValue = "http://localhost:8080") final String endpoint,
@RequestParam(value = "polldelay", defaultValue = "30") final int pollDelay,
@RequestParam(value = "gatewaytoken", defaultValue = "") final String gatewayToken)
throws MalformedURLException {
throws MalformedURLException {
final Protocol protocol;
switch (api.toLowerCase()) {

View File

@@ -0,0 +1,136 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.simulator;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* General simulator service properties.
*
*/
@Component
@ConfigurationProperties("hawkbit.device.simulator")
public class SimulationProperties {
/**
* List of tenants where the simulator should auto start simulations after
* startup.
*/
private final List<Autostart> autostarts = new ArrayList<>();
public List<Autostart> getAutostarts() {
return this.autostarts;
}
/**
* Auto start configuration for simulation setups that the simulator begins
* after startup.
*
*/
public static class Autostart {
/**
* Name prefix of simulated devices, followed by counter, e.g.
* simulated0, simulated1, simulated2....
*/
private String name = "simulated";
/**
* Amount of simulated devices.
*/
private int amount = 20;
/**
* Tenant name for the simulation.
*/
@NotEmpty
private String tenant;
/**
* API for simulation.
*/
private Protocol api = Protocol.DMF_AMQP;
/**
* Endpoint in case of DDI API based simulation.
*/
private String endpoint = "http://localhost:8080";
/**
* Poll time in case of DDI API based simulation.
*/
private int pollDelay = 30;
/**
* Optional gateway token for DDI API based simulation.
*/
private String gatewayToken = "";
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public int getAmount() {
return amount;
}
public void setAmount(final int amount) {
this.amount = amount;
}
public String getTenant() {
return tenant;
}
public void setTenant(final String tenant) {
this.tenant = tenant;
}
public Protocol getApi() {
return api;
}
public void setApi(final Protocol api) {
this.api = api;
}
public String getEndpoint() {
return endpoint;
}
public void setEndpoint(final String endpoint) {
this.endpoint = endpoint;
}
public int getPollDelay() {
return pollDelay;
}
public void setPollDelay(final int pollDelay) {
this.pollDelay = pollDelay;
}
public String getGatewayToken() {
return gatewayToken;
}
public void setGatewayToken(final String gatewayToken) {
this.gatewayToken = gatewayToken;
}
}
}

View File

@@ -0,0 +1,59 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.simulator;
import java.net.URL;
import org.eclipse.hawkbit.simulator.amqp.SpSenderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
/**
* Execution of operations after startup. Set up of simulations.
*
*/
@Component
public class SimulatorStartup implements ApplicationListener<ContextRefreshedEvent> {
private static final Logger LOGGER = LoggerFactory.getLogger(SimulatorStartup.class);
@Autowired
private SimulationProperties simulationProperties;
@Autowired
private SpSenderService spSenderService;
@Autowired
private DeviceSimulatorRepository repository;
@Autowired
private SimulatedDeviceFactory deviceFactory;
@Override
public void onApplicationEvent(final ContextRefreshedEvent event) {
simulationProperties.getAutostarts().forEach(autostart -> {
for (int i = 0; i < autostart.getAmount(); i++) {
final String deviceId = autostart.getName() + i;
try {
repository.add(deviceFactory.createSimulatedDevice(deviceId, autostart.getTenant(),
autostart.getApi(), autostart.getPollDelay(), new URL(autostart.getEndpoint()),
autostart.getGatewayToken()));
} catch (final Exception e) {
LOGGER.error("Creation of simulated device at startup failed.", e);
}
spSenderService.createOrUpdateThing(autostart.getTenant(), deviceId);
}
});
}
}

View File

@@ -59,7 +59,8 @@ public class AmqpConfiguration {
}
/**
* Create the receiver queue from sp. Receive messages from sp.
* Creates the receiver queue from update server for receiving message from
* update server.
*
* @return the queue
*/
@@ -70,7 +71,7 @@ public class AmqpConfiguration {
}
/**
* Create the recevier exchange. Sp send messages to this exchange.
* Creates the receiver exchange for sending messages to update server.
*
* @return the exchange
*/

View File

@@ -19,26 +19,25 @@ import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties("hawkbit.device.simulator.amqp")
public class AmqpProperties {
/**
* Queue for receiving DMF messages from update server.
*/
private String receiverConnectorQueueFromSp;
private String receiverConnectorQueueFromSp = "simulator_receiver";
/**
* Exchange for sending DMF messages to update server.
*/
private String senderForSpExchange;
private String senderForSpExchange = "simulator.replyTo";
/**
* Simulator dead letter queue.
*/
private String deadLetterQueue;
private String deadLetterQueue = "simulator_deadletter";
/**
* Simulator dead letter exchange.
*/
private String deadLetterExchange;
private String deadLetterExchange = "simulator.deadletter";
public String getReceiverConnectorQueueFromSp() {
return receiverConnectorQueueFromSp;

View File

@@ -26,14 +26,11 @@ import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
/**
* Handle all incoming Messages from SP.
*
*
* Handle all incoming Messages from hawkBit update server.
*
*/
@Component
public class SpReceiverService extends ReceiverService {
private static final Logger LOGGER = LoggerFactory.getLogger(ReceiverService.class);
public static final String SOFTWARE_MODULE_FIRMWARE = "firmware";
@@ -44,17 +41,6 @@ public class SpReceiverService extends ReceiverService {
/**
* Constructor.
*
* @param rabbitTemplate
* the rabbit template
* @param amqpProperties
* the amqp properties
* @param lwm2mSenderService
* the lwm2mSenderService
* @param spSenderService
* the spSenderService
* @param deviceUpdater
* the updater service to simulate update process
*/
@Autowired
public SpReceiverService(final RabbitTemplate rabbitTemplate, final AmqpProperties amqpProperties,
@@ -62,12 +48,11 @@ public class SpReceiverService extends ReceiverService {
super(rabbitTemplate, amqpProperties);
this.spSenderService = spSenderService;
this.deviceUpdater = deviceUpdater;
}
/**
* Handle the incoming Message from Queue with the property
* (com.bosch.sp.lwm2m.connector.amqp.receiverConnectorQueueFromSp).
* (hawkbit.device.simulator.amqp.receiverConnectorQueueFromSp).
*
* @param message
* the incoming message

View File

@@ -7,18 +7,17 @@
# http://www.eclipse.org/legal/epl-v10.html
#
#########################################################################################
# PUBLIC configuration, i.e. can be changed by users at runtime (defaults provided here)
#########################################################################################
## Configuration for RabbitMQ communication
## Configuration for DMF communication
hawkbit.device.simulator.amqp.receiverConnectorQueueFromSp=simulator_receiver
hawkbit.device.simulator.amqp.deadLetterQueue=simulator_deadletter
hawkbit.device.simulator.amqp.deadLetterExchange=simulator.deadletter
hawkbit.device.simulator.amqp.senderForSpExchange=simulator.replyTo
## Configuration for simulations
hawkbit.device.simulator.autostarts.[0].tenant=DEFAULT
## Configuration for RabbitMQ integration
## Configuration for local RabbitMQ integration
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.virtualHost=/

View File

@@ -1,7 +1,15 @@
# hawkBit Example Application
The hawkBit example application is a standalone spring-boot application with an embedded servlet container to start the hawkBit.
The hawkBit example application is a standalone spring-boot application with an embedded servlet container to host the hawkBit Update Server.
## Run
We have have described several options for you to get access to the example.
## Try out the example application in our hawkBit sandbox on Bluemix
- try out Management UI https://hawkbit.eu-gb.mybluemix.net/UI
- try out Management API https://hawkbit.eu-gb.mybluemix.net/rest/v1/targets (don't forget basic auth header)
- try out DDI API https://hawkbit.eu-gb.mybluemix.net/DEFAULT/controller/v1/MYTESTDEVICE
## On your own workstation
### Run
```
java -jar examples/hawkbit-example-app/target/hawkbit-example-app-*-SNAPSHOT.jar
```
@@ -10,6 +18,14 @@ Or:
run org eclipse.hawkbit.app.Start
```
## Usage
The UI can be accessed via _http://localhost:8080/UI_.
The REST API can be accessed via _http://localhost:8080/rest/v1_.
### Usage
The Management UI can be accessed via http://localhost:8080/UI
The Management API can be accessed via http://localhost:8080/rest/v1
## Deploy example app to Cloud Foundry
- Go to ```target``` subfolder.
- Select one of the two manifests
- **manifest-simple.yml** for a standalone hawkBit installation with embedded H2.
- **manifest.yml** for a standalone hawkBit installation with embedded H2 and RabbitMQ service binding for DMF integration (note: this manifest is used for the sandbox above).
- Run ```cf push``` against you cloud foundry environment.

View File

@@ -0,0 +1,20 @@
#
# Copyright (c) 2015 Bosch Software Innovations GmbH and others.
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
---
applications:
- name: hawkbit-simple
memory: 1024M
instances: 1
buildpack: https://github.com/cloudfoundry/java-buildpack
path: ${project.build.finalName}.jar
env:
SPRING_PROFILES_ACTIVE: cloudsandbox
CF_STAGING_TIMEOUT: 15
CF_STARTUP_TIMEOUT: 15

View File

@@ -0,0 +1,22 @@
#
# Copyright (c) 2015 Bosch Software Innovations GmbH and others.
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
---
applications:
- name: hawkbit
memory: 1024M
instances: 1
buildpack: https://github.com/cloudfoundry/java-buildpack
path: ${project.build.finalName}.jar
services:
- dmf-rabbit
env:
SPRING_PROFILES_ACTIVE: cloudsandbox,amqp
CF_STAGING_TIMEOUT: 15
CF_STARTUP_TIMEOUT: 15

View File

@@ -39,6 +39,20 @@
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>cf</directory>
<filtering>true</filtering>
<targetPath>${project.build.directory}</targetPath>
<includes>
<include>manifest.yml</include>
<include>manifest-simple.yml</include>
</includes>
</resource>
</resources>
</build>
<dependencies>

View File

@@ -0,0 +1,10 @@
#
# Copyright (c) 2015 Bosch Software Innovations GmbH and others.
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
vaadin.servlet.productionMode=true

View File

@@ -14,7 +14,7 @@ import org.springframework.cloud.netflix.feign.FeignClient;
/**
* Client binding for the DistributionSet resource of the management API.
*/
@FeignClient(url = "${hawkbit.endpoint.url:localhost:8080}/rest/v1/distributionsets")
@FeignClient(url = "${hawkbit.url:localhost:8080}/rest/v1/distributionsets")
public interface DistributionSetResourceClient extends DistributionSetRestApi {
}

View File

@@ -14,7 +14,7 @@ import org.springframework.cloud.netflix.feign.FeignClient;
/**
* Client binding for the DistributionSetTag resource of the management API.
*/
@FeignClient(url = "${hawkbit.endpoint.url:localhost:8080}/rest/v1/distributionsettags")
@FeignClient(url = "${hawkbit.url:localhost:8080}/rest/v1/distributionsettags")
public interface DistributionSetTagResourceClient extends DistributionSetTagRestApi {
}

View File

@@ -15,7 +15,7 @@ import org.springframework.cloud.netflix.feign.FeignClient;
* Client binding for the DistributionSetType resource of the management API.
*
*/
@FeignClient(url = "${hawkbit.endpoint.url:localhost:8080}/rest/v1/distributionsettypes")
@FeignClient(url = "${hawkbit.url:localhost:8080}/rest/v1/distributionsettypes")
public interface DistributionSetTypeResourceClient extends DistributionSetTypeRestApi {
}

View File

@@ -14,7 +14,7 @@ import org.springframework.cloud.netflix.feign.FeignClient;
/**
* Client binding for the Rollout resource of the management API.
*/
@FeignClient(url = "${hawkbit.endpoint.url:localhost:8080}/rest/v1/rollouts")
@FeignClient(url = "${hawkbit.url:localhost:8080}/rest/v1/rollouts")
public interface RolloutResourceClient extends RolloutRestApi {
}

View File

@@ -14,7 +14,7 @@ import org.springframework.cloud.netflix.feign.FeignClient;
/**
* Client binding for the SoftwareModule resource of the management API.
*/
@FeignClient(url = "${hawkbit.endpoint.url:localhost:8080}/rest/v1/softwaremodules")
@FeignClient(url = "${hawkbit.url:localhost:8080}/rest/v1/softwaremodules")
public interface SoftwareModuleResourceClient extends SoftwareModuleRestAPI {
}

View File

@@ -14,7 +14,7 @@ import org.springframework.cloud.netflix.feign.FeignClient;
/**
* Client binding for the oftwareModuleType resource of the management API.
*/
@FeignClient(url = "${hawkbit.endpoint.url:localhost:8080}/rest/v1/softwaremoduletypes")
@FeignClient(url = "${hawkbit.url:localhost:8080}/rest/v1/softwaremoduletypes")
public interface SoftwareModuleTypeResourceClient extends SoftwareModuleTypeRestApi {
}

View File

@@ -14,7 +14,7 @@ import org.springframework.cloud.netflix.feign.FeignClient;
/**
* Client binding for the Target resource of the management API.
*/
@FeignClient(url = "${hawkbit.endpoint.url:localhost:8080}/rest/v1/targets")
@FeignClient(url = "${hawkbit.url:localhost:8080}/rest/v1/targets")
public interface TargetResourceClient extends TargetRestApi {
}

View File

@@ -14,7 +14,7 @@ import org.springframework.cloud.netflix.feign.FeignClient;
/**
* Client binding for the TargetTag resource of the management API.
*/
@FeignClient(url = "${hawkbit.endpoint.url:localhost:8080}/rest/v1/targettags")
@FeignClient(url = "${hawkbit.url:localhost:8080}/rest/v1/targettags")
public interface TargetTagResourceClient extends TargetTagRestApi {
}

View File

@@ -16,11 +16,7 @@ import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetRe
import com.google.common.collect.Lists;
/**
*
* Builder pattern for building {@link DistributionSetRequestBodyPost}.
*
* @author Jonathan Knoblauch
*
*/
public class DistributionSetBuilder {

View File

@@ -20,8 +20,6 @@ import com.google.common.collect.Lists;
*
* Builder pattern for building {@link DistributionSetTypeRequestBodyPost}.
*
* @author Jonathan Knoblauch
*
*/
public class DistributionSetTypeBuilder {

View File

@@ -16,8 +16,6 @@ import org.eclipse.hawkbit.rest.resource.model.rollout.RolloutRestRequestBody;
*
* Builder pattern for building {@link RolloutRestRequestBody}.
*
* @author Jonathan Knoblauch
*
*/
public class RolloutBuilder {

View File

@@ -17,8 +17,6 @@ import org.eclipse.hawkbit.rest.resource.model.softwaremodule.SoftwareModuleAssi
*
* Builder pattern for building {@link SoftwareModuleAssigmentRest}.
*
* @author Jonathan Knoblauch
*
*/
public class SoftwareModuleAssigmentBuilder {

View File

@@ -20,8 +20,6 @@ import com.google.common.collect.Lists;
*
* Builder pattern for building {@link SoftwareModuleRequestBodyPost}.
*
* @author Jonathan Knoblauch
*
*/
public class SoftwareModuleBuilder {

View File

@@ -20,8 +20,6 @@ import com.google.common.collect.Lists;
*
* Builder pattern for building {@link SoftwareModuleRequestBodyPost}.
*
* @author Jonathan Knoblauch
*
*/
public class SoftwareModuleTypeBuilder {

View File

@@ -18,8 +18,6 @@ import com.google.common.collect.Lists;
/**
* Builder pattern for building {@link TagRequestBodyPut}.
*
* @author Jonathan Knoblauch
*
*/
public class TagBuilder {

View File

@@ -20,8 +20,6 @@ import com.google.common.collect.Lists;
*
* Builder pattern for building {@link TargetRequestBody}.
*
* @author Jonathan Knoblauch
*
*/
public class TargetBuilder {

View File

@@ -41,7 +41,7 @@ public class CreateStartedRolloutExample {
private static final String SM_MODULE_TYPE = "firmware";
/* known distribution set type name and key */
private static final String DS_MODULE_TYPE = "firmware";
private static final String DS_MODULE_TYPE = SM_MODULE_TYPE;
@Autowired
private DistributionSetResourceClient distributionSetResource;

View File

@@ -41,13 +41,13 @@ public class GettingStartedDefaultScenario {
private static final String SM_MODULE_TYPE = "gettingstarted";
/* known distribution set type name and key */
private static final String DS_MODULE_TYPE = "gettingstarted";
private static final String DS_MODULE_TYPE = SM_MODULE_TYPE;
/* known distribution name of this getting started example */
private static final String SM_EXAMPLE_NAME = "gettingstarted-example";
/* known distribution name of this getting started example */
private static final String DS_EXAMPLE_NAME = "gettingstarted-example";
private static final String DS_EXAMPLE_NAME = SM_EXAMPLE_NAME;
@Autowired
private DistributionSetResourceClient distributionSetResource;