Thomas Vachuska
Committed by Gerrit Code Review

Corrected output of network configuration subjectKeys in JSON output; no longer …

…relies on subject.toString.

Change-Id: If4e07bc27cfaf8feb59397a5f104e5f663504f6e
......@@ -35,13 +35,13 @@ import static com.google.common.base.Strings.isNullOrEmpty;
description = "Manages network configuration")
public class NetworkConfigCommand extends AbstractShellCommand {
@Argument(index = 0, name = "subjectKey", description = "Subject key",
@Argument(index = 0, name = "subjectClassKey", description = "Subject class key",
required = false, multiValued = false)
String subjectKey = null;
String subjectClassKey = null;
@Argument(index = 1, name = "subject", description = "Subject",
@Argument(index = 1, name = "subjectKey", description = "Subject key",
required = false, multiValued = false)
String subject = null;
String subjectKey = null;
@Argument(index = 2, name = "configKey", description = "Config key",
required = false, multiValued = false)
......@@ -54,18 +54,18 @@ public class NetworkConfigCommand extends AbstractShellCommand {
protected void execute() {
service = get(NetworkConfigService.class);
JsonNode root = mapper.createObjectNode();
if (isNullOrEmpty(subjectKey)) {
if (isNullOrEmpty(subjectClassKey)) {
addAll((ObjectNode) root);
} else {
SubjectFactory subjectFactory = service.getSubjectFactory(subjectKey);
if (isNullOrEmpty(subject)) {
SubjectFactory subjectFactory = service.getSubjectFactory(subjectClassKey);
if (isNullOrEmpty(subjectKey)) {
addSubjectClass((ObjectNode) root, subjectFactory);
} else {
Object s = subjectFactory.createSubject(subject);
Object s = subjectFactory.createSubject(subjectKey);
if (isNullOrEmpty(configKey)) {
addSubject((ObjectNode) root, s);
} else {
root = getSubjectConfig(getConfig(s, subjectKey, configKey));
root = getSubjectConfig(getConfig(s, subjectClassKey, configKey));
}
}
}
......@@ -82,14 +82,14 @@ public class NetworkConfigCommand extends AbstractShellCommand {
service.getSubjectClasses()
.forEach(sc -> {
SubjectFactory sf = service.getSubjectFactory(sc);
addSubjectClass(newObject(root, sf.subjectKey()), sf);
addSubjectClass(newObject(root, sf.subjectClassKey()), sf);
});
}
@SuppressWarnings("unchecked")
private void addSubjectClass(ObjectNode root, SubjectFactory sf) {
service.getSubjects(sf.subjectClass())
.forEach(s -> addSubject(newObject(root, s.toString()), s));
.forEach(s -> addSubject(newObject(root, sf.subjectKey(s)), s));
}
private void addSubject(ObjectNode root, Object s) {
......
......@@ -42,7 +42,7 @@ public class NetworkConfigRegistryCommand extends AbstractShellCommand {
private void print(ConfigFactory configFactory) {
print(shortOnly ? SHORT_FMT : FMT,
configFactory.subjectFactory().subjectKey(),
configFactory.subjectFactory().subjectClassKey(),
configFactory.configKey(),
configFactory.subjectFactory().subjectClass().getName(),
configFactory.configClass().getName());
......
......@@ -41,27 +41,27 @@ public interface NetworkConfigService
/**
* Returns the subject factory with the specified key.
*
* @param subjectKey subject class key
* @param subjectClassKey subject class key
* @return subject class
*/
SubjectFactory getSubjectFactory(String subjectKey);
SubjectFactory getSubjectFactory(String subjectClassKey);
/**
* Returns the subject factory for the specified class.
*
* @param subjectClass subject class
* @return subject class key
* @return subject class factory
*/
SubjectFactory getSubjectFactory(Class subjectClass);
/**
* Returns the configuration class with the specified key.
*
* @param subjectKey subject class key
* @param configKey subject class name
* @param subjectClassKey subject class key
* @param configKey subject class name
* @return subject class
*/
Class<? extends Config> getConfigClass(String subjectKey, String configKey);
Class<? extends Config> getConfigClass(String subjectClassKey, String configKey);
/**
* Returns the set of subjects for which some configuration is available.
......
......@@ -28,7 +28,7 @@ import com.google.common.annotations.Beta;
public abstract class SubjectFactory<S> {
private final Class<S> subjectClass;
private final String subjectKey;
private final String subjectClassKey;
/**
* Creates a new configuration factory for the specified class of subjects
......@@ -36,12 +36,12 @@ public abstract class SubjectFactory<S> {
* subject and configuration class keys are used merely as keys for use in
* composite JSON trees.
*
* @param subjectClass subject class
* @param subjectKey subject class key
* @param subjectClass subject class
* @param subjectClassKey subject class key
*/
protected SubjectFactory(Class<S> subjectClass, String subjectKey) {
protected SubjectFactory(Class<S> subjectClass, String subjectClassKey) {
this.subjectClass = subjectClass;
this.subjectKey = subjectKey;
this.subjectClassKey = subjectClassKey;
}
/**
......@@ -60,8 +60,20 @@ public abstract class SubjectFactory<S> {
*
* @return configuration key
*/
public String subjectKey() {
return subjectKey;
public String subjectClassKey() {
return subjectClassKey;
}
/**
* Returns the unique key of the specified configuration subject.
* This is primarily aimed for use in composite JSON trees in external
* representations and has no bearing on the internal behaviours.
*
* @param subject specific subject
* @return subject key
*/
public String subjectKey(S subject) {
return subject.toString();
}
/**
......
......@@ -43,6 +43,10 @@ public final class SubjectFactories {
public ApplicationId createSubject(String key) {
return coreService.registerApplication(key);
}
@Override
public String subjectKey(ApplicationId subject) {
return subject.name();
}
};
public static final SubjectFactory<DeviceId> DEVICE_SUBJECT_FACTORY =
......@@ -59,6 +63,10 @@ public final class SubjectFactories {
public ConnectPoint createSubject(String key) {
return ConnectPoint.deviceConnectPoint(key);
}
@Override
public String subjectKey(ConnectPoint subject) {
return key(subject);
}
};
public static final SubjectFactory<HostId> HOST_SUBJECT_FACTORY =
......@@ -78,6 +86,10 @@ public final class SubjectFactories {
return LinkKey.linkKey(ConnectPoint.deviceConnectPoint(cps[0]),
ConnectPoint.deviceConnectPoint(cps[1]));
}
@Override
public String subjectKey(LinkKey subject) {
return key(subject.src()) + "-" + key(subject.dst());
}
};
/**
......@@ -90,4 +102,8 @@ public final class SubjectFactories {
coreService = service;
}
private static String key(ConnectPoint subject) {
return subject.deviceId() + "/" + subject.port();
}
}
......
......@@ -29,7 +29,7 @@ public class NetworkConfigServiceAdapter implements NetworkConfigService {
}
@Override
public SubjectFactory getSubjectFactory(String subjectKey) {
public SubjectFactory getSubjectFactory(String subjectClassKey) {
return null;
}
......@@ -39,7 +39,7 @@ public class NetworkConfigServiceAdapter implements NetworkConfigService {
}
@Override
public Class<? extends Config> getConfigClass(String subjectKey, String configKey) {
public Class<? extends Config> getConfigClass(String subjectClassKey, String configKey) {
return null;
}
......
......@@ -96,7 +96,7 @@ public class NetworkConfigManager
configClasses.put(identifier(configFactory), configFactory.configClass());
SubjectFactory subjectFactory = configFactory.subjectFactory();
subjectClasses.putIfAbsent(subjectFactory.subjectKey(), subjectFactory);
subjectClasses.putIfAbsent(subjectFactory.subjectClassKey(), subjectFactory);
subjectClassKeys.putIfAbsent(subjectFactory.subjectClass(), subjectFactory);
store.addConfigFactory(configFactory);
......@@ -145,8 +145,8 @@ public class NetworkConfigManager
}
@Override
public SubjectFactory getSubjectFactory(String subjectKey) {
return subjectClasses.get(subjectKey);
public SubjectFactory getSubjectFactory(String subjectClassKey) {
return subjectClasses.get(subjectClassKey);
}
@Override
......@@ -155,8 +155,8 @@ public class NetworkConfigManager
}
@Override
public Class<? extends Config> getConfigClass(String subjectKey, String configKey) {
return configClasses.get(new ConfigIdentifier(subjectKey, configKey));
public Class<? extends Config> getConfigClass(String subjectClassKey, String configKey) {
return configClasses.get(new ConfigIdentifier(subjectClassKey, configKey));
}
@Override
......@@ -255,7 +255,7 @@ public class NetworkConfigManager
}
private static ConfigIdentifier identifier(ConfigFactory factory) {
return new ConfigIdentifier(factory.subjectFactory().subjectKey(), factory.configKey());
return new ConfigIdentifier(factory.subjectFactory().subjectClassKey(), factory.configKey());
}
static final class ConfigIdentifier {
......
......@@ -49,73 +49,77 @@ public class NetworkConfigWebResource extends AbstractWebResource {
public Response download() {
NetworkConfigService service = get(NetworkConfigService.class);
ObjectNode root = mapper().createObjectNode();
service.getSubjectClasses().forEach(sc ->
produceJson(service, newObject(root, service.getSubjectFactory(sc).subjectKey()), sc));
service.getSubjectClasses().forEach(sc -> {
SubjectFactory subjectFactory = service.getSubjectFactory(sc);
produceJson(service, newObject(root, subjectFactory.subjectClassKey()),
subjectFactory, sc);
});
return ok(root).build();
}
/**
* Get all network configuration for a subject class.
*
* @param subjectKey subject class key
* @param subjectClassKey subject class key
* @return network configuration JSON
*/
@GET
@Path("{subjectKey}")
@Path("{subjectClassKey}")
@Produces(MediaType.APPLICATION_JSON)
@SuppressWarnings("unchecked")
public Response download(@PathParam("subjectKey") String subjectKey) {
public Response download(@PathParam("subjectClassKey") String subjectClassKey) {
NetworkConfigService service = get(NetworkConfigService.class);
ObjectNode root = mapper().createObjectNode();
produceJson(service, root, service.getSubjectFactory(subjectKey).subjectClass());
SubjectFactory subjectFactory = service.getSubjectFactory(subjectClassKey);
produceJson(service, root, subjectFactory, subjectFactory.subjectClass());
return ok(root).build();
}
/**
* Get all network configuration for a subject.
* Get all network configuration for a subjectKey.
*
* @param subjectKey subject class key
* @param subject subject key
* @param subjectClassKey subjectKey class key
* @param subjectKey subjectKey key
* @return network configuration JSON
*/
@GET
@Path("{subjectKey}/{subject}")
@Path("{subjectClassKey}/{subjectKey}")
@Produces(MediaType.APPLICATION_JSON)
@SuppressWarnings("unchecked")
public Response download(@PathParam("subjectKey") String subjectKey,
@PathParam("subject") String subject) {
public Response download(@PathParam("subjectClassKey") String subjectClassKey,
@PathParam("subjectKey") String subjectKey) {
NetworkConfigService service = get(NetworkConfigService.class);
ObjectNode root = mapper().createObjectNode();
produceSubjectJson(service, root,
service.getSubjectFactory(subjectKey).createSubject(subject));
SubjectFactory subjectFactory = service.getSubjectFactory(subjectClassKey);
produceSubjectJson(service, root, subjectFactory.createSubject(subjectKey));
return ok(root).build();
}
/**
* Get specific network configuration for a subject.
* Get specific network configuration for a subjectKey.
*
* @param subjectKey subject class key
* @param subject subject key
* @param configKey configuration class key
* @param subjectClassKey subjectKey class key
* @param subjectKey subjectKey key
* @param configKey configuration class key
* @return network configuration JSON
*/
@GET
@Path("{subjectKey}/{subject}/{configKey}")
@Path("{subjectClassKey}/{subjectKey}/{configKey}")
@Produces(MediaType.APPLICATION_JSON)
@SuppressWarnings("unchecked")
public Response download(@PathParam("subjectKey") String subjectKey,
@PathParam("subject") String subject,
public Response download(@PathParam("subjectClassKey") String subjectClassKey,
@PathParam("subjectKey") String subjectKey,
@PathParam("configKey") String configKey) {
NetworkConfigService service = get(NetworkConfigService.class);
return ok(service.getConfig(service.getSubjectFactory(subjectKey).createSubject(subject),
service.getConfigClass(subjectKey, configKey)).node()).build();
return ok(service.getConfig(service.getSubjectFactory(subjectClassKey).createSubject(subjectKey),
service.getConfigClass(subjectClassKey, configKey)).node()).build();
}
@SuppressWarnings("unchecked")
private void produceJson(NetworkConfigService service, ObjectNode node,
Class subjectClass) {
SubjectFactory subjectFactory, Class subjectClass) {
service.getSubjects(subjectClass).forEach(s ->
produceSubjectJson(service, newObject(node, s.toString()), s));
produceSubjectJson(service, newObject(node, subjectFactory.subjectKey(s)), s));
}
private void produceSubjectJson(NetworkConfigService service, ObjectNode node,
......@@ -128,8 +132,8 @@ public class NetworkConfigWebResource extends AbstractWebResource {
* Upload bulk network configuration.
*
* @param request network configuration JSON rooted at the top node
* @throws IOException if unable to parse the request
* @return empty response
* @throws IOException if unable to parse the request
*/
@POST
@Consumes(MediaType.APPLICATION_JSON)
......@@ -146,78 +150,78 @@ public class NetworkConfigWebResource extends AbstractWebResource {
/**
* Upload multiple network configurations for a subject class.
*
* @param subjectKey subject class key
* @param request network configuration JSON rooted at the top node
* @param subjectClassKey subject class key
* @param request network configuration JSON rooted at the top node
* @return empty response
* @throws IOException if unable to parse the request
*/
@POST
@Path("{subjectKey}")
@Path("{subjectClassKey}")
@Consumes(MediaType.APPLICATION_JSON)
@SuppressWarnings("unchecked")
public Response upload(@PathParam("subjectKey") String subjectKey,
public Response upload(@PathParam("subjectClassKey") String subjectClassKey,
InputStream request) throws IOException {
NetworkConfigService service = get(NetworkConfigService.class);
ObjectNode root = (ObjectNode) mapper().readTree(request);
consumeJson(service, root, service.getSubjectFactory(subjectKey));
consumeJson(service, root, service.getSubjectFactory(subjectClassKey));
return Response.ok().build();
}
/**
* Upload mutliple network configurations for a subject.
* Upload mutliple network configurations for a subjectKey.
*
* @param subjectKey subject class key
* @param subject subject key
* @param request network configuration JSON rooted at the top node
* @param subjectClassKey subjectKey class key
* @param subjectKey subjectKey key
* @param request network configuration JSON rooted at the top node
* @return empty response
* @throws IOException if unable to parse the request
*/
@POST
@Path("{subjectKey}/{subject}")
@Path("{subjectClassKey}/{subjectKey}")
@Consumes(MediaType.APPLICATION_JSON)
@SuppressWarnings("unchecked")
public Response upload(@PathParam("subjectKey") String subjectKey,
@PathParam("subject") String subject,
public Response upload(@PathParam("subjectClassKey") String subjectClassKey,
@PathParam("subjectKey") String subjectKey,
InputStream request) throws IOException {
NetworkConfigService service = get(NetworkConfigService.class);
ObjectNode root = (ObjectNode) mapper().readTree(request);
consumeSubjectJson(service, root,
service.getSubjectFactory(subjectKey).createSubject(subject),
subjectKey);
service.getSubjectFactory(subjectClassKey).createSubject(subjectKey),
subjectClassKey);
return Response.ok().build();
}
/**
* Upload specific network configuration for a subject.
* Upload specific network configuration for a subjectKey.
*
* @param subjectKey subject class key
* @param subject subject key
* @param configKey configuration class key
* @param request network configuration JSON rooted at the top node
* @param subjectClassKey subjectKey class key
* @param subjectKey subjectKey key
* @param configKey configuration class key
* @param request network configuration JSON rooted at the top node
* @return empty response
* @throws IOException if unable to parse the request
*/
@POST
@Path("{subjectKey}/{subject}/{configKey}")
@Path("{subjectClassKey}/{subjectKey}/{configKey}")
@Consumes(MediaType.APPLICATION_JSON)
@SuppressWarnings("unchecked")
public Response upload(@PathParam("subjectKey") String subjectKey,
@PathParam("subject") String subject,
public Response upload(@PathParam("subjectClassKey") String subjectClassKey,
@PathParam("subjectKey") String subjectKey,
@PathParam("configKey") String configKey,
InputStream request) throws IOException {
NetworkConfigService service = get(NetworkConfigService.class);
ObjectNode root = (ObjectNode) mapper().readTree(request);
service.applyConfig(service.getSubjectFactory(subjectKey).createSubject(subject),
service.getConfigClass(subjectKey, configKey), root);
service.applyConfig(service.getSubjectFactory(subjectClassKey).createSubject(subjectKey),
service.getConfigClass(subjectClassKey, configKey), root);
return Response.ok().build();
}
private void consumeJson(NetworkConfigService service, ObjectNode classNode,
SubjectFactory subjectFactory) {
classNode.fieldNames().forEachRemaining(s ->
consumeSubjectJson(service, (ObjectNode) classNode.path(s),
subjectFactory.createSubject(s),
subjectFactory.subjectKey()));
consumeSubjectJson(service, (ObjectNode) classNode.path(s),
subjectFactory.createSubject(s),
subjectFactory.subjectClassKey()));
}
private void consumeSubjectJson(NetworkConfigService service,
......@@ -225,7 +229,7 @@ public class NetworkConfigWebResource extends AbstractWebResource {
String subjectKey) {
subjectNode.fieldNames().forEachRemaining(c ->
service.applyConfig(subject, service.getConfigClass(subjectKey, c),
(ObjectNode) subjectNode.path(c)));
subjectNode.path(c)));
}
......@@ -241,64 +245,62 @@ public class NetworkConfigWebResource extends AbstractWebResource {
service.getSubjectClasses()
.forEach(subjectClass -> service.getSubjects(subjectClass)
.forEach(subject -> service.getConfigs(subject)
.forEach(config -> service
.removeConfig(subject, config.getClass()))));
.forEach(config -> service.removeConfig(subject, config.getClass()))));
return Response.ok().build();
}
/**
* Clear all network configurations for a subject class.
*
* @param subjectKey subject class key
* @param subjectClassKey subject class key
* @return empty response
*/
@DELETE
@Path("{subjectKey}")
@Path("{subjectClassKey}")
@SuppressWarnings("unchecked")
public Response delete(@PathParam("subjectKey") String subjectKey) {
public Response delete(@PathParam("subjectClassKey") String subjectClassKey) {
NetworkConfigService service = get(NetworkConfigService.class);
service.getSubjects(service.getSubjectFactory(subjectKey).getClass())
service.getSubjects(service.getSubjectFactory(subjectClassKey).getClass())
.forEach(subject -> service.getConfigs(subject)
.forEach(config -> service
.removeConfig(subject, config.getClass())));
.forEach(config -> service.removeConfig(subject, config.getClass())));
return Response.ok().build();
}
/**
* Clear all network configurations for a subject.
* Clear all network configurations for a subjectKey.
*
* @param subjectKey subject class key
* @param subject subject key
* @param subjectClassKey subjectKey class key
* @param subjectKey subjectKey key
* @return empty response
*/
@DELETE
@Path("{subjectKey}/{subject}")
@Path("{subjectClassKey}/{subjectKey}")
@SuppressWarnings("unchecked")
public Response delete(@PathParam("subjectKey") String subjectKey,
@PathParam("subject") String subject) {
public Response delete(@PathParam("subjectClassKey") String subjectClassKey,
@PathParam("subjectKey") String subjectKey) {
NetworkConfigService service = get(NetworkConfigService.class);
Object s = service.getSubjectFactory(subjectKey).createSubject(subject);
Object s = service.getSubjectFactory(subjectClassKey).createSubject(subjectKey);
service.getConfigs(s).forEach(c -> service.removeConfig(s, c.getClass()));
return Response.ok().build();
}
/**
* Clear specific network configuration for a subject.
* Clear specific network configuration for a subjectKey.
*
* @param subjectKey subject class key
* @param subject subject key
* @param configKey configuration class key
* @param subjectClassKey subjectKey class key
* @param subjectKey subjectKey key
* @param configKey configuration class key
* @return empty response
*/
@DELETE
@Path("{subjectKey}/{subject}/{configKey}")
@Path("{subjectClassKey}/{subjectKey}/{configKey}")
@SuppressWarnings("unchecked")
public Response delete(@PathParam("subjectKey") String subjectKey,
@PathParam("subject") String subject,
public Response delete(@PathParam("subjectClassKey") String subjectClassKey,
@PathParam("subjectKey") String subjectKey,
@PathParam("configKey") String configKey) {
NetworkConfigService service = get(NetworkConfigService.class);
service.removeConfig(service.getSubjectFactory(subjectKey).createSubject(subject),
service.getConfigClass(subjectKey, configKey));
service.removeConfig(service.getSubjectFactory(subjectClassKey).createSubject(subjectKey),
service.getConfigClass(subjectClassKey, configKey));
return Response.ok().build();
}
......