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) \
|
||||
--rpm-init scripts/core-daemon \
|
||||
--config-files "/etc/core" \
|
||||
-d "ethtool" \
|
||||
-d "tcl" \
|
||||
-d "tk" \
|
||||
-d "procps-ng" \
|
||||
|
@ -89,6 +90,7 @@ fpm -s dir -t deb -n core \
|
|||
--deb-systemd scripts/core-daemon.service \
|
||||
--deb-no-default-config-files \
|
||||
--config-files "/etc/core" \
|
||||
-d "ethtool" \
|
||||
-d "tcl" \
|
||||
-d "tk" \
|
||||
-d "libtk-img" \
|
||||
|
|
|
@ -13,8 +13,9 @@
|
|||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<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>
|
||||
<log4j.version>2.9.0</log4j.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@ -58,25 +59,15 @@
|
|||
<artifactId>jackson-annotations</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>3.11.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-api</artifactId>
|
||||
<version>2.9.0</version>
|
||||
<version>${log4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
<version>2.9.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.socket</groupId>
|
||||
<artifactId>socket.io-client</artifactId>
|
||||
<version>0.8.3</version>
|
||||
<version>${log4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
|
@ -84,11 +75,6 @@
|
|||
<version>1.18.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-net</groupId>
|
||||
<artifactId>commons-net</artifactId>
|
||||
<version>3.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jfoenix</groupId>
|
||||
<artifactId>jfoenix</artifactId>
|
||||
|
@ -114,6 +100,11 @@
|
|||
<artifactId>guava</artifactId>
|
||||
<version>20.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.seancfoley</groupId>
|
||||
<artifactId>ipaddress</artifactId>
|
||||
<version>5.0.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -153,4 +144,4 @@
|
|||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
</project>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package com.core.client;
|
||||
|
||||
import com.core.Controller;
|
||||
import com.core.client.rest.ServiceFile;
|
||||
import com.core.client.rest.WlanConfig;
|
||||
import com.core.data.ServiceFile;
|
||||
import com.core.data.WlanConfig;
|
||||
import com.core.data.*;
|
||||
|
||||
import java.io.File;
|
||||
|
|
|
@ -2,10 +2,10 @@ package com.core.client.grpc;
|
|||
|
||||
import com.core.Controller;
|
||||
import com.core.client.ICoreClient;
|
||||
import com.core.client.rest.ServiceFile;
|
||||
import com.core.client.rest.WlanConfig;
|
||||
import com.core.data.*;
|
||||
import com.core.ui.dialogs.MobilityPlayerDialog;
|
||||
import inet.ipaddr.IPAddress;
|
||||
import inet.ipaddr.IPAddressString;
|
||||
import io.grpc.Context;
|
||||
import io.grpc.ManagedChannel;
|
||||
import io.grpc.ManagedChannelBuilder;
|
||||
|
@ -123,6 +123,9 @@ public class CoreGrpcClient implements ICoreClient {
|
|||
|
||||
private CoreProto.Interface interfaceToProto(CoreInterface coreInterface) {
|
||||
CoreProto.Interface.Builder builder = CoreProto.Interface.newBuilder();
|
||||
if (coreInterface.getId() != null) {
|
||||
builder.setId(coreInterface.getId());
|
||||
}
|
||||
if (coreInterface.getName() != null) {
|
||||
builder.setName(coreInterface.getName());
|
||||
}
|
||||
|
@ -130,16 +133,16 @@ public class CoreGrpcClient implements ICoreClient {
|
|||
builder.setMac(coreInterface.getMac());
|
||||
}
|
||||
if (coreInterface.getIp4() != null) {
|
||||
builder.setIp4(coreInterface.getIp4());
|
||||
builder.setIp4(coreInterface.getIp4().toAddressString().getHostAddress().toString());
|
||||
}
|
||||
if (coreInterface.getIp4Mask() != null) {
|
||||
builder.setIp4Mask(coreInterface.getIp4Mask());
|
||||
if (coreInterface.getIp4() != null) {
|
||||
builder.setIp4Mask(coreInterface.getIp4().getPrefixLength());
|
||||
}
|
||||
if (coreInterface.getIp6() != null) {
|
||||
builder.setIp6(coreInterface.getIp6());
|
||||
builder.setIp6(coreInterface.getIp6().toAddressString().getHostAddress().toString());
|
||||
}
|
||||
if (coreInterface.getIp6Mask() != null) {
|
||||
builder.setIp6Mask(Integer.parseInt(coreInterface.getIp6Mask()));
|
||||
if (coreInterface.getIp6() != null) {
|
||||
builder.setIp6Mask(coreInterface.getIp6().getPrefixLength());
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
@ -170,10 +173,12 @@ public class CoreGrpcClient implements ICoreClient {
|
|||
coreInterface.setId(protoInterface.getId());
|
||||
coreInterface.setName(protoInterface.getName());
|
||||
coreInterface.setMac(protoInterface.getMac());
|
||||
coreInterface.setIp4(protoInterface.getIp4());
|
||||
coreInterface.setIp4Mask(protoInterface.getIp4Mask());
|
||||
coreInterface.setIp6(protoInterface.getIp6());
|
||||
coreInterface.setIp6Mask(Integer.toString(protoInterface.getIp6Mask()));
|
||||
String ip4String = String.format("%s/%s", protoInterface.getIp4(), protoInterface.getIp4Mask());
|
||||
IPAddress ip4 = new IPAddressString(ip4String).getAddress();
|
||||
coreInterface.setIp4(ip4);
|
||||
String ip6String = String.format("%s/%s", protoInterface.getIp6(), protoInterface.getIp6Mask());
|
||||
IPAddress ip6 = new IPAddressString(ip6String).getAddress();
|
||||
coreInterface.setIp6(ip6);
|
||||
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;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonSetter;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
|
@ -11,9 +10,4 @@ public class CoreEvent {
|
|||
private Double time;
|
||||
private EventType eventType;
|
||||
private String data;
|
||||
|
||||
@JsonSetter("event_type")
|
||||
public void setEventType(int value) {
|
||||
eventType = EventType.get(value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package com.core.data;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import inet.ipaddr.IPAddress;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
|
@ -10,10 +10,6 @@ public class CoreInterface {
|
|||
private Integer id;
|
||||
private String name;
|
||||
private String mac;
|
||||
private String ip4;
|
||||
@JsonProperty("ip4mask")
|
||||
private Integer ip4Mask;
|
||||
private String ip6;
|
||||
@JsonProperty("ip6mask")
|
||||
private String ip6Mask;
|
||||
private IPAddress ip4;
|
||||
private IPAddress ip6;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package com.core.data;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
@ -12,36 +10,16 @@ import lombok.NoArgsConstructor;
|
|||
public class CoreLink {
|
||||
@EqualsAndHashCode.Include
|
||||
private Integer id;
|
||||
|
||||
@JsonIgnore
|
||||
private Float weight = 1.0f;
|
||||
|
||||
@JsonIgnore
|
||||
private boolean loaded = true;
|
||||
|
||||
@JsonIgnore
|
||||
private double throughput;
|
||||
|
||||
@JsonIgnore
|
||||
private boolean visible = true;
|
||||
|
||||
@JsonProperty("message_type")
|
||||
private Integer messageType;
|
||||
|
||||
private Integer type = 1;
|
||||
|
||||
@JsonProperty("node_one")
|
||||
private Integer nodeOne;
|
||||
|
||||
@JsonProperty("node_two")
|
||||
private Integer nodeTwo;
|
||||
|
||||
@JsonProperty("interface_one")
|
||||
private CoreInterface interfaceOne;
|
||||
|
||||
@JsonProperty("interface_two")
|
||||
private CoreInterface interfaceTwo;
|
||||
|
||||
private CoreLinkOptions options = new CoreLinkOptions();
|
||||
|
||||
public CoreLink(Integer id) {
|
||||
|
|
|
@ -2,7 +2,6 @@ package com.core.data;
|
|||
|
||||
import com.core.graph.RadioIcon;
|
||||
import com.core.utils.IconUtils;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import edu.uci.ics.jung.visualization.LayeredIcon;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
@ -27,15 +26,10 @@ public class CoreNode {
|
|||
private Set<String> services = new HashSet<>();
|
||||
private String emane;
|
||||
private String url;
|
||||
@JsonIgnore
|
||||
private NodeType nodeType;
|
||||
@JsonIgnore
|
||||
private String icon;
|
||||
@JsonIgnore
|
||||
private boolean loaded = true;
|
||||
@JsonIgnore
|
||||
private LayeredIcon graphIcon;
|
||||
@JsonIgnore
|
||||
private RadioIcon radioIcon = new RadioIcon();
|
||||
|
||||
public CoreNode(Integer id) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.core.data;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -14,9 +13,7 @@ public class CoreService {
|
|||
private List<String> configs = new ArrayList<>();
|
||||
private List<String> startup = new ArrayList<>();
|
||||
private List<String> validate = new ArrayList<>();
|
||||
@JsonProperty("validation_mode")
|
||||
private String validationMode;
|
||||
@JsonProperty("validation_timer")
|
||||
private String validationTimer;
|
||||
private List<String> shutdown = new ArrayList<>();
|
||||
private String meta;
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
package com.core.data;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class Hook {
|
||||
private String file;
|
||||
private Integer state;
|
||||
@JsonIgnore
|
||||
private String stateDisplay;
|
||||
private String data;
|
||||
}
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
package com.core.data;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class InterfaceThroughput {
|
||||
private int node;
|
||||
@JsonProperty("interface")
|
||||
private int nodeInterface;
|
||||
private double throughput;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package com.core.data;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -9,17 +7,12 @@ import java.io.File;
|
|||
@Data
|
||||
public class MobilityConfig {
|
||||
private String file;
|
||||
@JsonIgnore
|
||||
private File scriptFile;
|
||||
@JsonProperty("refresh_ms")
|
||||
private Integer refresh;
|
||||
private String loop;
|
||||
private String autostart;
|
||||
private String map;
|
||||
@JsonProperty("script_start")
|
||||
private String startScript;
|
||||
@JsonProperty("script_pause")
|
||||
private String pauseScript;
|
||||
@JsonProperty("script_stop")
|
||||
private String stopScript;
|
||||
}
|
||||
|
|
|
@ -73,11 +73,9 @@ public class NodeType {
|
|||
return ID_LOOKUP.values().stream()
|
||||
.filter(nodeType -> {
|
||||
boolean sameType = nodeType.getValue() == type;
|
||||
boolean sameModel;
|
||||
if (model != null) {
|
||||
boolean sameModel = true;
|
||||
if (!model.isEmpty()) {
|
||||
sameModel = model.equals(nodeType.getModel());
|
||||
} else {
|
||||
sameModel = nodeType.getModel() == null;
|
||||
}
|
||||
return sameType && sameModel;
|
||||
})
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package com.core.client.rest;
|
||||
package com.core.data;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
|
@ -1,4 +1,4 @@
|
|||
package com.core.client.rest;
|
||||
package com.core.data;
|
||||
|
||||
import lombok.Data;
|
||||
|
|
@ -1,41 +1,79 @@
|
|||
package com.core.graph;
|
||||
|
||||
import com.core.data.CoreInterface;
|
||||
import inet.ipaddr.IPAddress;
|
||||
import inet.ipaddr.IPAddressString;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
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 {
|
||||
private static final Logger logger = LogManager.getLogger();
|
||||
public static final int IP4_MASK = 24;
|
||||
public static final int IP4_INDEX = (IP4_MASK / 8) - 1;
|
||||
private IPAddress currentSubnet = new IPAddressString("10.0.0.0/24").getAddress().toPrefixBlock();
|
||||
private Queue<IPAddress> deleted = new LinkedBlockingQueue<>();
|
||||
private Set<IPAddress> usedSubnets = new HashSet<>();
|
||||
|
||||
private String ip4Base;
|
||||
|
||||
public CoreAddresses(String ip4Base) {
|
||||
this.ip4Base = ip4Base;
|
||||
public void usedAddress(IPAddress address) {
|
||||
logger.info("adding used address: {} - {}", address, address.toPrefixBlock());
|
||||
usedSubnets.add(address.toPrefixBlock());
|
||||
logger.info("used subnets: {}", usedSubnets);
|
||||
}
|
||||
|
||||
public int getSubnet(Collection<CoreInterface> nodeOneInterfaces, Collection<CoreInterface> nodeTwoInterfaces) {
|
||||
int subOne = getMaxSubnet(nodeOneInterfaces);
|
||||
int subTwo = getMaxSubnet(nodeTwoInterfaces);
|
||||
logger.info("next subnet: {} - {}", subOne, subTwo);
|
||||
return Math.max(subOne, subTwo) + 1;
|
||||
public void reuseSubnet(IPAddress subnet) {
|
||||
deleted.add(subnet);
|
||||
}
|
||||
|
||||
private int getMaxSubnet(Collection<CoreInterface> coreInterfaces) {
|
||||
int sub = 0;
|
||||
for (CoreInterface coreInterface : coreInterfaces) {
|
||||
String[] values = coreInterface.getIp4().split("\\.");
|
||||
int currentSub = Integer.parseInt(values[IP4_INDEX]);
|
||||
logger.info("checking {} value {}", coreInterface.getIp4(), currentSub);
|
||||
sub = Math.max(currentSub, sub);
|
||||
public IPAddress nextSubnet() {
|
||||
logger.info("getting next subnet: {}", currentSubnet);
|
||||
// skip existing subnets, when loaded from file
|
||||
while (usedSubnets.contains(currentSubnet)) {
|
||||
currentSubnet = currentSubnet.incrementBoundary(1).toPrefixBlock();
|
||||
}
|
||||
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) {
|
||||
return String.format("%s.%s.%s", ip4Base, sub, id);
|
||||
public IPAddress findSubnet(Set<CoreInterface> interfaces) {
|
||||
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.decorators.EdgeShape;
|
||||
import edu.uci.ics.jung.visualization.renderers.Renderer;
|
||||
import inet.ipaddr.IPAddress;
|
||||
import javafx.application.Platform;
|
||||
import lombok.Data;
|
||||
import org.apache.commons.net.util.SubnetUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
|
@ -32,7 +32,6 @@ import java.awt.event.MouseEvent;
|
|||
import java.awt.geom.Ellipse2D;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -50,8 +49,7 @@ public class NetworkGraph {
|
|||
private EditingModalGraphMouse<CoreNode, CoreLink> graphMouse;
|
||||
private AnnotationControls<CoreNode, CoreLink> annotationControls;
|
||||
|
||||
private SubnetUtils subnetUtils = new SubnetUtils("10.0.0.0/24");
|
||||
private CoreAddresses coreAddresses = new CoreAddresses("10.0");
|
||||
private CoreAddresses coreAddresses = new CoreAddresses();
|
||||
private NodeType nodeType;
|
||||
private Map<Integer, CoreNode> nodeMap = new ConcurrentHashMap<>();
|
||||
private int vertexId = 1;
|
||||
|
@ -77,9 +75,8 @@ public class NetworkGraph {
|
|||
graphViewer.setBackground(Color.WHITE);
|
||||
graphViewer.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.S);
|
||||
|
||||
RenderContext<CoreNode, CoreLink> renderContext = graphViewer.getRenderContext();
|
||||
|
||||
// node render properties
|
||||
RenderContext<CoreNode, CoreLink> renderContext = graphViewer.getRenderContext();
|
||||
renderContext.setVertexLabelTransformer(CoreNode::getName);
|
||||
renderContext.setVertexLabelRenderer(nodeLabelRenderer);
|
||||
renderContext.setVertexShapeTransformer(node -> {
|
||||
|
@ -251,6 +248,7 @@ public class NetworkGraph {
|
|||
}
|
||||
nodeMap.clear();
|
||||
graphViewer.repaint();
|
||||
coreAddresses.reset();
|
||||
}
|
||||
|
||||
public void updatePositions() {
|
||||
|
@ -287,40 +285,93 @@ public class NetworkGraph {
|
|||
|
||||
private void handleEdgeAdded(GraphEvent.Edge<CoreNode, CoreLink> edgeEvent) {
|
||||
CoreLink link = edgeEvent.getEdge();
|
||||
if (!link.isLoaded()) {
|
||||
Pair<CoreNode> endpoints = graph.getEndpoints(link);
|
||||
|
||||
CoreNode nodeOne = endpoints.getFirst();
|
||||
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.isLoaded()) {
|
||||
// load addresses to avoid duplication
|
||||
if (link.getInterfaceOne().getIp4() != null) {
|
||||
coreAddresses.usedAddress(link.getInterfaceOne().getIp4());
|
||||
}
|
||||
|
||||
link.setNodeTwo(nodeTwo.getId());
|
||||
if (isNode(nodeTwo)) {
|
||||
int interfaceTwoId = nextInterfaceId(nodeTwo);
|
||||
CoreInterface interfaceTwo = createInterface(nodeTwo, sub, interfaceTwoId);
|
||||
link.setInterfaceTwo(interfaceTwo);
|
||||
if (link.getInterfaceTwo().getIp4() != null) {
|
||||
coreAddresses.usedAddress(link.getInterfaceTwo().getIp4());
|
||||
}
|
||||
|
||||
boolean isVisible = !checkForWirelessNode(nodeOne, nodeTwo);
|
||||
link.setVisible(isVisible);
|
||||
|
||||
logger.info("adding user created edge: {}", link);
|
||||
return;
|
||||
}
|
||||
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()
|
||||
.map(link -> {
|
||||
if (node.getId().equals(link.getNodeOne())) {
|
||||
|
@ -330,7 +381,7 @@ public class NetworkGraph {
|
|||
}
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private int nextInterfaceId(CoreNode node) {
|
||||
|
@ -360,19 +411,52 @@ public class NetworkGraph {
|
|||
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.setId(interfaceId);
|
||||
coreInterface.setName(String.format("eth%s", interfaceId));
|
||||
String nodeOneIp4 = coreAddresses.getIp4Address(sub, node.getId());
|
||||
coreInterface.setIp4(nodeOneIp4);
|
||||
coreInterface.setIp4Mask(CoreAddresses.IP4_MASK);
|
||||
IPAddress address = subnet.increment(node.getId());
|
||||
logger.info("creating interface for node({}): {}", node.getId(), address);
|
||||
coreInterface.setIp4(address);
|
||||
coreInterface.setIp6(address.toIPv6());
|
||||
return coreInterface;
|
||||
}
|
||||
|
||||
private void handleEdgeRemoved(GraphEvent.Edge<CoreNode, CoreLink> edgeEvent) {
|
||||
CoreLink link = edgeEvent.getEdge();
|
||||
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) {
|
||||
|
@ -431,7 +515,7 @@ public class NetworkGraph {
|
|||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -11,6 +11,7 @@ import com.core.ui.textfields.DoubleFilter;
|
|||
import com.core.utils.FxmlUtils;
|
||||
import com.jfoenix.controls.JFXButton;
|
||||
import com.jfoenix.controls.JFXTextField;
|
||||
import inet.ipaddr.IPAddress;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.fxml.FXML;
|
||||
|
@ -129,8 +130,8 @@ public class LinkDetails extends ScrollPane {
|
|||
if (coreInterface.getMac() != null) {
|
||||
addRow("MAC", coreInterface.getMac(), true);
|
||||
}
|
||||
addIp4Address(coreInterface.getIp4(), coreInterface.getIp4Mask());
|
||||
addIp6Address(coreInterface.getIp6(), coreInterface.getIp6Mask());
|
||||
addIp4Address(coreInterface.getIp4());
|
||||
addIp6Address(coreInterface.getIp6());
|
||||
}
|
||||
|
||||
private void addRow(String labelText, String value, boolean disabled) {
|
||||
|
@ -155,18 +156,18 @@ public class LinkDetails extends ScrollPane {
|
|||
return textField;
|
||||
}
|
||||
|
||||
private void addIp4Address(String ip, Integer mask) {
|
||||
private void addIp4Address(IPAddress ip) {
|
||||
if (ip == null) {
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
addRow("IP6", String.format("%s/%s", ip, mask), true);
|
||||
addRow("IP6", ip.toString(), true);
|
||||
}
|
||||
|
||||
private void clear() {
|
||||
|
|
|
@ -10,6 +10,7 @@ import com.jfoenix.controls.JFXButton;
|
|||
import com.jfoenix.controls.JFXListView;
|
||||
import com.jfoenix.controls.JFXScrollPane;
|
||||
import com.jfoenix.controls.JFXTextField;
|
||||
import inet.ipaddr.IPAddress;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.fxml.FXML;
|
||||
|
@ -147,8 +148,8 @@ public class NodeDetails extends ScrollPane {
|
|||
if (coreInterface.getMac() != null) {
|
||||
addRow("MAC", coreInterface.getMac(), true);
|
||||
}
|
||||
addIp4Address(coreInterface.getIp4(), coreInterface.getIp4Mask());
|
||||
addIp6Address(coreInterface.getIp6(), coreInterface.getIp6Mask());
|
||||
addIp4Address(coreInterface.getIp4());
|
||||
addIp6Address(coreInterface.getIp6());
|
||||
}
|
||||
|
||||
private void addRow(String labelText, String value, boolean disabled) {
|
||||
|
@ -158,18 +159,18 @@ public class NodeDetails extends ScrollPane {
|
|||
gridPane.addRow(index++, label, textField);
|
||||
}
|
||||
|
||||
private void addIp4Address(String ip, Integer mask) {
|
||||
private void addIp4Address(IPAddress ip) {
|
||||
if (ip == null) {
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
addRow("IP6", String.format("%s/%s", ip, mask), true);
|
||||
addRow("IP6", ip.toString(), true);
|
||||
}
|
||||
|
||||
private void clear() {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package com.core.ui.dialogs;
|
||||
|
||||
import com.core.Controller;
|
||||
import com.core.client.rest.WlanConfig;
|
||||
import com.core.data.WlanConfig;
|
||||
import com.core.data.CoreNode;
|
||||
import com.core.ui.Toast;
|
||||
import com.jfoenix.controls.JFXButton;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package com.core.ui.dialogs;
|
||||
|
||||
import com.core.Controller;
|
||||
import com.core.client.rest.ServiceFile;
|
||||
import com.core.data.ServiceFile;
|
||||
import com.core.data.CoreNode;
|
||||
import com.core.data.CoreService;
|
||||
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.location.mobility import BasicRangeModel, Ns2ScriptedMobility
|
||||
from core.nodes import nodeutils
|
||||
from core.nodes.base import CoreNetworkBase
|
||||
from core.nodes.ipaddress import MacAddress
|
||||
from core.services.coreservices import ServiceManager
|
||||
|
||||
|
@ -73,18 +74,24 @@ def convert_link(session, link_data):
|
|||
interface_one = None
|
||||
if link_data.interface1_id is not None:
|
||||
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(
|
||||
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,
|
||||
ip6=convert_value(link_data.interface1_ip6), ip6mask=link_data.interface1_ip6_mask)
|
||||
|
||||
interface_two = None
|
||||
if link_data.interface2_id is not None:
|
||||
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(
|
||||
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,
|
||||
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)
|
||||
session = self.get_session(request.session_id, context)
|
||||
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)
|
||||
|
||||
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 RegisterTlvs
|
||||
from core.emulator.enumerations import SessionTlvs
|
||||
from core.location.mobility import BasicRangeModel
|
||||
from core.nodes import nodeutils
|
||||
from core.services.coreservices import ServiceManager
|
||||
from core.services.coreservices import ServiceShim
|
||||
|
@ -1268,6 +1269,13 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
|||
parsed_config = ConfigShim.str_to_dict(values_str)
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ VCMD_BIN = which("vcmd")
|
|||
BRCTL_BIN = which("brctl")
|
||||
SYSCTL_BIN = which("sysctl")
|
||||
IP_BIN = which("ip")
|
||||
ETHTOOL_BIN = which("ethtool")
|
||||
TC_BIN = which("tc")
|
||||
EBTABLES_BIN = which("ebtables")
|
||||
MOUNT_BIN = which("mount")
|
||||
|
|
|
@ -9,7 +9,7 @@ import os
|
|||
import threading
|
||||
import time
|
||||
from builtins import int
|
||||
from past.builtins import cmp
|
||||
from functools import total_ordering
|
||||
|
||||
from core import utils
|
||||
from core.config import ConfigGroup
|
||||
|
@ -358,7 +358,7 @@ class BasicRangeModel(WirelessModel):
|
|||
:param dict config: values to convert
|
||||
: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)
|
||||
self.bw = int(config["bandwidth"])
|
||||
if self.bw == 0:
|
||||
|
@ -561,6 +561,7 @@ class BasicRangeModel(WirelessModel):
|
|||
return all_links
|
||||
|
||||
|
||||
@total_ordering
|
||||
class WayPoint(object):
|
||||
"""
|
||||
Maintains information regarding waypoints.
|
||||
|
@ -580,18 +581,17 @@ class WayPoint(object):
|
|||
self.coords = coords
|
||||
self.speed = speed
|
||||
|
||||
def __cmp__(self, other):
|
||||
"""
|
||||
Custom comparison method for waypoints.
|
||||
def __eq__(self, other):
|
||||
return (self.time, self.nodenum) == (other.time, other.nodedum)
|
||||
|
||||
:param WayPoint other: waypoint to compare to
|
||||
:return: the comparison result against the other waypoint
|
||||
:rtype: int
|
||||
"""
|
||||
tmp = cmp(self.time, other.time)
|
||||
if tmp == 0:
|
||||
tmp = cmp(self.nodenum, other.nodenum)
|
||||
return tmp
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __lt__(self, other):
|
||||
result = self.time < other.time
|
||||
if result:
|
||||
result = self.nodenum < other.nodenum
|
||||
return result
|
||||
|
||||
|
||||
class WayPointMobility(WirelessModel):
|
||||
|
@ -836,7 +836,12 @@ class WayPointMobility(WirelessModel):
|
|||
:param z: z position
|
||||
: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_data = node.data(message_type=0)
|
||||
self.session.broadcast_node(node_data)
|
||||
|
|
|
@ -668,6 +668,7 @@ class CoreNode(CoreNodeBase):
|
|||
if self.up:
|
||||
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.ETHTOOL_BIN, "-K", ifname, "rx", "off", "tx", "off"])
|
||||
|
||||
veth.name = ifname
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ class VnodeClient(object):
|
|||
|
||||
# run command, return process when not waiting
|
||||
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)
|
||||
if not wait:
|
||||
return 0
|
||||
|
@ -124,7 +124,7 @@ class VnodeClient(object):
|
|||
self._verify_connection()
|
||||
args = utils.split_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)
|
||||
return p, p.stdin, p.stdout, p.stderr
|
||||
|
||||
|
@ -157,7 +157,7 @@ class VnodeClient(object):
|
|||
# run command, return process when not waiting
|
||||
args = utils.split_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)
|
||||
|
||||
if not wait:
|
||||
|
|
|
@ -1018,14 +1018,7 @@ class WlanNode(CoreNetwork):
|
|||
logging.info("adding model: %s", model.name)
|
||||
if model.config_type == RegisterTlvs.WIRELESS.value:
|
||||
self.model = model(session=self.session, _id=self.id)
|
||||
self.model.update_config(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()
|
||||
self.updatemodel(config)
|
||||
elif model.config_type == RegisterTlvs.MOBILITY.value:
|
||||
self.mobility = model(session=self.session, _id=self.id)
|
||||
self.mobility.update_config(config)
|
||||
|
@ -1033,20 +1026,19 @@ class WlanNode(CoreNetwork):
|
|||
def update_mobility(self, config):
|
||||
if not self.mobility:
|
||||
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):
|
||||
if not self.model:
|
||||
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)
|
||||
self.model.set_configs(config, node_id=self.id)
|
||||
self.model.update_config(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.updateconfig()
|
||||
|
||||
def all_link_data(self, flags):
|
||||
"""
|
||||
|
|
|
@ -148,9 +148,7 @@ def split_args(args):
|
|||
:return: shell-like syntax list
|
||||
:rtype: list
|
||||
"""
|
||||
logging.info("split args: %s - %s", args, type(args))
|
||||
if isinstance(args, basestring):
|
||||
logging.info("splitting args")
|
||||
args = shlex.split(args)
|
||||
return args
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
}
|
||||
},
|
||||
"root": {
|
||||
"level": "DEBUG",
|
||||
"level": "INFO",
|
||||
"handlers": ["console"]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -458,18 +458,29 @@ class TestGrpc:
|
|||
# given
|
||||
client = CoreGrpcClient()
|
||||
session = grpc_server.coreemu.create_session()
|
||||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
wlan = session.add_node(_type=NodeTypes.WIRELESS_LAN)
|
||||
wlan.setmodel(BasicRangeModel, BasicRangeModel.default_values())
|
||||
session.instantiate()
|
||||
range_key = "range"
|
||||
range_value = "300"
|
||||
range_value = "50"
|
||||
|
||||
# then
|
||||
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
|
||||
assert response.result is True
|
||||
config = session.mobility.get_model_config(wlan.id, BasicRangeModel.name)
|
||||
assert config[range_key] == range_value
|
||||
assert wlan.model.range == int(range_value)
|
||||
|
||||
def test_get_emane_config(self, grpc_server):
|
||||
# given
|
||||
|
|
Loading…
Reference in a new issue