merged latest from develop
This commit is contained in:
commit
d053d126a9
45 changed files with 303 additions and 1076 deletions
|
@ -64,6 +64,7 @@ fpm -s dir -t rpm -n core \
|
||||||
-v $(PACKAGE_VERSION) \
|
-v $(PACKAGE_VERSION) \
|
||||||
--rpm-init scripts/core-daemon \
|
--rpm-init scripts/core-daemon \
|
||||||
--config-files "/etc/core" \
|
--config-files "/etc/core" \
|
||||||
|
-d "ethtool" \
|
||||||
-d "tcl" \
|
-d "tcl" \
|
||||||
-d "tk" \
|
-d "tk" \
|
||||||
-d "procps-ng" \
|
-d "procps-ng" \
|
||||||
|
@ -89,6 +90,7 @@ fpm -s dir -t deb -n core \
|
||||||
--deb-systemd scripts/core-daemon.service \
|
--deb-systemd scripts/core-daemon.service \
|
||||||
--deb-no-default-config-files \
|
--deb-no-default-config-files \
|
||||||
--config-files "/etc/core" \
|
--config-files "/etc/core" \
|
||||||
|
-d "ethtool" \
|
||||||
-d "tcl" \
|
-d "tcl" \
|
||||||
-d "tk" \
|
-d "tk" \
|
||||||
-d "libtk-img" \
|
-d "libtk-img" \
|
||||||
|
|
|
@ -13,8 +13,9 @@
|
||||||
<maven.compiler.source>1.8</maven.compiler.source>
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
<maven.compiler.target>1.8</maven.compiler.target>
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
<jung.version>2.1.1</jung.version>
|
<jung.version>2.1.1</jung.version>
|
||||||
<jackson.version>2.9.6</jackson.version>
|
<jackson.version>2.9.9</jackson.version>
|
||||||
<grpc.version>1.20.0</grpc.version>
|
<grpc.version>1.20.0</grpc.version>
|
||||||
|
<log4j.version>2.9.0</log4j.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -58,25 +59,15 @@
|
||||||
<artifactId>jackson-annotations</artifactId>
|
<artifactId>jackson-annotations</artifactId>
|
||||||
<version>${jackson.version}</version>
|
<version>${jackson.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.squareup.okhttp3</groupId>
|
|
||||||
<artifactId>okhttp</artifactId>
|
|
||||||
<version>3.11.0</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.logging.log4j</groupId>
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
<artifactId>log4j-api</artifactId>
|
<artifactId>log4j-api</artifactId>
|
||||||
<version>2.9.0</version>
|
<version>${log4j.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.logging.log4j</groupId>
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
<artifactId>log4j-core</artifactId>
|
<artifactId>log4j-core</artifactId>
|
||||||
<version>2.9.0</version>
|
<version>${log4j.version}</version>
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.socket</groupId>
|
|
||||||
<artifactId>socket.io-client</artifactId>
|
|
||||||
<version>0.8.3</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
|
@ -84,11 +75,6 @@
|
||||||
<version>1.18.0</version>
|
<version>1.18.0</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>commons-net</groupId>
|
|
||||||
<artifactId>commons-net</artifactId>
|
|
||||||
<version>3.6</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.jfoenix</groupId>
|
<groupId>com.jfoenix</groupId>
|
||||||
<artifactId>jfoenix</artifactId>
|
<artifactId>jfoenix</artifactId>
|
||||||
|
@ -114,6 +100,11 @@
|
||||||
<artifactId>guava</artifactId>
|
<artifactId>guava</artifactId>
|
||||||
<version>20.0</version>
|
<version>20.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.seancfoley</groupId>
|
||||||
|
<artifactId>ipaddress</artifactId>
|
||||||
|
<version>5.0.2</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -153,4 +144,4 @@
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package com.core.client;
|
package com.core.client;
|
||||||
|
|
||||||
import com.core.Controller;
|
import com.core.Controller;
|
||||||
import com.core.client.rest.ServiceFile;
|
import com.core.data.ServiceFile;
|
||||||
import com.core.client.rest.WlanConfig;
|
import com.core.data.WlanConfig;
|
||||||
import com.core.data.*;
|
import com.core.data.*;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
|
@ -2,10 +2,10 @@ package com.core.client.grpc;
|
||||||
|
|
||||||
import com.core.Controller;
|
import com.core.Controller;
|
||||||
import com.core.client.ICoreClient;
|
import com.core.client.ICoreClient;
|
||||||
import com.core.client.rest.ServiceFile;
|
|
||||||
import com.core.client.rest.WlanConfig;
|
|
||||||
import com.core.data.*;
|
import com.core.data.*;
|
||||||
import com.core.ui.dialogs.MobilityPlayerDialog;
|
import com.core.ui.dialogs.MobilityPlayerDialog;
|
||||||
|
import inet.ipaddr.IPAddress;
|
||||||
|
import inet.ipaddr.IPAddressString;
|
||||||
import io.grpc.Context;
|
import io.grpc.Context;
|
||||||
import io.grpc.ManagedChannel;
|
import io.grpc.ManagedChannel;
|
||||||
import io.grpc.ManagedChannelBuilder;
|
import io.grpc.ManagedChannelBuilder;
|
||||||
|
@ -123,6 +123,9 @@ public class CoreGrpcClient implements ICoreClient {
|
||||||
|
|
||||||
private CoreProto.Interface interfaceToProto(CoreInterface coreInterface) {
|
private CoreProto.Interface interfaceToProto(CoreInterface coreInterface) {
|
||||||
CoreProto.Interface.Builder builder = CoreProto.Interface.newBuilder();
|
CoreProto.Interface.Builder builder = CoreProto.Interface.newBuilder();
|
||||||
|
if (coreInterface.getId() != null) {
|
||||||
|
builder.setId(coreInterface.getId());
|
||||||
|
}
|
||||||
if (coreInterface.getName() != null) {
|
if (coreInterface.getName() != null) {
|
||||||
builder.setName(coreInterface.getName());
|
builder.setName(coreInterface.getName());
|
||||||
}
|
}
|
||||||
|
@ -130,16 +133,16 @@ public class CoreGrpcClient implements ICoreClient {
|
||||||
builder.setMac(coreInterface.getMac());
|
builder.setMac(coreInterface.getMac());
|
||||||
}
|
}
|
||||||
if (coreInterface.getIp4() != null) {
|
if (coreInterface.getIp4() != null) {
|
||||||
builder.setIp4(coreInterface.getIp4());
|
builder.setIp4(coreInterface.getIp4().toAddressString().getHostAddress().toString());
|
||||||
}
|
}
|
||||||
if (coreInterface.getIp4Mask() != null) {
|
if (coreInterface.getIp4() != null) {
|
||||||
builder.setIp4Mask(coreInterface.getIp4Mask());
|
builder.setIp4Mask(coreInterface.getIp4().getPrefixLength());
|
||||||
}
|
}
|
||||||
if (coreInterface.getIp6() != null) {
|
if (coreInterface.getIp6() != null) {
|
||||||
builder.setIp6(coreInterface.getIp6());
|
builder.setIp6(coreInterface.getIp6().toAddressString().getHostAddress().toString());
|
||||||
}
|
}
|
||||||
if (coreInterface.getIp6Mask() != null) {
|
if (coreInterface.getIp6() != null) {
|
||||||
builder.setIp6Mask(Integer.parseInt(coreInterface.getIp6Mask()));
|
builder.setIp6Mask(coreInterface.getIp6().getPrefixLength());
|
||||||
}
|
}
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
@ -170,10 +173,12 @@ public class CoreGrpcClient implements ICoreClient {
|
||||||
coreInterface.setId(protoInterface.getId());
|
coreInterface.setId(protoInterface.getId());
|
||||||
coreInterface.setName(protoInterface.getName());
|
coreInterface.setName(protoInterface.getName());
|
||||||
coreInterface.setMac(protoInterface.getMac());
|
coreInterface.setMac(protoInterface.getMac());
|
||||||
coreInterface.setIp4(protoInterface.getIp4());
|
String ip4String = String.format("%s/%s", protoInterface.getIp4(), protoInterface.getIp4Mask());
|
||||||
coreInterface.setIp4Mask(protoInterface.getIp4Mask());
|
IPAddress ip4 = new IPAddressString(ip4String).getAddress();
|
||||||
coreInterface.setIp6(protoInterface.getIp6());
|
coreInterface.setIp4(ip4);
|
||||||
coreInterface.setIp6Mask(Integer.toString(protoInterface.getIp6Mask()));
|
String ip6String = String.format("%s/%s", protoInterface.getIp6(), protoInterface.getIp6Mask());
|
||||||
|
IPAddress ip6 = new IPAddressString(ip6String).getAddress();
|
||||||
|
coreInterface.setIp6(ip6);
|
||||||
return coreInterface;
|
return coreInterface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,430 +0,0 @@
|
||||||
package com.core.client.rest;
|
|
||||||
|
|
||||||
import com.core.Controller;
|
|
||||||
import com.core.client.ICoreClient;
|
|
||||||
import com.core.data.*;
|
|
||||||
import com.core.utils.WebUtils;
|
|
||||||
import com.core.websocket.CoreWebSocket;
|
|
||||||
import lombok.Data;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class CoreRestClient implements ICoreClient {
|
|
||||||
private static final Logger logger = LogManager.getLogger();
|
|
||||||
private String address;
|
|
||||||
private int port;
|
|
||||||
private Integer sessionId;
|
|
||||||
private SessionState sessionState;
|
|
||||||
private CoreWebSocket coreWebSocket;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setConnection(String address, int port) {
|
|
||||||
this.address = address;
|
|
||||||
this.port = port;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLocalConnection() {
|
|
||||||
return address.equals("127.0.0.1") || address.equals("localhost");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Integer currentSession() {
|
|
||||||
return sessionId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateState(SessionState state) {
|
|
||||||
sessionState = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateSession(Integer sessionId) {
|
|
||||||
this.sessionId = sessionId;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getUrl(String path) {
|
|
||||||
return String.format("http://%s:%s/%s", address, port, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SessionOverview createSession() throws IOException {
|
|
||||||
String url = getUrl("sessions");
|
|
||||||
return WebUtils.post(url, SessionOverview.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean deleteSession(Integer sessionId) throws IOException {
|
|
||||||
String path = String.format("sessions/%s", sessionId);
|
|
||||||
String url = getUrl(path);
|
|
||||||
return WebUtils.delete(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, List<String>> getServices() throws IOException {
|
|
||||||
String url = getUrl("services");
|
|
||||||
GetServices getServices = WebUtils.getJson(url, GetServices.class);
|
|
||||||
return getServices.getGroups();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Session getSession(Integer sessionId) throws IOException {
|
|
||||||
String path = String.format("sessions/%s", sessionId);
|
|
||||||
String url = getUrl(path);
|
|
||||||
return WebUtils.getJson(url, Session.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<SessionOverview> getSessions() throws IOException {
|
|
||||||
String url = getUrl("sessions");
|
|
||||||
GetSessions getSessions = WebUtils.getJson(url, GetSessions.class);
|
|
||||||
return getSessions.getSessions();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean start(Collection<CoreNode> nodes, Collection<CoreLink> links, List<Hook> hooks) throws IOException {
|
|
||||||
boolean result = setState(SessionState.DEFINITION);
|
|
||||||
if (!result) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = setState(SessionState.CONFIGURATION);
|
|
||||||
if (!result) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Hook hook : hooks) {
|
|
||||||
if (!createHook(hook)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (CoreNode node : nodes) {
|
|
||||||
// must pre-configure wlan nodes, if not already
|
|
||||||
if (node.getNodeType().getValue() == NodeType.WLAN) {
|
|
||||||
WlanConfig config = getWlanConfig(node);
|
|
||||||
setWlanConfig(node, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!createNode(node)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (CoreLink link : links) {
|
|
||||||
if (!createLink(link)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return setState(SessionState.INSTANTIATION);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean stop() throws IOException {
|
|
||||||
return setState(SessionState.SHUTDOWN);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean setState(SessionState state) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/state", sessionId));
|
|
||||||
Map<String, Integer> data = new HashMap<>();
|
|
||||||
data.put("state", state.getValue());
|
|
||||||
boolean result = WebUtils.putJson(url, data);
|
|
||||||
|
|
||||||
if (result) {
|
|
||||||
sessionState = state;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean uploadFile(File file) throws IOException {
|
|
||||||
String url = getUrl("upload");
|
|
||||||
return WebUtils.postFile(url, file);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean startThroughput(Controller controller) throws IOException {
|
|
||||||
String url = getUrl("throughput/start");
|
|
||||||
return WebUtils.putJson(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean stopThroughput() throws IOException {
|
|
||||||
String url = getUrl("throughput/stop");
|
|
||||||
return WebUtils.putJson(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, List<String>> getDefaultServices() throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/services/default", sessionId));
|
|
||||||
GetDefaultServices getDefaultServices = WebUtils.getJson(url, GetDefaultServices.class);
|
|
||||||
return getDefaultServices.getDefaults();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean setDefaultServices(Map<String, Set<String>> defaults) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/services/default", sessionId));
|
|
||||||
return WebUtils.postJson(url, defaults);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CoreService getService(CoreNode node, String serviceName) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/nodes/%s/services/%s", sessionId, node.getId(), serviceName));
|
|
||||||
return WebUtils.getJson(url, CoreService.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean setService(CoreNode node, String serviceName, CoreService service) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/nodes/%s/services/%s", sessionId, node.getId(), serviceName));
|
|
||||||
return WebUtils.putJson(url, service);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getServiceFile(CoreNode node, String serviceName, String fileName) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/nodes/%s/services/%s/file", sessionId, node.getId(),
|
|
||||||
serviceName));
|
|
||||||
Map<String, String> args = new HashMap<>();
|
|
||||||
args.put("file", fileName);
|
|
||||||
return WebUtils.getJson(url, String.class, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean startService(CoreNode node, String serviceName) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/nodes/%s/services/%s/start", sessionId, node.getId(),
|
|
||||||
serviceName));
|
|
||||||
return WebUtils.putJson(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean stopService(CoreNode node, String serviceName) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/nodes/%s/services/%s/stop", sessionId, node.getId(),
|
|
||||||
serviceName));
|
|
||||||
return WebUtils.putJson(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean restartService(CoreNode node, String serviceName) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/nodes/%s/services/%s/restart", sessionId, node.getId(),
|
|
||||||
serviceName));
|
|
||||||
return WebUtils.putJson(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean validateService(CoreNode node, String serviceName) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/nodes/%s/services/%s/validate", sessionId, node.getId(),
|
|
||||||
serviceName));
|
|
||||||
return WebUtils.putJson(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean setServiceFile(CoreNode node, String serviceName, ServiceFile serviceFile) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/nodes/%s/services/%s/file", sessionId, node.getId(),
|
|
||||||
serviceName));
|
|
||||||
return WebUtils.putJson(url, serviceFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> getEmaneModels() throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/emane/models", sessionId));
|
|
||||||
GetEmaneModels getEmaneModels = WebUtils.getJson(url, GetEmaneModels.class);
|
|
||||||
return getEmaneModels.getModels();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<ConfigGroup> getEmaneModelConfig(Integer id, String model) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/emane/model/config", sessionId));
|
|
||||||
Map<String, String> args = new HashMap<>();
|
|
||||||
args.put("node", id.toString());
|
|
||||||
args.put("name", model);
|
|
||||||
GetConfig getConfig = WebUtils.getJson(url, GetConfig.class, args);
|
|
||||||
return getConfig.getGroups();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<ConfigGroup> getEmaneConfig(CoreNode node) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/emane/config", sessionId));
|
|
||||||
Map<String, String> args = new HashMap<>();
|
|
||||||
args.put("node", node.getId().toString());
|
|
||||||
GetConfig getConfig = WebUtils.getJson(url, GetConfig.class, args);
|
|
||||||
return getConfig.getGroups();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean setEmaneConfig(CoreNode node, List<ConfigOption> options) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/emane/config", sessionId));
|
|
||||||
SetEmaneConfig setEmaneConfig = new SetEmaneConfig();
|
|
||||||
setEmaneConfig.setNode(node.getId());
|
|
||||||
setEmaneConfig.setValues(options);
|
|
||||||
return WebUtils.putJson(url, setEmaneConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean setEmaneModelConfig(Integer id, String model, List<ConfigOption> options) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/emane/model/config", sessionId));
|
|
||||||
SetEmaneModelConfig setEmaneModelConfig = new SetEmaneModelConfig();
|
|
||||||
setEmaneModelConfig.setNode(id);
|
|
||||||
setEmaneModelConfig.setName(model);
|
|
||||||
setEmaneModelConfig.setValues(options);
|
|
||||||
return WebUtils.putJson(url, setEmaneModelConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRunning() {
|
|
||||||
return sessionState == SessionState.RUNTIME;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void saveSession(File file) throws IOException {
|
|
||||||
String path = String.format("sessions/%s/xml", sessionId);
|
|
||||||
String url = getUrl(path);
|
|
||||||
WebUtils.getFile(url, file);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SessionOverview openSession(File file) throws IOException {
|
|
||||||
String url = getUrl("sessions/xml");
|
|
||||||
return WebUtils.postFile(url, file, SessionOverview.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<ConfigGroup> getSessionConfig() throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/options", sessionId));
|
|
||||||
GetConfig getConfig = WebUtils.getJson(url, GetConfig.class);
|
|
||||||
return getConfig.getGroups();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean setSessionConfig(List<ConfigOption> configOptions) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/options", sessionId));
|
|
||||||
SetConfig setConfig = new SetConfig(configOptions);
|
|
||||||
return WebUtils.putJson(url, setConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LocationConfig getLocationConfig() throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/location", sessionId));
|
|
||||||
return WebUtils.getJson(url, LocationConfig.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean setLocationConfig(LocationConfig config) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/location", sessionId));
|
|
||||||
return WebUtils.putJson(url, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String nodeCommand(CoreNode node, String command) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/nodes/%s/command", sessionId, node.getId()));
|
|
||||||
return WebUtils.putJson(url, command, String.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean createNode(CoreNode node) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/nodes", sessionId));
|
|
||||||
return WebUtils.postJson(url, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean editNode(CoreNode node) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/nodes/%s", sessionId, node.getId()));
|
|
||||||
return WebUtils.putJson(url, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean deleteNode(CoreNode node) throws IOException {
|
|
||||||
String url = getUrl(String.format("/sessions/%s/nodes/%s", sessionId, node.getId()));
|
|
||||||
return WebUtils.delete(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean createLink(CoreLink link) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/links", sessionId));
|
|
||||||
return WebUtils.postJson(url, link);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean editLink(CoreLink link) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/links", sessionId));
|
|
||||||
return WebUtils.putJson(url, link);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean createHook(Hook hook) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/hooks", sessionId));
|
|
||||||
return WebUtils.postJson(url, hook);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Hook> getHooks() throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/hooks", sessionId));
|
|
||||||
GetHooks getHooks = WebUtils.getJson(url, GetHooks.class);
|
|
||||||
return getHooks.getHooks();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WlanConfig getWlanConfig(CoreNode node) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/nodes/%s/wlan", sessionId, node.getId()));
|
|
||||||
return WebUtils.getJson(url, WlanConfig.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean setWlanConfig(CoreNode node, WlanConfig config) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/nodes/%s/wlan", sessionId, node.getId()));
|
|
||||||
return WebUtils.putJson(url, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getTerminalCommand(CoreNode node) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/nodes/%s/terminal", sessionId, node.getId()));
|
|
||||||
return WebUtils.getJson(url, String.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean setMobilityConfig(CoreNode node, MobilityConfig config) throws IOException {
|
|
||||||
boolean uploaded = uploadFile(config.getScriptFile());
|
|
||||||
if (!uploaded) {
|
|
||||||
throw new IOException("failed to upload mobility script");
|
|
||||||
}
|
|
||||||
|
|
||||||
String url = getUrl(String.format("sessions/%s/nodes/%s/mobility", sessionId, node.getId()));
|
|
||||||
config.setFile(config.getScriptFile().getName());
|
|
||||||
return WebUtils.postJson(url, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<Integer, MobilityConfig> getMobilityConfigs() throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/mobility/configs", sessionId));
|
|
||||||
GetMobilityConfigs getMobilityConfigs = WebUtils.getJson(url, GetMobilityConfigs.class);
|
|
||||||
return getMobilityConfigs.getConfigurations();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MobilityConfig getMobilityConfig(CoreNode node) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/nodes/%s/mobility", sessionId, node.getId()));
|
|
||||||
return WebUtils.getJson(url, MobilityConfig.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean mobilityAction(CoreNode node, String action) throws IOException {
|
|
||||||
String url = getUrl(String.format("sessions/%s/nodes/%s/mobility/%s", sessionId, node.getId(), action));
|
|
||||||
return WebUtils.putJson(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setupEventHandlers(Controller controller) throws IOException {
|
|
||||||
coreWebSocket.stop();
|
|
||||||
coreWebSocket = new CoreWebSocket(controller);
|
|
||||||
try {
|
|
||||||
coreWebSocket.start(address, port);
|
|
||||||
} catch (URISyntaxException ex) {
|
|
||||||
throw new IOException("error starting web socket", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
package com.core.client.rest;
|
|
||||||
|
|
||||||
import com.core.data.ConfigGroup;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class GetConfig {
|
|
||||||
private List<ConfigGroup> groups = new ArrayList<>();
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
package com.core.client.rest;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
public class GetDefaultServices {
|
|
||||||
private Map<String, List<String>> defaults = new HashMap<>();
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
package com.core.client.rest;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class GetEmaneModels {
|
|
||||||
private List<String> models = new ArrayList<>();
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
package com.core.client.rest;
|
|
||||||
|
|
||||||
import com.core.data.Hook;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class GetHooks {
|
|
||||||
private List<Hook> hooks = new ArrayList<>();
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
package com.core.client.rest;
|
|
||||||
|
|
||||||
import com.core.data.MobilityConfig;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class GetMobilityConfigs {
|
|
||||||
private Map<Integer, MobilityConfig> configurations = new HashMap<>();
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
package com.core.client.rest;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@NoArgsConstructor
|
|
||||||
public class GetServices {
|
|
||||||
private Map<String, List<String>> groups;
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
package com.core.client.rest;
|
|
||||||
|
|
||||||
import com.core.data.SessionOverview;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@NoArgsConstructor
|
|
||||||
public class GetSessions {
|
|
||||||
private List<SessionOverview> sessions = new ArrayList<>();
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
package com.core.client.rest;
|
|
||||||
|
|
||||||
import com.core.data.ConfigOption;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
public class SetConfig {
|
|
||||||
private List<ConfigOption> values = new ArrayList<>();
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
package com.core.client.rest;
|
|
||||||
|
|
||||||
import com.core.data.ConfigOption;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class SetEmaneConfig {
|
|
||||||
private Integer node;
|
|
||||||
private List<ConfigOption> values = new ArrayList<>();
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
package com.core.client.rest;
|
|
||||||
|
|
||||||
import com.core.data.ConfigOption;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class SetEmaneModelConfig {
|
|
||||||
private Integer node;
|
|
||||||
private String name;
|
|
||||||
private List<ConfigOption> values = new ArrayList<>();
|
|
||||||
}
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.core.data;
|
package com.core.data;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonSetter;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@ -11,9 +10,4 @@ public class CoreEvent {
|
||||||
private Double time;
|
private Double time;
|
||||||
private EventType eventType;
|
private EventType eventType;
|
||||||
private String data;
|
private String data;
|
||||||
|
|
||||||
@JsonSetter("event_type")
|
|
||||||
public void setEventType(int value) {
|
|
||||||
eventType = EventType.get(value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.core.data;
|
package com.core.data;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import inet.ipaddr.IPAddress;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@ -10,10 +10,6 @@ public class CoreInterface {
|
||||||
private Integer id;
|
private Integer id;
|
||||||
private String name;
|
private String name;
|
||||||
private String mac;
|
private String mac;
|
||||||
private String ip4;
|
private IPAddress ip4;
|
||||||
@JsonProperty("ip4mask")
|
private IPAddress ip6;
|
||||||
private Integer ip4Mask;
|
|
||||||
private String ip6;
|
|
||||||
@JsonProperty("ip6mask")
|
|
||||||
private String ip6Mask;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package com.core.data;
|
package com.core.data;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
@ -12,36 +10,16 @@ import lombok.NoArgsConstructor;
|
||||||
public class CoreLink {
|
public class CoreLink {
|
||||||
@EqualsAndHashCode.Include
|
@EqualsAndHashCode.Include
|
||||||
private Integer id;
|
private Integer id;
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
private Float weight = 1.0f;
|
private Float weight = 1.0f;
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
private boolean loaded = true;
|
private boolean loaded = true;
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
private double throughput;
|
private double throughput;
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
private boolean visible = true;
|
private boolean visible = true;
|
||||||
|
|
||||||
@JsonProperty("message_type")
|
|
||||||
private Integer messageType;
|
private Integer messageType;
|
||||||
|
|
||||||
private Integer type = 1;
|
private Integer type = 1;
|
||||||
|
|
||||||
@JsonProperty("node_one")
|
|
||||||
private Integer nodeOne;
|
private Integer nodeOne;
|
||||||
|
|
||||||
@JsonProperty("node_two")
|
|
||||||
private Integer nodeTwo;
|
private Integer nodeTwo;
|
||||||
|
|
||||||
@JsonProperty("interface_one")
|
|
||||||
private CoreInterface interfaceOne;
|
private CoreInterface interfaceOne;
|
||||||
|
|
||||||
@JsonProperty("interface_two")
|
|
||||||
private CoreInterface interfaceTwo;
|
private CoreInterface interfaceTwo;
|
||||||
|
|
||||||
private CoreLinkOptions options = new CoreLinkOptions();
|
private CoreLinkOptions options = new CoreLinkOptions();
|
||||||
|
|
||||||
public CoreLink(Integer id) {
|
public CoreLink(Integer id) {
|
||||||
|
|
|
@ -2,7 +2,6 @@ package com.core.data;
|
||||||
|
|
||||||
import com.core.graph.RadioIcon;
|
import com.core.graph.RadioIcon;
|
||||||
import com.core.utils.IconUtils;
|
import com.core.utils.IconUtils;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
|
||||||
import edu.uci.ics.jung.visualization.LayeredIcon;
|
import edu.uci.ics.jung.visualization.LayeredIcon;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
@ -27,15 +26,10 @@ public class CoreNode {
|
||||||
private Set<String> services = new HashSet<>();
|
private Set<String> services = new HashSet<>();
|
||||||
private String emane;
|
private String emane;
|
||||||
private String url;
|
private String url;
|
||||||
@JsonIgnore
|
|
||||||
private NodeType nodeType;
|
private NodeType nodeType;
|
||||||
@JsonIgnore
|
|
||||||
private String icon;
|
private String icon;
|
||||||
@JsonIgnore
|
|
||||||
private boolean loaded = true;
|
private boolean loaded = true;
|
||||||
@JsonIgnore
|
|
||||||
private LayeredIcon graphIcon;
|
private LayeredIcon graphIcon;
|
||||||
@JsonIgnore
|
|
||||||
private RadioIcon radioIcon = new RadioIcon();
|
private RadioIcon radioIcon = new RadioIcon();
|
||||||
|
|
||||||
public CoreNode(Integer id) {
|
public CoreNode(Integer id) {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.core.data;
|
package com.core.data;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -14,9 +13,7 @@ public class CoreService {
|
||||||
private List<String> configs = new ArrayList<>();
|
private List<String> configs = new ArrayList<>();
|
||||||
private List<String> startup = new ArrayList<>();
|
private List<String> startup = new ArrayList<>();
|
||||||
private List<String> validate = new ArrayList<>();
|
private List<String> validate = new ArrayList<>();
|
||||||
@JsonProperty("validation_mode")
|
|
||||||
private String validationMode;
|
private String validationMode;
|
||||||
@JsonProperty("validation_timer")
|
|
||||||
private String validationTimer;
|
private String validationTimer;
|
||||||
private List<String> shutdown = new ArrayList<>();
|
private List<String> shutdown = new ArrayList<>();
|
||||||
private String meta;
|
private String meta;
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
package com.core.data;
|
package com.core.data;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class Hook {
|
public class Hook {
|
||||||
private String file;
|
private String file;
|
||||||
private Integer state;
|
private Integer state;
|
||||||
@JsonIgnore
|
|
||||||
private String stateDisplay;
|
private String stateDisplay;
|
||||||
private String data;
|
private String data;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
package com.core.data;
|
package com.core.data;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class InterfaceThroughput {
|
public class InterfaceThroughput {
|
||||||
private int node;
|
private int node;
|
||||||
@JsonProperty("interface")
|
|
||||||
private int nodeInterface;
|
private int nodeInterface;
|
||||||
private double throughput;
|
private double throughput;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package com.core.data;
|
package com.core.data;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -9,17 +7,12 @@ import java.io.File;
|
||||||
@Data
|
@Data
|
||||||
public class MobilityConfig {
|
public class MobilityConfig {
|
||||||
private String file;
|
private String file;
|
||||||
@JsonIgnore
|
|
||||||
private File scriptFile;
|
private File scriptFile;
|
||||||
@JsonProperty("refresh_ms")
|
|
||||||
private Integer refresh;
|
private Integer refresh;
|
||||||
private String loop;
|
private String loop;
|
||||||
private String autostart;
|
private String autostart;
|
||||||
private String map;
|
private String map;
|
||||||
@JsonProperty("script_start")
|
|
||||||
private String startScript;
|
private String startScript;
|
||||||
@JsonProperty("script_pause")
|
|
||||||
private String pauseScript;
|
private String pauseScript;
|
||||||
@JsonProperty("script_stop")
|
|
||||||
private String stopScript;
|
private String stopScript;
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,11 +73,9 @@ public class NodeType {
|
||||||
return ID_LOOKUP.values().stream()
|
return ID_LOOKUP.values().stream()
|
||||||
.filter(nodeType -> {
|
.filter(nodeType -> {
|
||||||
boolean sameType = nodeType.getValue() == type;
|
boolean sameType = nodeType.getValue() == type;
|
||||||
boolean sameModel;
|
boolean sameModel = true;
|
||||||
if (model != null) {
|
if (!model.isEmpty()) {
|
||||||
sameModel = model.equals(nodeType.getModel());
|
sameModel = model.equals(nodeType.getModel());
|
||||||
} else {
|
|
||||||
sameModel = nodeType.getModel() == null;
|
|
||||||
}
|
}
|
||||||
return sameType && sameModel;
|
return sameType && sameModel;
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.core.client.rest;
|
package com.core.data;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
|
@ -1,4 +1,4 @@
|
||||||
package com.core.client.rest;
|
package com.core.data;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
|
@ -1,41 +1,79 @@
|
||||||
package com.core.graph;
|
package com.core.graph;
|
||||||
|
|
||||||
import com.core.data.CoreInterface;
|
import com.core.data.CoreInterface;
|
||||||
|
import inet.ipaddr.IPAddress;
|
||||||
|
import inet.ipaddr.IPAddressString;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.beans.IndexedPropertyDescriptor;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
public class CoreAddresses {
|
public class CoreAddresses {
|
||||||
private static final Logger logger = LogManager.getLogger();
|
private static final Logger logger = LogManager.getLogger();
|
||||||
public static final int IP4_MASK = 24;
|
private IPAddress currentSubnet = new IPAddressString("10.0.0.0/24").getAddress().toPrefixBlock();
|
||||||
public static final int IP4_INDEX = (IP4_MASK / 8) - 1;
|
private Queue<IPAddress> deleted = new LinkedBlockingQueue<>();
|
||||||
|
private Set<IPAddress> usedSubnets = new HashSet<>();
|
||||||
|
|
||||||
private String ip4Base;
|
public void usedAddress(IPAddress address) {
|
||||||
|
logger.info("adding used address: {} - {}", address, address.toPrefixBlock());
|
||||||
public CoreAddresses(String ip4Base) {
|
usedSubnets.add(address.toPrefixBlock());
|
||||||
this.ip4Base = ip4Base;
|
logger.info("used subnets: {}", usedSubnets);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSubnet(Collection<CoreInterface> nodeOneInterfaces, Collection<CoreInterface> nodeTwoInterfaces) {
|
public void reuseSubnet(IPAddress subnet) {
|
||||||
int subOne = getMaxSubnet(nodeOneInterfaces);
|
deleted.add(subnet);
|
||||||
int subTwo = getMaxSubnet(nodeTwoInterfaces);
|
|
||||||
logger.info("next subnet: {} - {}", subOne, subTwo);
|
|
||||||
return Math.max(subOne, subTwo) + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getMaxSubnet(Collection<CoreInterface> coreInterfaces) {
|
public IPAddress nextSubnet() {
|
||||||
int sub = 0;
|
logger.info("getting next subnet: {}", currentSubnet);
|
||||||
for (CoreInterface coreInterface : coreInterfaces) {
|
// skip existing subnets, when loaded from file
|
||||||
String[] values = coreInterface.getIp4().split("\\.");
|
while (usedSubnets.contains(currentSubnet)) {
|
||||||
int currentSub = Integer.parseInt(values[IP4_INDEX]);
|
currentSubnet = currentSubnet.incrementBoundary(1).toPrefixBlock();
|
||||||
logger.info("checking {} value {}", coreInterface.getIp4(), currentSub);
|
|
||||||
sub = Math.max(currentSub, sub);
|
|
||||||
}
|
}
|
||||||
return sub;
|
|
||||||
|
// re-use any deleted subnets
|
||||||
|
IPAddress next = deleted.poll();
|
||||||
|
if (next == null) {
|
||||||
|
next = currentSubnet;
|
||||||
|
currentSubnet = currentSubnet.incrementBoundary(1).toPrefixBlock();
|
||||||
|
}
|
||||||
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getIp4Address(int sub, int id) {
|
public IPAddress findSubnet(Set<CoreInterface> interfaces) {
|
||||||
return String.format("%s.%s.%s", ip4Base, sub, id);
|
IPAddress subnet;
|
||||||
|
logger.info("finding subnet from interfaces: {}", interfaces);
|
||||||
|
if (interfaces.isEmpty()) {
|
||||||
|
subnet = nextSubnet();
|
||||||
|
} else {
|
||||||
|
IPAddress maxAddress = getMaxAddress(interfaces);
|
||||||
|
subnet = maxAddress.toPrefixBlock();
|
||||||
|
}
|
||||||
|
return subnet;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IPAddress getMaxAddress(Set<CoreInterface> interfaces) {
|
||||||
|
return interfaces.stream()
|
||||||
|
.map(CoreInterface::getIp4)
|
||||||
|
.max(Comparator.comparingInt(x -> x.toIPv4().intValue()))
|
||||||
|
.orElseGet(() -> currentSubnet);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
deleted.clear();
|
||||||
|
usedSubnets.clear();
|
||||||
|
currentSubnet = new IPAddressString("10.0.0.0/24").getAddress().toPrefixBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String... args) {
|
||||||
|
IPAddress addresses = new IPAddressString("10.0.0.0/16").getAddress();
|
||||||
|
System.out.println(String.format("address: %s", addresses.increment(257)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,9 @@ import edu.uci.ics.jung.visualization.control.GraphMouseListener;
|
||||||
import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
|
import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
|
||||||
import edu.uci.ics.jung.visualization.decorators.EdgeShape;
|
import edu.uci.ics.jung.visualization.decorators.EdgeShape;
|
||||||
import edu.uci.ics.jung.visualization.renderers.Renderer;
|
import edu.uci.ics.jung.visualization.renderers.Renderer;
|
||||||
|
import inet.ipaddr.IPAddress;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.apache.commons.net.util.SubnetUtils;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
@ -32,7 +32,6 @@ import java.awt.event.MouseEvent;
|
||||||
import java.awt.geom.Ellipse2D;
|
import java.awt.geom.Ellipse2D;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -50,8 +49,7 @@ public class NetworkGraph {
|
||||||
private EditingModalGraphMouse<CoreNode, CoreLink> graphMouse;
|
private EditingModalGraphMouse<CoreNode, CoreLink> graphMouse;
|
||||||
private AnnotationControls<CoreNode, CoreLink> annotationControls;
|
private AnnotationControls<CoreNode, CoreLink> annotationControls;
|
||||||
|
|
||||||
private SubnetUtils subnetUtils = new SubnetUtils("10.0.0.0/24");
|
private CoreAddresses coreAddresses = new CoreAddresses();
|
||||||
private CoreAddresses coreAddresses = new CoreAddresses("10.0");
|
|
||||||
private NodeType nodeType;
|
private NodeType nodeType;
|
||||||
private Map<Integer, CoreNode> nodeMap = new ConcurrentHashMap<>();
|
private Map<Integer, CoreNode> nodeMap = new ConcurrentHashMap<>();
|
||||||
private int vertexId = 1;
|
private int vertexId = 1;
|
||||||
|
@ -77,9 +75,8 @@ public class NetworkGraph {
|
||||||
graphViewer.setBackground(Color.WHITE);
|
graphViewer.setBackground(Color.WHITE);
|
||||||
graphViewer.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.S);
|
graphViewer.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.S);
|
||||||
|
|
||||||
RenderContext<CoreNode, CoreLink> renderContext = graphViewer.getRenderContext();
|
|
||||||
|
|
||||||
// node render properties
|
// node render properties
|
||||||
|
RenderContext<CoreNode, CoreLink> renderContext = graphViewer.getRenderContext();
|
||||||
renderContext.setVertexLabelTransformer(CoreNode::getName);
|
renderContext.setVertexLabelTransformer(CoreNode::getName);
|
||||||
renderContext.setVertexLabelRenderer(nodeLabelRenderer);
|
renderContext.setVertexLabelRenderer(nodeLabelRenderer);
|
||||||
renderContext.setVertexShapeTransformer(node -> {
|
renderContext.setVertexShapeTransformer(node -> {
|
||||||
|
@ -251,6 +248,7 @@ public class NetworkGraph {
|
||||||
}
|
}
|
||||||
nodeMap.clear();
|
nodeMap.clear();
|
||||||
graphViewer.repaint();
|
graphViewer.repaint();
|
||||||
|
coreAddresses.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updatePositions() {
|
public void updatePositions() {
|
||||||
|
@ -287,40 +285,93 @@ public class NetworkGraph {
|
||||||
|
|
||||||
private void handleEdgeAdded(GraphEvent.Edge<CoreNode, CoreLink> edgeEvent) {
|
private void handleEdgeAdded(GraphEvent.Edge<CoreNode, CoreLink> edgeEvent) {
|
||||||
CoreLink link = edgeEvent.getEdge();
|
CoreLink link = edgeEvent.getEdge();
|
||||||
if (!link.isLoaded()) {
|
if (link.isLoaded()) {
|
||||||
Pair<CoreNode> endpoints = graph.getEndpoints(link);
|
// load addresses to avoid duplication
|
||||||
|
if (link.getInterfaceOne().getIp4() != null) {
|
||||||
CoreNode nodeOne = endpoints.getFirst();
|
coreAddresses.usedAddress(link.getInterfaceOne().getIp4());
|
||||||
CoreNode nodeTwo = endpoints.getSecond();
|
|
||||||
|
|
||||||
// create interfaces for nodes
|
|
||||||
int sub = coreAddresses.getSubnet(
|
|
||||||
getInterfaces(nodeOne),
|
|
||||||
getInterfaces(nodeTwo)
|
|
||||||
);
|
|
||||||
|
|
||||||
link.setNodeOne(nodeOne.getId());
|
|
||||||
if (isNode(nodeOne)) {
|
|
||||||
int interfaceOneId = nextInterfaceId(nodeOne);
|
|
||||||
CoreInterface interfaceOne = createInterface(nodeOne, sub, interfaceOneId);
|
|
||||||
link.setInterfaceOne(interfaceOne);
|
|
||||||
}
|
}
|
||||||
|
if (link.getInterfaceTwo().getIp4() != null) {
|
||||||
link.setNodeTwo(nodeTwo.getId());
|
coreAddresses.usedAddress(link.getInterfaceTwo().getIp4());
|
||||||
if (isNode(nodeTwo)) {
|
|
||||||
int interfaceTwoId = nextInterfaceId(nodeTwo);
|
|
||||||
CoreInterface interfaceTwo = createInterface(nodeTwo, sub, interfaceTwoId);
|
|
||||||
link.setInterfaceTwo(interfaceTwo);
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
boolean isVisible = !checkForWirelessNode(nodeOne, nodeTwo);
|
|
||||||
link.setVisible(isVisible);
|
|
||||||
|
|
||||||
logger.info("adding user created edge: {}", link);
|
|
||||||
}
|
}
|
||||||
|
Pair<CoreNode> endpoints = graph.getEndpoints(link);
|
||||||
|
CoreNode nodeOne = endpoints.getFirst();
|
||||||
|
CoreNode nodeTwo = endpoints.getSecond();
|
||||||
|
boolean nodeOneIsDefault = isNode(nodeOne);
|
||||||
|
boolean nodeTwoIsDefault = isNode(nodeTwo);
|
||||||
|
|
||||||
|
// check what we are linking together
|
||||||
|
IPAddress subnet = null;
|
||||||
|
Set<CoreInterface> interfaces;
|
||||||
|
if (nodeOneIsDefault && nodeTwoIsDefault) {
|
||||||
|
subnet = coreAddresses.nextSubnet();
|
||||||
|
logger.info("linking node to node using subnet: {}", subnet);
|
||||||
|
} else if (nodeOneIsDefault) {
|
||||||
|
interfaces = getNetworkInterfaces(nodeTwo, new HashSet<>());
|
||||||
|
subnet = coreAddresses.findSubnet(interfaces);
|
||||||
|
logger.info("linking node one to network using subnet: {}", subnet);
|
||||||
|
} else if (nodeTwoIsDefault) {
|
||||||
|
interfaces = getNetworkInterfaces(nodeOne, new HashSet<>());
|
||||||
|
subnet = coreAddresses.findSubnet(interfaces);
|
||||||
|
logger.info("linking node two to network using subnet: {}", subnet);
|
||||||
|
} else {
|
||||||
|
logger.info("subnet not needed for linking networks together");
|
||||||
|
}
|
||||||
|
|
||||||
|
link.setNodeOne(nodeOne.getId());
|
||||||
|
if (nodeOneIsDefault) {
|
||||||
|
int interfaceOneId = nextInterfaceId(nodeOne);
|
||||||
|
CoreInterface interfaceOne = createInterface(nodeOne, interfaceOneId, subnet);
|
||||||
|
link.setInterfaceOne(interfaceOne);
|
||||||
|
}
|
||||||
|
|
||||||
|
link.setNodeTwo(nodeTwo.getId());
|
||||||
|
if (nodeTwoIsDefault) {
|
||||||
|
int interfaceTwoId = nextInterfaceId(nodeTwo);
|
||||||
|
CoreInterface interfaceTwo = createInterface(nodeTwo, interfaceTwoId, subnet);
|
||||||
|
link.setInterfaceTwo(interfaceTwo);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isVisible = !checkForWirelessNode(nodeOne, nodeTwo);
|
||||||
|
link.setVisible(isVisible);
|
||||||
|
logger.info("adding user created edge: {}", link);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<CoreInterface> getInterfaces(CoreNode node) {
|
public Set<CoreInterface> getNetworkInterfaces(CoreNode node, Set<CoreNode> visited) {
|
||||||
|
Set<CoreInterface> interfaces = new HashSet<>();
|
||||||
|
if (visited.contains(node)) {
|
||||||
|
return interfaces;
|
||||||
|
}
|
||||||
|
visited.add(node);
|
||||||
|
|
||||||
|
logger.info("checking network node links: {}", node);
|
||||||
|
for (CoreLink link : graph.getIncidentEdges(node)) {
|
||||||
|
logger.info("checking link: {}", link);
|
||||||
|
if (link.getNodeOne() == null && link.getNodeTwo() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore oneself
|
||||||
|
CoreNode currentNode = getVertex(link.getNodeOne());
|
||||||
|
CoreInterface currentInterface = link.getInterfaceOne();
|
||||||
|
if (node.getId().equals(link.getNodeOne())) {
|
||||||
|
currentNode = getVertex(link.getNodeTwo());
|
||||||
|
currentInterface = link.getInterfaceTwo();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNode(currentNode)) {
|
||||||
|
interfaces.add(currentInterface);
|
||||||
|
} else {
|
||||||
|
Set<CoreInterface> nextInterfaces = getNetworkInterfaces(currentNode, visited);
|
||||||
|
interfaces.addAll(nextInterfaces);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return interfaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<CoreInterface> getNodeInterfaces(CoreNode node) {
|
||||||
return graph.getIncidentEdges(node).stream()
|
return graph.getIncidentEdges(node).stream()
|
||||||
.map(link -> {
|
.map(link -> {
|
||||||
if (node.getId().equals(link.getNodeOne())) {
|
if (node.getId().equals(link.getNodeOne())) {
|
||||||
|
@ -330,7 +381,7 @@ public class NetworkGraph {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
private int nextInterfaceId(CoreNode node) {
|
private int nextInterfaceId(CoreNode node) {
|
||||||
|
@ -360,19 +411,52 @@ public class NetworkGraph {
|
||||||
return node.getType() == NodeType.DEFAULT;
|
return node.getType() == NodeType.DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CoreInterface createInterface(CoreNode node, int sub, int interfaceId) {
|
private CoreInterface createInterface(CoreNode node, int interfaceId, IPAddress subnet) {
|
||||||
CoreInterface coreInterface = new CoreInterface();
|
CoreInterface coreInterface = new CoreInterface();
|
||||||
coreInterface.setId(interfaceId);
|
coreInterface.setId(interfaceId);
|
||||||
coreInterface.setName(String.format("eth%s", interfaceId));
|
coreInterface.setName(String.format("eth%s", interfaceId));
|
||||||
String nodeOneIp4 = coreAddresses.getIp4Address(sub, node.getId());
|
IPAddress address = subnet.increment(node.getId());
|
||||||
coreInterface.setIp4(nodeOneIp4);
|
logger.info("creating interface for node({}): {}", node.getId(), address);
|
||||||
coreInterface.setIp4Mask(CoreAddresses.IP4_MASK);
|
coreInterface.setIp4(address);
|
||||||
|
coreInterface.setIp6(address.toIPv6());
|
||||||
return coreInterface;
|
return coreInterface;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleEdgeRemoved(GraphEvent.Edge<CoreNode, CoreLink> edgeEvent) {
|
private void handleEdgeRemoved(GraphEvent.Edge<CoreNode, CoreLink> edgeEvent) {
|
||||||
CoreLink link = edgeEvent.getEdge();
|
CoreLink link = edgeEvent.getEdge();
|
||||||
logger.info("removed edge: {}", link);
|
logger.info("removed edge: {}", link);
|
||||||
|
CoreNode nodeOne = getVertex(link.getNodeOne());
|
||||||
|
CoreInterface interfaceOne = link.getInterfaceOne();
|
||||||
|
CoreNode nodeTwo = getVertex(link.getNodeTwo());
|
||||||
|
CoreInterface interfaceTwo = link.getInterfaceTwo();
|
||||||
|
boolean nodeOneIsDefault = isNode(nodeOne);
|
||||||
|
boolean nodeTwoIsDefault = isNode(nodeTwo);
|
||||||
|
|
||||||
|
// check what we are unlinking
|
||||||
|
Set<CoreInterface> interfaces;
|
||||||
|
IPAddress subnet = null;
|
||||||
|
if (nodeOneIsDefault && nodeTwoIsDefault) {
|
||||||
|
subnet = interfaceOne.getIp4().toPrefixBlock();
|
||||||
|
logger.info("unlinking node to node reuse subnet: {}", subnet);
|
||||||
|
} else if (nodeOneIsDefault) {
|
||||||
|
interfaces = getNetworkInterfaces(nodeTwo, new HashSet<>());
|
||||||
|
if (interfaces.isEmpty()) {
|
||||||
|
subnet = interfaceOne.getIp4().toPrefixBlock();
|
||||||
|
logger.info("unlinking node one from network reuse subnet: {}", subnet);
|
||||||
|
}
|
||||||
|
} else if (nodeTwoIsDefault) {
|
||||||
|
interfaces = getNetworkInterfaces(nodeOne, new HashSet<>());
|
||||||
|
if (interfaces.isEmpty()) {
|
||||||
|
subnet = interfaceTwo.getIp4().toPrefixBlock();
|
||||||
|
logger.info("unlinking node two from network reuse subnet: {}", subnet);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.info("nothing to do when unlinking networks");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subnet != null) {
|
||||||
|
coreAddresses.reuseSubnet(subnet);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleVertexAdded(GraphEvent.Vertex<CoreNode, CoreLink> vertexEvent) {
|
private void handleVertexAdded(GraphEvent.Vertex<CoreNode, CoreLink> vertexEvent) {
|
||||||
|
@ -431,7 +515,7 @@ public class NetworkGraph {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isWirelessNode(CoreNode node) {
|
private boolean isWirelessNode(CoreNode node) {
|
||||||
return node.getType() == NodeType.EMANE || node.getType() == NodeType.WLAN;
|
return node != null && (node.getType() == NodeType.EMANE || node.getType() == NodeType.WLAN);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkForWirelessNode(CoreNode nodeOne, CoreNode nodeTwo) {
|
private boolean checkForWirelessNode(CoreNode nodeOne, CoreNode nodeTwo) {
|
||||||
|
|
|
@ -11,6 +11,7 @@ import com.core.ui.textfields.DoubleFilter;
|
||||||
import com.core.utils.FxmlUtils;
|
import com.core.utils.FxmlUtils;
|
||||||
import com.jfoenix.controls.JFXButton;
|
import com.jfoenix.controls.JFXButton;
|
||||||
import com.jfoenix.controls.JFXTextField;
|
import com.jfoenix.controls.JFXTextField;
|
||||||
|
import inet.ipaddr.IPAddress;
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.event.EventHandler;
|
import javafx.event.EventHandler;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
|
@ -129,8 +130,8 @@ public class LinkDetails extends ScrollPane {
|
||||||
if (coreInterface.getMac() != null) {
|
if (coreInterface.getMac() != null) {
|
||||||
addRow("MAC", coreInterface.getMac(), true);
|
addRow("MAC", coreInterface.getMac(), true);
|
||||||
}
|
}
|
||||||
addIp4Address(coreInterface.getIp4(), coreInterface.getIp4Mask());
|
addIp4Address(coreInterface.getIp4());
|
||||||
addIp6Address(coreInterface.getIp6(), coreInterface.getIp6Mask());
|
addIp6Address(coreInterface.getIp6());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addRow(String labelText, String value, boolean disabled) {
|
private void addRow(String labelText, String value, boolean disabled) {
|
||||||
|
@ -155,18 +156,18 @@ public class LinkDetails extends ScrollPane {
|
||||||
return textField;
|
return textField;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addIp4Address(String ip, Integer mask) {
|
private void addIp4Address(IPAddress ip) {
|
||||||
if (ip == null) {
|
if (ip == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
addRow("IP4", String.format("%s/%s", ip, mask), true);
|
addRow("IP4", ip.toString(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addIp6Address(String ip, String mask) {
|
private void addIp6Address(IPAddress ip) {
|
||||||
if (ip == null) {
|
if (ip == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
addRow("IP6", String.format("%s/%s", ip, mask), true);
|
addRow("IP6", ip.toString(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clear() {
|
private void clear() {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import com.jfoenix.controls.JFXButton;
|
||||||
import com.jfoenix.controls.JFXListView;
|
import com.jfoenix.controls.JFXListView;
|
||||||
import com.jfoenix.controls.JFXScrollPane;
|
import com.jfoenix.controls.JFXScrollPane;
|
||||||
import com.jfoenix.controls.JFXTextField;
|
import com.jfoenix.controls.JFXTextField;
|
||||||
|
import inet.ipaddr.IPAddress;
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.event.EventHandler;
|
import javafx.event.EventHandler;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
|
@ -147,8 +148,8 @@ public class NodeDetails extends ScrollPane {
|
||||||
if (coreInterface.getMac() != null) {
|
if (coreInterface.getMac() != null) {
|
||||||
addRow("MAC", coreInterface.getMac(), true);
|
addRow("MAC", coreInterface.getMac(), true);
|
||||||
}
|
}
|
||||||
addIp4Address(coreInterface.getIp4(), coreInterface.getIp4Mask());
|
addIp4Address(coreInterface.getIp4());
|
||||||
addIp6Address(coreInterface.getIp6(), coreInterface.getIp6Mask());
|
addIp6Address(coreInterface.getIp6());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addRow(String labelText, String value, boolean disabled) {
|
private void addRow(String labelText, String value, boolean disabled) {
|
||||||
|
@ -158,18 +159,18 @@ public class NodeDetails extends ScrollPane {
|
||||||
gridPane.addRow(index++, label, textField);
|
gridPane.addRow(index++, label, textField);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addIp4Address(String ip, Integer mask) {
|
private void addIp4Address(IPAddress ip) {
|
||||||
if (ip == null) {
|
if (ip == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
addRow("IP4", String.format("%s/%s", ip, mask), true);
|
addRow("IP4", ip.toString(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addIp6Address(String ip, String mask) {
|
private void addIp6Address(IPAddress ip) {
|
||||||
if (ip == null) {
|
if (ip == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
addRow("IP6", String.format("%s/%s", ip, mask), true);
|
addRow("IP6", ip.toString(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clear() {
|
private void clear() {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package com.core.ui.dialogs;
|
package com.core.ui.dialogs;
|
||||||
|
|
||||||
import com.core.Controller;
|
import com.core.Controller;
|
||||||
import com.core.client.rest.WlanConfig;
|
import com.core.data.WlanConfig;
|
||||||
import com.core.data.CoreNode;
|
import com.core.data.CoreNode;
|
||||||
import com.core.ui.Toast;
|
import com.core.ui.Toast;
|
||||||
import com.jfoenix.controls.JFXButton;
|
import com.jfoenix.controls.JFXButton;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package com.core.ui.dialogs;
|
package com.core.ui.dialogs;
|
||||||
|
|
||||||
import com.core.Controller;
|
import com.core.Controller;
|
||||||
import com.core.client.rest.ServiceFile;
|
import com.core.data.ServiceFile;
|
||||||
import com.core.data.CoreNode;
|
import com.core.data.CoreNode;
|
||||||
import com.core.data.CoreService;
|
import com.core.data.CoreService;
|
||||||
import com.jfoenix.controls.JFXButton;
|
import com.jfoenix.controls.JFXButton;
|
||||||
|
|
|
@ -1,174 +0,0 @@
|
||||||
package com.core.utils;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
|
||||||
import okhttp3.*;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public final class WebUtils {
|
|
||||||
private static final Logger logger = LogManager.getLogger();
|
|
||||||
private static final OkHttpClient client = new OkHttpClient();
|
|
||||||
private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
|
|
||||||
|
|
||||||
private WebUtils() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T getJson(String url, Class<T> clazz) throws IOException {
|
|
||||||
return getJson(url, clazz, Collections.emptyMap());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T getJson(String url, Class<T> clazz, Map<String, String> args) throws IOException {
|
|
||||||
logger.debug("get json: {}", url);
|
|
||||||
HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
|
|
||||||
args.forEach(urlBuilder::addQueryParameter);
|
|
||||||
HttpUrl httpUrl = urlBuilder.build();
|
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
|
||||||
.url(httpUrl)
|
|
||||||
.build();
|
|
||||||
String response = readResponse(request);
|
|
||||||
return JsonUtils.read(response, clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void getFile(String url, File file) throws IOException {
|
|
||||||
logger.debug("get file: {}", url);
|
|
||||||
Request request = new Request.Builder()
|
|
||||||
.url(url)
|
|
||||||
.build();
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
|
||||||
InputStream input = response.body().byteStream();
|
|
||||||
try (OutputStream output = new FileOutputStream(file)) {
|
|
||||||
int count;
|
|
||||||
byte[] data = new byte[1024];
|
|
||||||
while ((count = input.read(data)) != -1) {
|
|
||||||
output.write(data, 0, count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean postFile(String url, File file) throws IOException {
|
|
||||||
MediaType mediaType = MediaType.parse("File/*");
|
|
||||||
RequestBody requestBody = new MultipartBody.Builder()
|
|
||||||
.setType(MultipartBody.FORM)
|
|
||||||
.addFormDataPart("file", file.getName(), RequestBody.create(mediaType, file))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
|
||||||
.url(url)
|
|
||||||
.post(requestBody)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
|
||||||
return response.isSuccessful();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T postFile(String url, File file, Class<T> clazz) throws IOException {
|
|
||||||
MediaType mediaType = MediaType.parse("File/*");
|
|
||||||
RequestBody requestBody = new MultipartBody.Builder()
|
|
||||||
.setType(MultipartBody.FORM)
|
|
||||||
.addFormDataPart("file", file.getName(), RequestBody.create(mediaType, file))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
|
||||||
.url(url)
|
|
||||||
.post(requestBody)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
String response = readResponse(request);
|
|
||||||
return JsonUtils.read(response, clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T getJson(String url, TypeReference<T> reference) throws IOException {
|
|
||||||
Request request = new Request.Builder()
|
|
||||||
.url(url)
|
|
||||||
.build();
|
|
||||||
String response = readResponse(request);
|
|
||||||
return JsonUtils.getMapper().readValue(response, reference);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String readResponse(Request request) throws IOException {
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
|
||||||
ResponseBody body = response.body();
|
|
||||||
if (body == null) {
|
|
||||||
throw new IOException("failed to received body");
|
|
||||||
} else {
|
|
||||||
return body.string();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean postJson(String url, Object json) throws IOException {
|
|
||||||
logger.debug("post json: {} - {}", url, json);
|
|
||||||
RequestBody body = RequestBody.create(JSON, JsonUtils.toString(json));
|
|
||||||
Request request = new Request.Builder()
|
|
||||||
.url(url)
|
|
||||||
.post(body)
|
|
||||||
.build();
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
|
||||||
return response.isSuccessful();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean putJson(String url) throws IOException {
|
|
||||||
logger.debug("put json: {}", url);
|
|
||||||
RequestBody body = new FormBody.Builder().build();
|
|
||||||
Request request = new Request.Builder()
|
|
||||||
.url(url)
|
|
||||||
.put(body)
|
|
||||||
.build();
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
|
||||||
return response.isSuccessful();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean putJson(String url, Object json) throws IOException {
|
|
||||||
logger.debug("put json: {} - {}", url, json);
|
|
||||||
RequestBody body = RequestBody.create(JSON, JsonUtils.toString(json));
|
|
||||||
Request request = new Request.Builder()
|
|
||||||
.url(url)
|
|
||||||
.put(body)
|
|
||||||
.build();
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
|
||||||
return response.isSuccessful();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T putJson(String url, Object json, Class<T> clazz) throws IOException {
|
|
||||||
logger.debug("put json: {} - {}", url, json);
|
|
||||||
RequestBody body = RequestBody.create(JSON, JsonUtils.toString(json));
|
|
||||||
Request request = new Request.Builder()
|
|
||||||
.url(url)
|
|
||||||
.put(body)
|
|
||||||
.build();
|
|
||||||
String response = readResponse(request);
|
|
||||||
return JsonUtils.read(response, clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T post(String url, Class<T> clazz) throws IOException {
|
|
||||||
logger.debug("post: {}", url);
|
|
||||||
RequestBody body = new FormBody.Builder().build();
|
|
||||||
Request request = new Request.Builder()
|
|
||||||
.url(url)
|
|
||||||
.post(body)
|
|
||||||
.build();
|
|
||||||
String response = readResponse(request);
|
|
||||||
return JsonUtils.read(response, clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean delete(String url) throws IOException {
|
|
||||||
logger.debug("delete: {}", url);
|
|
||||||
Request request = new Request.Builder()
|
|
||||||
.url(url)
|
|
||||||
.delete()
|
|
||||||
.build();
|
|
||||||
try (Response response = client.newCall(request).execute()) {
|
|
||||||
return response.isSuccessful();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,130 +0,0 @@
|
||||||
package com.core.websocket;
|
|
||||||
|
|
||||||
import com.core.Controller;
|
|
||||||
import com.core.data.*;
|
|
||||||
import com.core.ui.dialogs.MobilityPlayerDialog;
|
|
||||||
import com.core.utils.JsonUtils;
|
|
||||||
import io.socket.client.IO;
|
|
||||||
import io.socket.client.Socket;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
|
|
||||||
public class CoreWebSocket {
|
|
||||||
private static final Logger logger = LogManager.getLogger();
|
|
||||||
private final Controller controller;
|
|
||||||
private Thread socketThread;
|
|
||||||
private Socket socket;
|
|
||||||
|
|
||||||
public CoreWebSocket(Controller controller) {
|
|
||||||
this.controller = controller;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void start(String address, int port) throws URISyntaxException {
|
|
||||||
socket = IO.socket(String.format("http://%s:%s", address, port));
|
|
||||||
socket.on(Socket.EVENT_CONNECT, args -> logger.info("connected to web socket"));
|
|
||||||
socket.on("node", this::handleNodes);
|
|
||||||
socket.on("event", this::handleEvents);
|
|
||||||
socket.on("config", this::handleConfigs);
|
|
||||||
socket.on("link", this::handleLinks);
|
|
||||||
socket.on("throughput", this::handleThroughputs);
|
|
||||||
socket.on(Socket.EVENT_DISCONNECT, args -> logger.info("disconnected from web socket"));
|
|
||||||
|
|
||||||
logger.info("attempting to connect to web socket!");
|
|
||||||
socketThread = new Thread(socket::connect);
|
|
||||||
socketThread.setDaemon(true);
|
|
||||||
socketThread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stop() {
|
|
||||||
if (socketThread != null) {
|
|
||||||
socket.close();
|
|
||||||
socketThread.interrupt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleThroughputs(Object... args) {
|
|
||||||
for (Object arg : args) {
|
|
||||||
logger.info("throughput update: {}", arg);
|
|
||||||
try {
|
|
||||||
Throughputs throughputs = JsonUtils.read(arg.toString(), Throughputs.class);
|
|
||||||
controller.handleThroughputs(throughputs);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
logger.error("error getting throughputs", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleNodes(Object... args) {
|
|
||||||
for (Object arg : args) {
|
|
||||||
try {
|
|
||||||
CoreNode node = JsonUtils.read(arg.toString(), CoreNode.class);
|
|
||||||
logger.info("core node update: {}", node);
|
|
||||||
controller.getNetworkGraph().setNodeLocation(node);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
logger.error("error getting core node", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleEvents(Object... args) {
|
|
||||||
for (Object arg : args) {
|
|
||||||
try {
|
|
||||||
CoreEvent event = JsonUtils.read(arg.toString(), CoreEvent.class);
|
|
||||||
logger.info("handling broadcast event: {}", event);
|
|
||||||
SessionState state = SessionState.get(event.getEventType().getValue());
|
|
||||||
if (state == null) {
|
|
||||||
logger.warn("unknown event type: {}", event.getEventType().getValue());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// session state event
|
|
||||||
if (state.getValue() <= 6) {
|
|
||||||
logger.info("event updating session state: {}", state);
|
|
||||||
controller.getCoreClient().updateState(state);
|
|
||||||
// mobility script event
|
|
||||||
} else if (state.getValue() <= 9) {
|
|
||||||
Integer nodeId = event.getNode();
|
|
||||||
String[] values = event.getData().split("\\s+");
|
|
||||||
Integer start = Integer.parseInt(values[0].split("=")[1]);
|
|
||||||
Integer end = Integer.parseInt(values[1].split("=")[1]);
|
|
||||||
logger.info(String.format("node(%s) mobility event (%s) - start(%s) stop(%s)",
|
|
||||||
nodeId, state, start, end));
|
|
||||||
logger.info("all dialogs: {}", controller.getMobilityPlayerDialogs().keySet());
|
|
||||||
MobilityPlayerDialog mobilityPlayerDialog = controller.getMobilityPlayerDialogs().get(nodeId);
|
|
||||||
mobilityPlayerDialog.event(state, start, end);
|
|
||||||
}
|
|
||||||
} catch (IOException ex) {
|
|
||||||
logger.error("error getting core event", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleLinks(Object... args) {
|
|
||||||
for (Object arg : args) {
|
|
||||||
try {
|
|
||||||
CoreLink link = JsonUtils.read(arg.toString(), CoreLink.class);
|
|
||||||
logger.info("handling broadcast link: {}", link);
|
|
||||||
MessageFlags flag = MessageFlags.get(link.getMessageType());
|
|
||||||
if (MessageFlags.DELETE == flag) {
|
|
||||||
logger.info("delete");
|
|
||||||
controller.getNetworkGraph().removeWirelessLink(link);
|
|
||||||
} else if (MessageFlags.ADD == flag) {
|
|
||||||
link.setLoaded(true);
|
|
||||||
controller.getNetworkGraph().addLink(link);
|
|
||||||
}
|
|
||||||
controller.getNetworkGraph().getGraphViewer().repaint();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
logger.error("error handling broadcast link", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleConfigs(Object... args) {
|
|
||||||
for (Object arg : args) {
|
|
||||||
logger.info("handling broadcast config: {}", arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +1 @@
|
||||||
../../../../daemon/proto/core.proto
|
../../../../daemon/proto/core/api/grpc/core.proto
|
|
@ -17,6 +17,7 @@ from core.emulator.emudata import NodeOptions, InterfaceData, LinkOptions
|
||||||
from core.emulator.enumerations import NodeTypes, EventTypes, LinkTypes
|
from core.emulator.enumerations import NodeTypes, EventTypes, LinkTypes
|
||||||
from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility
|
from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility
|
||||||
from core.nodes import nodeutils
|
from core.nodes import nodeutils
|
||||||
|
from core.nodes.base import CoreNetworkBase
|
||||||
from core.nodes.ipaddress import MacAddress
|
from core.nodes.ipaddress import MacAddress
|
||||||
from core.services.coreservices import ServiceManager
|
from core.services.coreservices import ServiceManager
|
||||||
|
|
||||||
|
@ -73,18 +74,24 @@ def convert_link(session, link_data):
|
||||||
interface_one = None
|
interface_one = None
|
||||||
if link_data.interface1_id is not None:
|
if link_data.interface1_id is not None:
|
||||||
node = session.get_node(link_data.node1_id)
|
node = session.get_node(link_data.node1_id)
|
||||||
interface = node.netif(link_data.interface1_id)
|
interface_name = None
|
||||||
|
if not isinstance(node, CoreNetworkBase):
|
||||||
|
interface = node.netif(link_data.interface1_id)
|
||||||
|
interface_name = interface.name
|
||||||
interface_one = core_pb2.Interface(
|
interface_one = core_pb2.Interface(
|
||||||
id=link_data.interface1_id, name=interface.name, mac=convert_value(link_data.interface1_mac),
|
id=link_data.interface1_id, name=interface_name, mac=convert_value(link_data.interface1_mac),
|
||||||
ip4=convert_value(link_data.interface1_ip4), ip4mask=link_data.interface1_ip4_mask,
|
ip4=convert_value(link_data.interface1_ip4), ip4mask=link_data.interface1_ip4_mask,
|
||||||
ip6=convert_value(link_data.interface1_ip6), ip6mask=link_data.interface1_ip6_mask)
|
ip6=convert_value(link_data.interface1_ip6), ip6mask=link_data.interface1_ip6_mask)
|
||||||
|
|
||||||
interface_two = None
|
interface_two = None
|
||||||
if link_data.interface2_id is not None:
|
if link_data.interface2_id is not None:
|
||||||
node = session.get_node(link_data.node2_id)
|
node = session.get_node(link_data.node2_id)
|
||||||
interface = node.netif(link_data.interface2_id)
|
interface_name = None
|
||||||
|
if not isinstance(node, CoreNetworkBase):
|
||||||
|
interface = node.netif(link_data.interface2_id)
|
||||||
|
interface_name = interface.name
|
||||||
interface_two = core_pb2.Interface(
|
interface_two = core_pb2.Interface(
|
||||||
id=link_data.interface2_id, name=interface.name, mac=convert_value(link_data.interface2_mac),
|
id=link_data.interface2_id, name=interface_name, mac=convert_value(link_data.interface2_mac),
|
||||||
ip4=convert_value(link_data.interface2_ip4), ip4mask=link_data.interface2_ip4_mask,
|
ip4=convert_value(link_data.interface2_ip4), ip4mask=link_data.interface2_ip4_mask,
|
||||||
ip6=convert_value(link_data.interface2_ip6), ip6mask=link_data.interface2_ip6_mask)
|
ip6=convert_value(link_data.interface2_ip6), ip6mask=link_data.interface2_ip6_mask)
|
||||||
|
|
||||||
|
@ -855,6 +862,9 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
||||||
logging.debug("set wlan config: %s", request)
|
logging.debug("set wlan config: %s", request)
|
||||||
session = self.get_session(request.session_id, context)
|
session = self.get_session(request.session_id, context)
|
||||||
session.mobility.set_model_config(request.node_id, BasicRangeModel.name, request.config)
|
session.mobility.set_model_config(request.node_id, BasicRangeModel.name, request.config)
|
||||||
|
if session.state == EventTypes.RUNTIME_STATE.value:
|
||||||
|
node = self.get_node(session, request.node_id, context)
|
||||||
|
node.updatemodel(request.config)
|
||||||
return core_pb2.SetWlanConfigResponse(result=True)
|
return core_pb2.SetWlanConfigResponse(result=True)
|
||||||
|
|
||||||
def GetEmaneConfig(self, request, context):
|
def GetEmaneConfig(self, request, context):
|
||||||
|
|
|
@ -40,6 +40,7 @@ from core.emulator.enumerations import NodeTlvs
|
||||||
from core.emulator.enumerations import NodeTypes
|
from core.emulator.enumerations import NodeTypes
|
||||||
from core.emulator.enumerations import RegisterTlvs
|
from core.emulator.enumerations import RegisterTlvs
|
||||||
from core.emulator.enumerations import SessionTlvs
|
from core.emulator.enumerations import SessionTlvs
|
||||||
|
from core.location.mobility import BasicRangeModel
|
||||||
from core.nodes import nodeutils
|
from core.nodes import nodeutils
|
||||||
from core.services.coreservices import ServiceManager
|
from core.services.coreservices import ServiceManager
|
||||||
from core.services.coreservices import ServiceShim
|
from core.services.coreservices import ServiceShim
|
||||||
|
@ -1268,6 +1269,13 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
||||||
parsed_config = ConfigShim.str_to_dict(values_str)
|
parsed_config = ConfigShim.str_to_dict(values_str)
|
||||||
|
|
||||||
self.session.mobility.set_model_config(node_id, object_name, parsed_config)
|
self.session.mobility.set_model_config(node_id, object_name, parsed_config)
|
||||||
|
if self.session.state == EventTypes.RUNTIME_STATE.value:
|
||||||
|
try:
|
||||||
|
node = self.session.get_node(node_id)
|
||||||
|
if object_name == BasicRangeModel.name:
|
||||||
|
node.updatemodel(parsed_config)
|
||||||
|
except KeyError:
|
||||||
|
logging.error("skipping mobility configuration for unknown node: %s", node_id)
|
||||||
|
|
||||||
return replies
|
return replies
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ VCMD_BIN = which("vcmd")
|
||||||
BRCTL_BIN = which("brctl")
|
BRCTL_BIN = which("brctl")
|
||||||
SYSCTL_BIN = which("sysctl")
|
SYSCTL_BIN = which("sysctl")
|
||||||
IP_BIN = which("ip")
|
IP_BIN = which("ip")
|
||||||
|
ETHTOOL_BIN = which("ethtool")
|
||||||
TC_BIN = which("tc")
|
TC_BIN = which("tc")
|
||||||
EBTABLES_BIN = which("ebtables")
|
EBTABLES_BIN = which("ebtables")
|
||||||
MOUNT_BIN = which("mount")
|
MOUNT_BIN = which("mount")
|
||||||
|
|
|
@ -9,7 +9,7 @@ import os
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
from builtins import int
|
from builtins import int
|
||||||
from past.builtins import cmp
|
from functools import total_ordering
|
||||||
|
|
||||||
from core import utils
|
from core import utils
|
||||||
from core.config import ConfigGroup
|
from core.config import ConfigGroup
|
||||||
|
@ -358,7 +358,7 @@ class BasicRangeModel(WirelessModel):
|
||||||
:param dict config: values to convert
|
:param dict config: values to convert
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.range = int(config["range"])
|
self.range = int(float(config["range"]))
|
||||||
logging.info("basic range model configured for WLAN %d using range %d", self.wlan.id, self.range)
|
logging.info("basic range model configured for WLAN %d using range %d", self.wlan.id, self.range)
|
||||||
self.bw = int(config["bandwidth"])
|
self.bw = int(config["bandwidth"])
|
||||||
if self.bw == 0:
|
if self.bw == 0:
|
||||||
|
@ -561,6 +561,7 @@ class BasicRangeModel(WirelessModel):
|
||||||
return all_links
|
return all_links
|
||||||
|
|
||||||
|
|
||||||
|
@total_ordering
|
||||||
class WayPoint(object):
|
class WayPoint(object):
|
||||||
"""
|
"""
|
||||||
Maintains information regarding waypoints.
|
Maintains information regarding waypoints.
|
||||||
|
@ -580,18 +581,17 @@ class WayPoint(object):
|
||||||
self.coords = coords
|
self.coords = coords
|
||||||
self.speed = speed
|
self.speed = speed
|
||||||
|
|
||||||
def __cmp__(self, other):
|
def __eq__(self, other):
|
||||||
"""
|
return (self.time, self.nodenum) == (other.time, other.nodedum)
|
||||||
Custom comparison method for waypoints.
|
|
||||||
|
|
||||||
:param WayPoint other: waypoint to compare to
|
def __ne__(self, other):
|
||||||
:return: the comparison result against the other waypoint
|
return not self == other
|
||||||
:rtype: int
|
|
||||||
"""
|
def __lt__(self, other):
|
||||||
tmp = cmp(self.time, other.time)
|
result = self.time < other.time
|
||||||
if tmp == 0:
|
if result:
|
||||||
tmp = cmp(self.nodenum, other.nodenum)
|
result = self.nodenum < other.nodenum
|
||||||
return tmp
|
return result
|
||||||
|
|
||||||
|
|
||||||
class WayPointMobility(WirelessModel):
|
class WayPointMobility(WirelessModel):
|
||||||
|
@ -836,7 +836,12 @@ class WayPointMobility(WirelessModel):
|
||||||
:param z: z position
|
:param z: z position
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
# this would cause PyCoreNetIf.poshook() callback (range calculation)
|
if x is not None:
|
||||||
|
x = int(x)
|
||||||
|
if y is not None:
|
||||||
|
y = int(y)
|
||||||
|
if z is not None:
|
||||||
|
z = int(z)
|
||||||
node.position.set(x, y, z)
|
node.position.set(x, y, z)
|
||||||
node_data = node.data(message_type=0)
|
node_data = node.data(message_type=0)
|
||||||
self.session.broadcast_node(node_data)
|
self.session.broadcast_node(node_data)
|
||||||
|
|
|
@ -668,6 +668,7 @@ class CoreNode(CoreNodeBase):
|
||||||
if self.up:
|
if self.up:
|
||||||
utils.check_cmd([constants.IP_BIN, "link", "set", veth.name, "netns", str(self.pid)])
|
utils.check_cmd([constants.IP_BIN, "link", "set", veth.name, "netns", str(self.pid)])
|
||||||
self.check_cmd([constants.IP_BIN, "link", "set", veth.name, "name", ifname])
|
self.check_cmd([constants.IP_BIN, "link", "set", veth.name, "name", ifname])
|
||||||
|
self.check_cmd([constants.ETHTOOL_BIN, "-K", ifname, "rx", "off", "tx", "off"])
|
||||||
|
|
||||||
veth.name = ifname
|
veth.name = ifname
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ class VnodeClient(object):
|
||||||
|
|
||||||
# run command, return process when not waiting
|
# run command, return process when not waiting
|
||||||
cmd = self._cmd_args() + args
|
cmd = self._cmd_args() + args
|
||||||
logging.info("cmd wait(%s): %s", wait, cmd)
|
logging.debug("cmd wait(%s): %s", wait, cmd)
|
||||||
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
|
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
|
||||||
if not wait:
|
if not wait:
|
||||||
return 0
|
return 0
|
||||||
|
@ -124,7 +124,7 @@ class VnodeClient(object):
|
||||||
self._verify_connection()
|
self._verify_connection()
|
||||||
args = utils.split_args(args)
|
args = utils.split_args(args)
|
||||||
cmd = self._cmd_args() + args
|
cmd = self._cmd_args() + args
|
||||||
logging.info("popen: %s", cmd)
|
logging.debug("popen: %s", cmd)
|
||||||
p = Popen(cmd, stdout=PIPE, stderr=PIPE, stdin=PIPE)
|
p = Popen(cmd, stdout=PIPE, stderr=PIPE, stdin=PIPE)
|
||||||
return p, p.stdin, p.stdout, p.stderr
|
return p, p.stdin, p.stdout, p.stderr
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ class VnodeClient(object):
|
||||||
# run command, return process when not waiting
|
# run command, return process when not waiting
|
||||||
args = utils.split_args(args)
|
args = utils.split_args(args)
|
||||||
cmd = self._cmd_args() + args
|
cmd = self._cmd_args() + args
|
||||||
logging.info("redircmd: %s", cmd)
|
logging.debug("redircmd: %s", cmd)
|
||||||
p = Popen(cmd, stdin=infd, stdout=outfd, stderr=errfd)
|
p = Popen(cmd, stdin=infd, stdout=outfd, stderr=errfd)
|
||||||
|
|
||||||
if not wait:
|
if not wait:
|
||||||
|
|
|
@ -1018,14 +1018,7 @@ class WlanNode(CoreNetwork):
|
||||||
logging.info("adding model: %s", model.name)
|
logging.info("adding model: %s", model.name)
|
||||||
if model.config_type == RegisterTlvs.WIRELESS.value:
|
if model.config_type == RegisterTlvs.WIRELESS.value:
|
||||||
self.model = model(session=self.session, _id=self.id)
|
self.model = model(session=self.session, _id=self.id)
|
||||||
self.model.update_config(config)
|
self.updatemodel(config)
|
||||||
if self.model.position_callback:
|
|
||||||
for netif in self.netifs():
|
|
||||||
netif.poshook = self.model.position_callback
|
|
||||||
if netif.node is not None:
|
|
||||||
x, y, z = netif.node.position.get()
|
|
||||||
netif.poshook(netif, x, y, z)
|
|
||||||
self.model.setlinkparams()
|
|
||||||
elif model.config_type == RegisterTlvs.MOBILITY.value:
|
elif model.config_type == RegisterTlvs.MOBILITY.value:
|
||||||
self.mobility = model(session=self.session, _id=self.id)
|
self.mobility = model(session=self.session, _id=self.id)
|
||||||
self.mobility.update_config(config)
|
self.mobility.update_config(config)
|
||||||
|
@ -1033,20 +1026,19 @@ class WlanNode(CoreNetwork):
|
||||||
def update_mobility(self, config):
|
def update_mobility(self, config):
|
||||||
if not self.mobility:
|
if not self.mobility:
|
||||||
raise ValueError("no mobility set to update for node(%s)", self.id)
|
raise ValueError("no mobility set to update for node(%s)", self.id)
|
||||||
self.mobility.set_configs(config, node_id=self.id)
|
self.mobility.update_config(config)
|
||||||
|
|
||||||
def updatemodel(self, config):
|
def updatemodel(self, config):
|
||||||
if not self.model:
|
if not self.model:
|
||||||
raise ValueError("no model set to update for node(%s)", self.id)
|
raise ValueError("no model set to update for node(%s)", self.id)
|
||||||
logging.info("node(%s) updating model(%s): %s", self.id, self.model.name, config)
|
logging.info("node(%s) updating model(%s): %s", self.id, self.model.name, config)
|
||||||
self.model.set_configs(config, node_id=self.id)
|
self.model.update_config(config)
|
||||||
if self.model.position_callback:
|
if self.model.position_callback:
|
||||||
for netif in self.netifs():
|
for netif in self.netifs():
|
||||||
netif.poshook = self.model.position_callback
|
netif.poshook = self.model.position_callback
|
||||||
if netif.node is not None:
|
if netif.node is not None:
|
||||||
x, y, z = netif.node.position.get()
|
x, y, z = netif.node.position.get()
|
||||||
netif.poshook(netif, x, y, z)
|
netif.poshook(netif, x, y, z)
|
||||||
self.model.updateconfig()
|
|
||||||
|
|
||||||
def all_link_data(self, flags):
|
def all_link_data(self, flags):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -148,9 +148,7 @@ def split_args(args):
|
||||||
:return: shell-like syntax list
|
:return: shell-like syntax list
|
||||||
:rtype: list
|
:rtype: list
|
||||||
"""
|
"""
|
||||||
logging.info("split args: %s - %s", args, type(args))
|
|
||||||
if isinstance(args, basestring):
|
if isinstance(args, basestring):
|
||||||
logging.info("splitting args")
|
|
||||||
args = shlex.split(args)
|
args = shlex.split(args)
|
||||||
return args
|
return args
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"level": "DEBUG",
|
"level": "INFO",
|
||||||
"handlers": ["console"]
|
"handlers": ["console"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -458,18 +458,29 @@ class TestGrpc:
|
||||||
# given
|
# given
|
||||||
client = CoreGrpcClient()
|
client = CoreGrpcClient()
|
||||||
session = grpc_server.coreemu.create_session()
|
session = grpc_server.coreemu.create_session()
|
||||||
|
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||||
wlan = session.add_node(_type=NodeTypes.WIRELESS_LAN)
|
wlan = session.add_node(_type=NodeTypes.WIRELESS_LAN)
|
||||||
|
wlan.setmodel(BasicRangeModel, BasicRangeModel.default_values())
|
||||||
|
session.instantiate()
|
||||||
range_key = "range"
|
range_key = "range"
|
||||||
range_value = "300"
|
range_value = "50"
|
||||||
|
|
||||||
# then
|
# then
|
||||||
with client.context_connect():
|
with client.context_connect():
|
||||||
response = client.set_wlan_config(session.id, wlan.id, {range_key: range_value})
|
response = client.set_wlan_config(session.id, wlan.id, {
|
||||||
|
range_key: range_value,
|
||||||
|
"delay": "0",
|
||||||
|
"loss": "0",
|
||||||
|
"bandwidth": "50000",
|
||||||
|
"error": "0",
|
||||||
|
"jitter": "0"
|
||||||
|
})
|
||||||
|
|
||||||
# then
|
# then
|
||||||
assert response.result is True
|
assert response.result is True
|
||||||
config = session.mobility.get_model_config(wlan.id, BasicRangeModel.name)
|
config = session.mobility.get_model_config(wlan.id, BasicRangeModel.name)
|
||||||
assert config[range_key] == range_value
|
assert config[range_key] == range_value
|
||||||
|
assert wlan.model.range == int(range_value)
|
||||||
|
|
||||||
def test_get_emane_config(self, grpc_server):
|
def test_get_emane_config(self, grpc_server):
|
||||||
# given
|
# given
|
||||||
|
|
Loading…
Reference in a new issue