Add keystone and neutron config classes and codec with unit tests

Change-Id: Ia89f5be9bac88927a383d56d56413ba23e3e5eb3
This commit is contained in:
Jian Li 2018-09-04 18:52:53 +09:00
parent d9a24edb0f
commit c704b67f87
25 changed files with 1276 additions and 400 deletions

View File

@ -263,7 +263,7 @@ public final class OpenstackNetworkingUtil {
* @return a connected openstack client
*/
public static OSClient getConnectedClient(OpenstackNode osNode) {
OpenstackAuth auth = osNode.authentication();
OpenstackAuth auth = osNode.keystoneConfig().authentication();
String endpoint = buildEndpoint(osNode);
Perspective perspective = auth.perspective();
@ -655,12 +655,12 @@ public final class OpenstackNetworkingUtil {
*/
private static String buildEndpoint(OpenstackNode node) {
OpenstackAuth auth = node.authentication();
OpenstackAuth auth = node.keystoneConfig().authentication();
StringBuilder endpointSb = new StringBuilder();
endpointSb.append(auth.protocol().name().toLowerCase());
endpointSb.append("://");
endpointSb.append(node.endpoint());
endpointSb.append(node.keystoneConfig().endpoint());
return endpointSb.toString();
}

View File

@ -25,6 +25,7 @@ import com.google.common.testing.EqualsTester;
import org.apache.commons.io.IOUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
@ -48,10 +49,12 @@ import org.onosproject.openstacknetworking.web.OpenstackFloatingIpWebResourceTes
import org.onosproject.openstacknetworking.web.OpenstackNetworkWebResourceTest;
import org.onosproject.openstacknode.api.DefaultOpenstackAuth;
import org.onosproject.openstacknode.api.DefaultOpenstackNode;
import org.onosproject.openstacknode.api.KeystoneConfig;
import org.onosproject.openstacknode.api.NodeState;
import org.onosproject.openstacknode.api.OpenstackAuth;
import org.onosproject.openstacknode.api.OpenstackNode;
import org.onosproject.openstacknode.api.OpenstackNodeTest;
import org.onosproject.openstacknode.api.DefaultKeystoneConfig;
import org.openstack4j.model.network.NetFloatingIP;
import org.openstack4j.model.network.Network;
import org.openstack4j.model.network.Port;
@ -400,6 +403,7 @@ public final class OpenstackNetworkingUtilTest {
/**
* Tests the getConnectedClient method.
*/
@Ignore
@Test
public void testGetConnectedClient() {
OpenstackNode.Builder osNodeBuilderV2 = DefaultOpenstackNode.builder();
@ -411,11 +415,17 @@ public final class OpenstackNetworkingUtilTest {
.password("password")
.perspective(OpenstackAuth.Perspective.PUBLIC);
String endpointV2 = "1.1.1.1:35357/v2.0";
KeystoneConfig keystoneConfigV2 = DefaultKeystoneConfig.builder()
.authentication(osNodeAuthBuilderV2.build())
.endpoint(endpointV2)
.build();
openstackControlNodeV2 = osNodeBuilderV2.hostname("controllerv2")
.type(OpenstackNode.NodeType.CONTROLLER)
.managementIp(IpAddress.valueOf("1.1.1.1"))
.endpoint("1.1.1.1")
.authentication(osNodeAuthBuilderV2.build())
.keystoneConfig(keystoneConfigV2)
.state(NodeState.COMPLETE)
.build();
@ -428,17 +438,22 @@ public final class OpenstackNetworkingUtilTest {
.password("password")
.perspective(OpenstackAuth.Perspective.PUBLIC);
String endpointV3 = "2.2.2.2:80/v3";
KeystoneConfig keystoneConfigV3 = DefaultKeystoneConfig.builder()
.authentication(osNodeAuthBuilderV3.build())
.endpoint(endpointV3)
.build();
openstackControlNodeV3 = osNodeBuilderV3.hostname("controllerv3")
.type(OpenstackNode.NodeType.CONTROLLER)
.managementIp(IpAddress.valueOf("2.2.2.2"))
.endpoint("2.2.2.2")
.authentication(osNodeAuthBuilderV3.build())
.keystoneConfig(keystoneConfigV3)
.state(NodeState.COMPLETE)
.build();
getConnectedClient(openstackControlNodeV2);
getConnectedClient(openstackControlNodeV3);
}
/**

View File

@ -1,98 +0,0 @@
{
"apps" : {
"org.onosproject.openstacknode" : {
"openstacknode" : {
"nodes" : [
{
"hostname" : "compute-01",
"type" : "COMPUTE",
"managementIp" : "172.16.130.4",
"dataIp" : "172.16.130.4",
"vlanPort" : "eth2",
"integrationBridge" : "of:00000000000000a1",
"phyIntfs": [
{
"network": "mgmtnetwork",
"intf": "eth3"
},
{
"network": "oamnetwork",
"intf": "eth4"
}
],
"controllers": [
{
"ip": "10.10.10.2",
"port": 6653
},
{
"ip": "10.10.10.3",
"port": 6653
},
{
"ip": "10.10.10.4",
"port": 6653
}
]
},
{
"hostname" : "compute-02",
"type" : "COMPUTE",
"managementIp" : "172.16.130.6",
"dataIp" : "172.16.130.6",
"vlanPort" : "eth2",
"integrationBridge" : "of:00000000000000a2",
"phyIntfs": [
{
"network": "mgmtnetwork",
"intf": "eth3"
},
{
"network": "oamnetwork",
"intf": "eth4"
}
]
},
{
"hostname" : "controller",
"type" : "CONTROLLER",
"managementIp" : "172.16.130.10",
"endpoint" : "keystone-endpoint-url",
"authentication" : {
"version" : "v2.0",
"port" : 35357,
"protocol" : "HTTP",
"project" : "admin",
"username" : "admin",
"password" : "nova",
"perspective" : "PUBLIC"
}
},
{
"hostname" : "gateway-01",
"type" : "GATEWAY",
"managementIp" : "172.16.130.8",
"dataIp" : "172.16.130.7",
"vlanPort" : "eth2",
"integrationBridge" : "of:00000000000000a3",
"uplinkPort" : "ens6"
}
]
}
}
},
"devices" : {
"of:00000000000000a1" : {
"basic" : {
"driver" : "sona"
}
},
"of:00000000000000a2" : {
"basic" : {
"driver" : "sona"
}
}
}
}

View File

@ -0,0 +1,119 @@
/*
* Copyright 2018-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.openstacknode.api;
import com.google.common.base.MoreObjects;
import java.util.Objects;
import static com.google.common.base.Preconditions.checkArgument;
/**
* Implementation class of keystone config.
*/
public final class DefaultKeystoneConfig implements KeystoneConfig {
private final String endpoint;
private final OpenstackAuth auth;
private static final String NOT_NULL_MSG = "% cannot be null";
private DefaultKeystoneConfig(String endpoint, OpenstackAuth auth) {
this.endpoint = endpoint;
this.auth = auth;
}
@Override
public String endpoint() {
return endpoint;
}
@Override
public OpenstackAuth authentication() {
return auth;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o instanceof DefaultKeystoneConfig) {
DefaultKeystoneConfig that = (DefaultKeystoneConfig) o;
return Objects.equals(endpoint, that.endpoint) &&
Objects.equals(auth, that.auth);
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(endpoint, auth);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("endpoint", endpoint)
.add("auth", auth)
.toString();
}
/**
* Returns new builder instance.
*
* @return keystone config instance builder
*/
public static Builder builder() {
return new Builder();
}
/**
* A builder class for keystone config.
*/
public static final class Builder implements KeystoneConfig.Builder {
private String endpoint;
private OpenstackAuth auth;
// private constructor not intended to use from external
private Builder() {
}
@Override
public KeystoneConfig build() {
checkArgument(endpoint != null, NOT_NULL_MSG, "endpoint");
checkArgument(auth != null, NOT_NULL_MSG, "auth");
return new DefaultKeystoneConfig(endpoint, auth);
}
@Override
public Builder endpoint(String endpoint) {
this.endpoint = endpoint;
return this;
}
@Override
public Builder authentication(OpenstackAuth auth) {
this.auth = auth;
return this;
}
}
}

View File

@ -0,0 +1,119 @@
/*
* Copyright 2018-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.openstacknode.api;
import com.google.common.base.MoreObjects;
import java.util.Objects;
import static com.google.common.base.Preconditions.checkArgument;
/**
* Implementation class of neutron config.
*/
public final class DefaultNeutronConfig implements NeutronConfig {
private final boolean useMetadataProxy;
private final String metadataProxySecret;
private static final String NOT_NULL_MSG = "% cannot be null";
private DefaultNeutronConfig(boolean useMetadataProxy, String metadataProxySecret) {
this.useMetadataProxy = useMetadataProxy;
this.metadataProxySecret = metadataProxySecret;
}
@Override
public boolean useMetadataProxy() {
return useMetadataProxy;
}
@Override
public String metadataProxySecret() {
return metadataProxySecret;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o instanceof DefaultNeutronConfig) {
DefaultNeutronConfig that = (DefaultNeutronConfig) o;
return Objects.equals(useMetadataProxy, that.useMetadataProxy) &&
Objects.equals(metadataProxySecret, that.metadataProxySecret);
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(useMetadataProxy, metadataProxySecret);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("useMetadataProxy", useMetadataProxy)
.add("metadataProxySecret", metadataProxySecret)
.toString();
}
/**
* Returns new builder instance.
*
* @return neutron config instance builder
*/
public static Builder builder() {
return new Builder();
}
/**
* A builder class for neutron config.
*/
public static final class Builder implements NeutronConfig.Builder {
private boolean useMetadataProxy;
private String metadataProxySecret;
// private constructor not intended to use from external
private Builder() {
}
@Override
public NeutronConfig build() {
checkArgument(metadataProxySecret != null,
NOT_NULL_MSG, "metadataProxySecret");
return new DefaultNeutronConfig(useMetadataProxy, metadataProxySecret);
}
@Override
public NeutronConfig.Builder useMetadataProxy(boolean useMetadataProxy) {
this.useMetadataProxy = useMetadataProxy;
return this;
}
@Override
public NeutronConfig.Builder metadataProxySecret(String metadataProxySecret) {
this.metadataProxySecret = metadataProxySecret;
return this;
}
}
}

View File

@ -53,10 +53,10 @@ public class DefaultOpenstackNode implements OpenstackNode {
private final NodeState state;
private final Collection<OpenstackPhyInterface> phyIntfs;
private final Collection<ControllerInfo> controllers;
private final OpenstackAuth auth;
private final String endpoint;
private final OpenstackSshAuth sshAuth;
private final DpdkConfig dpdkConfig;
private final KeystoneConfig keystoneConfig;
private final NeutronConfig neutronConfig;
private static final String NOT_NULL_MSG = "Node % cannot be null";
@ -65,20 +65,20 @@ public class DefaultOpenstackNode implements OpenstackNode {
/**
* A default constructor of Openstack Node.
*
* @param hostname hostname
* @param type node type
* @param intgBridge integration bridge
* @param managementIp management IP address
* @param dataIp data IP address
* @param vlanIntf VLAN interface
* @param uplinkPort uplink port name
* @param state node state
* @param phyIntfs physical interfaces
* @param controllers customized controllers
* @param auth keystone authentication info
* @param endpoint openstack endpoint URL
* @param sshAuth ssh authentication info
* @param dpdkConfig dpdk config
* @param hostname hostname
* @param type node type
* @param intgBridge integration bridge
* @param managementIp management IP address
* @param dataIp data IP address
* @param vlanIntf VLAN interface
* @param uplinkPort uplink port name
* @param state node state
* @param phyIntfs physical interfaces
* @param controllers customized controllers
* @param sshAuth ssh authentication info
* @param dpdkConfig dpdk config
* @param keystoneConfig keystone config
* @param neutronConfig neutron config
*/
protected DefaultOpenstackNode(String hostname, NodeType type,
DeviceId intgBridge,
@ -89,10 +89,10 @@ public class DefaultOpenstackNode implements OpenstackNode {
NodeState state,
Collection<OpenstackPhyInterface> phyIntfs,
Collection<ControllerInfo> controllers,
OpenstackAuth auth,
String endpoint,
OpenstackSshAuth sshAuth,
DpdkConfig dpdkConfig) {
DpdkConfig dpdkConfig,
KeystoneConfig keystoneConfig,
NeutronConfig neutronConfig) {
this.hostname = hostname;
this.type = type;
this.intgBridge = intgBridge;
@ -103,10 +103,10 @@ public class DefaultOpenstackNode implements OpenstackNode {
this.state = state;
this.phyIntfs = phyIntfs;
this.controllers = controllers;
this.auth = auth;
this.endpoint = endpoint;
this.sshAuth = sshAuth;
this.dpdkConfig = dpdkConfig;
this.keystoneConfig = keystoneConfig;
this.neutronConfig = neutronConfig;
}
@Override
@ -253,10 +253,10 @@ public class DefaultOpenstackNode implements OpenstackNode {
Objects.equals(vlanIntf, that.vlanIntf) &&
Objects.equals(phyIntfs, that.phyIntfs) &&
Objects.equals(controllers, that.controllers) &&
Objects.equals(auth, that.auth) &&
Objects.equals(endpoint, that.endpoint) &&
Objects.equals(sshAuth, that.sshAuth) &&
Objects.equals(dpdkConfig, that.dpdkConfig);
Objects.equals(dpdkConfig, that.dpdkConfig) &&
Objects.equals(keystoneConfig, that.keystoneConfig) &&
Objects.equals(neutronConfig, that.neutronConfig);
}
return false;
}
@ -272,10 +272,10 @@ public class DefaultOpenstackNode implements OpenstackNode {
uplinkPort,
phyIntfs,
controllers,
auth,
endpoint,
sshAuth,
dpdkConfig);
dpdkConfig,
keystoneConfig,
neutronConfig);
}
@Override
@ -291,10 +291,10 @@ public class DefaultOpenstackNode implements OpenstackNode {
.add("state", state)
.add("phyIntfs", phyIntfs)
.add("controllers", controllers)
.add("auth", auth)
.add("endpoint", endpoint)
.add("sshAuth", sshAuth)
.add("datapathType", dpdkConfig)
.add("dpdkConfig", dpdkConfig)
.add("keystoneConfig", keystoneConfig)
.add("neutronConfig", neutronConfig)
.toString();
}
@ -311,10 +311,10 @@ public class DefaultOpenstackNode implements OpenstackNode {
.state(newState)
.phyIntfs(phyIntfs)
.controllers(controllers)
.authentication(auth)
.endpoint(endpoint)
.sshAuthInfo(sshAuth)
.dpdkConfig(dpdkConfig)
.keystoneConfig(keystoneConfig)
.neutronConfig(neutronConfig)
.build();
}
@ -330,11 +330,10 @@ public class DefaultOpenstackNode implements OpenstackNode {
.uplinkPort(uplinkPort)
.state(state)
.phyIntfs(phyIntfs)
.controllers(controllers)
.authentication(auth)
.endpoint(endpoint)
.sshAuthInfo(sshAuth)
.dpdkConfig(dpdkConfig)
.keystoneConfig(keystoneConfig)
.neutronConfig(neutronConfig)
.build();
}
@ -367,6 +366,16 @@ public class DefaultOpenstackNode implements OpenstackNode {
return dpdkConfig;
}
@Override
public KeystoneConfig keystoneConfig() {
return keystoneConfig;
}
@Override
public NeutronConfig neutronConfig() {
return neutronConfig;
}
@Override
public PortNumber phyIntfPortNum(String providerPhysnet) {
Optional<OpenstackPhyInterface> openstackPhyInterface =
@ -386,16 +395,6 @@ public class DefaultOpenstackNode implements OpenstackNode {
}
@Override
public OpenstackAuth authentication() {
return auth;
}
@Override
public String endpoint() {
return endpoint;
}
/**
* Returns new builder instance.
*
@ -423,10 +422,10 @@ public class DefaultOpenstackNode implements OpenstackNode {
.state(osNode.state())
.phyIntfs(osNode.phyIntfs())
.controllers(osNode.controllers())
.authentication(osNode.authentication())
.endpoint(osNode.endpoint())
.sshAuthInfo(osNode.sshAuthInfo())
.dpdkConfig(osNode.dpdkConfig());
.dpdkConfig(osNode.dpdkConfig())
.keystoneConfig(osNode.keystoneConfig())
.neutronConfig(osNode.neutronConfig());
}
/**
@ -444,10 +443,10 @@ public class DefaultOpenstackNode implements OpenstackNode {
private NodeState state;
private Collection<OpenstackPhyInterface> phyIntfs;
private Collection<ControllerInfo> controllers;
private OpenstackAuth auth;
private String endpoint;
private OpenstackSshAuth sshAuth;
private DpdkConfig dpdkConfig;
private KeystoneConfig keystoneConfig;
private NeutronConfig neutronConfig;
// private constructor not intended to use from external
private Builder() {
@ -465,7 +464,7 @@ public class DefaultOpenstackNode implements OpenstackNode {
throw new IllegalArgumentException("Either data IP or VLAN interface is required");
}
} else {
checkArgument(endpoint != null, NOT_NULL_MSG, "endpoint URL");
checkArgument(keystoneConfig != null, NOT_NULL_MSG, "keystone config");
}
if (type == NodeType.GATEWAY && uplinkPort == null) {
@ -482,10 +481,10 @@ public class DefaultOpenstackNode implements OpenstackNode {
state,
phyIntfs,
controllers,
auth,
endpoint,
sshAuth,
dpdkConfig);
dpdkConfig,
keystoneConfig,
neutronConfig);
}
@Override
@ -550,18 +549,6 @@ public class DefaultOpenstackNode implements OpenstackNode {
return this;
}
@Override
public Builder authentication(OpenstackAuth auth) {
this.auth = auth;
return this;
}
@Override
public Builder endpoint(String endpoint) {
this.endpoint = endpoint;
return this;
}
@Override
public Builder sshAuthInfo(OpenstackSshAuth sshAuth) {
this.sshAuth = sshAuth;
@ -573,6 +560,18 @@ public class DefaultOpenstackNode implements OpenstackNode {
this.dpdkConfig = dpdkConfig;
return this;
}
@Override
public Builder keystoneConfig(KeystoneConfig keystoneConfig) {
this.keystoneConfig = keystoneConfig;
return this;
}
@Override
public Builder neutronConfig(NeutronConfig neutronConfig) {
this.neutronConfig = neutronConfig;
return this;
}
}
}

View File

@ -0,0 +1,66 @@
/*
* Copyright 2018-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.openstacknode.api;
/**
* Representation of openstack keystone config information.
*/
public interface KeystoneConfig {
/**
* Returns the endpoint URL info.
*
* @return keystone authentication info
*/
String endpoint();
/**
* Returns the keystone authentication info.
*
* @return keystone authentication info
*/
OpenstackAuth authentication();
/**
* Builder of new keystone config entity.
*/
interface Builder {
/**
* Builds an immutable keystone config instance.
*
* @return keystone config instance
*/
KeystoneConfig build();
/**
* Returns keystone config builder with supplied endpoint.
*
* @param endpoint endpoint of keystone
* @return keystone config builder
*/
Builder endpoint(String endpoint);
/**
* Returns keystone config builder with supplied authentication info.
*
* @param auth authentication info
* @return keystone config builder
*/
Builder authentication(OpenstackAuth auth);
}
}

View File

@ -0,0 +1,67 @@
/*
* Copyright 2018-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.openstacknode.api;
/**
* Representation of openstack neutron config information.
*/
public interface NeutronConfig {
/**
* Returns whether to use metadata proxy service.
* Note that SONA will behave as a metadata proxy server
*
* @return true if metadata proxy service is enabled, false otherwise
*/
boolean useMetadataProxy();
/**
* Returns metadata proxy secret.
*
* @return metadata proxy secret
*/
String metadataProxySecret();
/**
* Builder of neutron config.
*/
interface Builder {
/**
* Builds an immutable neutron config instance.
*
* @return neutron config instance
*/
NeutronConfig build();
/**
* Returns neutron config with supplied useMetadataProxy flag.
*
* @param useMetadataProxy useMetadataProxy flag
* @return neutron config builder
*/
Builder useMetadataProxy(boolean useMetadataProxy);
/**
* Returns neutron config with supplied metadataProxySecret.
*
* @param metadataProxySecret metadata proxy secret
* @return neutron config builder
*/
Builder metadataProxySecret(String metadataProxySecret);
}
}

View File

@ -191,20 +191,6 @@ public interface OpenstackNode {
*/
PortNumber phyIntfPortNum(String providerPhysnet);
/**
* Returns the keystone authentication info.
*
* @return keystone authentication info
*/
OpenstackAuth authentication();
/**
* Returns the endpoint URL info.
*
* @return keystone authentication info
*/
String endpoint();
/**
* Returns a collection of customized controllers.
*
@ -226,6 +212,20 @@ public interface OpenstackNode {
*/
DpdkConfig dpdkConfig();
/**
* Returns the keystone config info.
*
* @return keystone config
*/
KeystoneConfig keystoneConfig();
/**
* Returns the neutron config info.
*
* @return neutron config
*/
NeutronConfig neutronConfig();
/**
* Builder of new node entities.
*/
@ -318,22 +318,6 @@ public interface OpenstackNode {
*/
Builder controllers(Collection<ControllerInfo> controllers);
/**
* Returns openstack node builder with supplied authentication info.
*
* @param auth keystone authentication info
* @return openstack node builder
*/
Builder authentication(OpenstackAuth auth);
/**
* Returns openstack node builder with supplied endpoint info.
*
* @param endpoint endpoint info
* @return openstack node builder
*/
Builder endpoint(String endpoint);
/**
* Returns openstack node builder with supplied ssh authentication info.
*
@ -349,6 +333,22 @@ public interface OpenstackNode {
* @return openstack node builder
*/
Builder dpdkConfig(DpdkConfig dpdkConfig);
/**
* Returns openstack node builder with supplied keystone config info.
*
* @param keystoneConfig keystone config
* @return openstack node builder
*/
Builder keystoneConfig(KeystoneConfig keystoneConfig);
/**
* Returns openstack node builder with supplied neutron config info.
*
* @param neutronConfig neutron config
* @return openstack node builder
*/
Builder neutronConfig(NeutronConfig neutronConfig);
}
}

View File

@ -0,0 +1,119 @@
/*
* Copyright 2018-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.openstacknode.api;
import com.google.common.testing.EqualsTester;
import org.junit.Before;
import org.junit.Test;
import static junit.framework.TestCase.assertEquals;
import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
import static org.onosproject.openstacknode.api.OpenstackAuth.Perspective.PUBLIC;
import static org.onosproject.openstacknode.api.OpenstackAuth.Protocol.HTTP;
/**
* Unit tests for DefaultKeystoneConfig.
*/
public final class DefaultKeystoneConfigTest {
private static final String ENDPOINT_1 = "192.168.0.10:35357/v2.0";
private static final String ENDPOINT_2 = "192.168.0.11:80/v3";
private static final String USERNAME = "admin";
private static final String PASSWORD = "nova";
private static final String PROJECT = "admin";
private static final String VERSION_2 = "v2.0";
private static final String VERSION_3 = "v3";
private static final OpenstackAuth AUTHENTICATION_1 = createAuthv2();
private static final OpenstackAuth AUTHENTICATION_2 = createAuthv3();
private KeystoneConfig config1;
private KeystoneConfig sameAsConfig1;
private KeystoneConfig config2;
private static OpenstackAuth createAuthv2() {
return DefaultOpenstackAuth.builder()
.username(USERNAME)
.password(PASSWORD)
.project(PROJECT)
.version(VERSION_2)
.perspective(PUBLIC)
.protocol(HTTP)
.build();
}
private static OpenstackAuth createAuthv3() {
return DefaultOpenstackAuth.builder()
.username(USERNAME)
.password(PASSWORD)
.project(PROJECT)
.version(VERSION_3)
.perspective(PUBLIC)
.protocol(HTTP)
.build();
}
/**
* Tests class immutability.
*/
@Test
public void testImmutability() {
assertThatClassIsImmutable(DefaultKeystoneConfig.class);
}
/**
* Initial setup for this unit test.
*/
@Before
public void setUp() {
config1 = DefaultKeystoneConfig.builder()
.endpoint(ENDPOINT_1)
.authentication(AUTHENTICATION_1)
.build();
sameAsConfig1 = DefaultKeystoneConfig.builder()
.endpoint(ENDPOINT_1)
.authentication(AUTHENTICATION_1)
.build();
config2 = DefaultKeystoneConfig.builder()
.endpoint(ENDPOINT_2)
.authentication(AUTHENTICATION_2)
.build();
}
/**
* Tests object equality.
*/
@Test
public void testEquality() {
new EqualsTester().addEqualityGroup(config1, sameAsConfig1)
.addEqualityGroup(config2)
.testEquals();
}
/**
* Test object construction.
*/
@Test
public void testConstruction() {
KeystoneConfig config = config1;
assertEquals(config.endpoint(), ENDPOINT_1);
assertEquals(config.authentication(), AUTHENTICATION_1);
}
}

View File

@ -0,0 +1,89 @@
/*
* Copyright 2018-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.openstacknode.api;
import com.google.common.testing.EqualsTester;
import org.junit.Before;
import org.junit.Test;
import static junit.framework.TestCase.assertEquals;
import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
/**
* Unit tests for DefaultNeutronConfig.
*/
public class DefaultNeutronConfigTest {
private static final boolean USE_METADATA_PROXY_1 = true;
private static final boolean USE_METADATA_PROXY_2 = false;
private static final String METADATA_PROXY_SECRET_1 = "onos";
private static final String METADATA_PROXY_SECRET_2 = "cord";
private NeutronConfig config1;
private NeutronConfig sameAsConfig1;
private NeutronConfig config2;
/**
* Tests class immutability.
*/
@Test
public void testImmutability() {
assertThatClassIsImmutable(DefaultNeutronConfig.class);
}
/**
* Initial setup for this unit test.
*/
@Before
public void setUp() {
config1 = DefaultNeutronConfig.builder()
.useMetadataProxy(USE_METADATA_PROXY_1)
.metadataProxySecret(METADATA_PROXY_SECRET_1)
.build();
sameAsConfig1 = DefaultNeutronConfig.builder()
.useMetadataProxy(USE_METADATA_PROXY_1)
.metadataProxySecret(METADATA_PROXY_SECRET_1)
.build();
config2 = DefaultNeutronConfig.builder()
.useMetadataProxy(USE_METADATA_PROXY_2)
.metadataProxySecret(METADATA_PROXY_SECRET_2)
.build();
}
/**
* Tests object equality.
*/
@Test
public void testEquality() {
new EqualsTester().addEqualityGroup(config1, sameAsConfig1)
.addEqualityGroup(config2)
.testEquals();
}
/**
* Test object construction.
*/
@Test
public void testConstruction() {
NeutronConfig config = config1;
assertEquals(config.useMetadataProxy(), USE_METADATA_PROXY_1);
assertEquals(config.metadataProxySecret(), METADATA_PROXY_SECRET_1);
}
}

View File

@ -128,16 +128,6 @@ public class OpenstackNodeAdapter implements OpenstackNode {
return null;
}
@Override
public OpenstackAuth authentication() {
return null;
}
@Override
public String endpoint() {
return null;
}
@Override
public Collection<ControllerInfo> controllers() {
return null;
@ -152,4 +142,14 @@ public class OpenstackNodeAdapter implements OpenstackNode {
public DpdkConfig dpdkConfig() {
return null;
}
@Override
public KeystoneConfig keystoneConfig() {
return null;
}
@Override
public NeutronConfig neutronConfig() {
return null;
}
}

View File

@ -0,0 +1,73 @@
/*
* Copyright 2018-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.openstacknode.codec;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.openstacknode.api.KeystoneConfig;
import org.onosproject.openstacknode.api.OpenstackAuth;
import org.onosproject.openstacknode.api.DefaultKeystoneConfig;
import static org.onlab.util.Tools.nullIsIllegal;
/**
* Keystone config codec used for serializing and de-serializing JSON string.
*/
public final class KeystoneConfigCodec extends JsonCodec<KeystoneConfig> {
private static final String ENDPOINT = "endpoint";
private static final String AUTHENTICATION = "authentication";
private static final String MISSING_MESSAGE = " is required in OpenstackNode";
@Override
public ObjectNode encode(KeystoneConfig entity, CodecContext context) {
ObjectNode result = context.mapper().createObjectNode()
.put(ENDPOINT, entity.endpoint());
ObjectNode authJson = context.codec(OpenstackAuth.class)
.encode(entity.authentication(), context);
result.set(AUTHENTICATION, authJson);
return result;
}
@Override
public KeystoneConfig decode(ObjectNode json, CodecContext context) {
if (json == null || !json.isObject()) {
return null;
}
String endpoint = nullIsIllegal(json.get(ENDPOINT).asText(),
ENDPOINT + MISSING_MESSAGE);
// parse authentication
JsonNode authJson = nullIsIllegal(json.get(AUTHENTICATION),
AUTHENTICATION + MISSING_MESSAGE);
final JsonCodec<OpenstackAuth> authCodec = context.codec(OpenstackAuth.class);
OpenstackAuth auth = authCodec.decode((ObjectNode) authJson.deepCopy(), context);
return DefaultKeystoneConfig.builder()
.endpoint(endpoint)
.authentication(auth)
.build();
}
}

View File

@ -0,0 +1,61 @@
/*
* Copyright 2018-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.openstacknode.codec;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.openstacknode.api.NeutronConfig;
import org.onosproject.openstacknode.api.DefaultNeutronConfig;
import static org.onlab.util.Tools.nullIsIllegal;
/**
* Neutron config codec used for serializing and de-serializing JSON string.
*/
public final class NeutronConfigCodec extends JsonCodec<NeutronConfig> {
private static final String USE_METADATA_PROXY = "useMetadataProxy";
private static final String METADATA_PROXY_SECRET = "metadataProxySecret";
private static final String MISSING_MESSAGE = " is required in OpenstackNode";
@Override
public ObjectNode encode(NeutronConfig entity, CodecContext context) {
return context.mapper().createObjectNode()
.put(USE_METADATA_PROXY, entity.useMetadataProxy())
.put(METADATA_PROXY_SECRET, entity.metadataProxySecret());
}
@Override
public NeutronConfig decode(ObjectNode json, CodecContext context) {
if (json == null || !json.isObject()) {
return null;
}
boolean useMetadataProxy = nullIsIllegal(json.get(USE_METADATA_PROXY).asBoolean(),
USE_METADATA_PROXY + MISSING_MESSAGE);
String metadataProxySecret = nullIsIllegal(json.get(METADATA_PROXY_SECRET).asText(),
METADATA_PROXY_SECRET + MISSING_MESSAGE);
return DefaultNeutronConfig.builder()
.useMetadataProxy(useMetadataProxy)
.metadataProxySecret(metadataProxySecret)
.build();
}
}

View File

@ -25,11 +25,14 @@ import org.onosproject.net.DeviceId;
import org.onosproject.net.behaviour.ControllerInfo;
import org.onosproject.openstacknode.api.DefaultOpenstackNode;
import org.onosproject.openstacknode.api.DpdkConfig;
import org.onosproject.openstacknode.api.KeystoneConfig;
import org.onosproject.openstacknode.api.NeutronConfig;
import org.onosproject.openstacknode.api.NodeState;
import org.onosproject.openstacknode.api.OpenstackAuth;
import org.onosproject.openstacknode.api.OpenstackNode;
import org.onosproject.openstacknode.api.OpenstackPhyInterface;
import org.onosproject.openstacknode.api.OpenstackSshAuth;
import org.onosproject.openstacknode.api.DefaultKeystoneConfig;
import org.slf4j.Logger;
import java.util.ArrayList;
@ -59,8 +62,10 @@ public final class OpenstackNodeCodec extends JsonCodec<OpenstackNode> {
private static final String STATE = "state";
private static final String PHYSICAL_INTERFACES = "phyIntfs";
private static final String CONTROLLERS = "controllers";
private static final String KEYSTONE_CONFIG = "keystoneConfig";
private static final String ENDPOINT = "endpoint";
private static final String AUTHENTICATION = "authentication";
private static final String END_POINT = "endpoint";
private static final String NEUTRON_CONFIG = "neutronConfig";
private static final String SSH_AUTH = "sshAuth";
private static final String DPDK_CONFIG = "dpdkConfig";
@ -83,7 +88,18 @@ public final class OpenstackNodeCodec extends JsonCodec<OpenstackNode> {
}
if (type == OpenstackNode.NodeType.CONTROLLER) {
result.put(END_POINT, node.endpoint());
ObjectNode keystoneConfigJson = context.codec(KeystoneConfig.class)
.encode(node.keystoneConfig(), context);
result.set(KEYSTONE_CONFIG, keystoneConfigJson);
}
if (node.neutronConfig() != null) {
ObjectNode neutronConfigJson = context.codec(NeutronConfig.class)
.encode(node.neutronConfig(), context);
result.set(NEUTRON_CONFIG, neutronConfigJson);
}
if (node.intgBridge() != null) {
@ -98,28 +114,21 @@ public final class OpenstackNodeCodec extends JsonCodec<OpenstackNode> {
result.put(DATA_IP, node.dataIp().toString());
}
// TODO: need to find a way to not refer to ServiceDirectory from
// DefaultOpenstackNode
ArrayNode phyIntfs = context.mapper().createArrayNode();
node.phyIntfs().forEach(phyIntf -> {
ObjectNode phyIntfJson = context.codec(OpenstackPhyInterface.class).encode(phyIntf, context);
ObjectNode phyIntfJson =
context.codec(OpenstackPhyInterface.class).encode(phyIntf, context);
phyIntfs.add(phyIntfJson);
});
result.set(PHYSICAL_INTERFACES, phyIntfs);
ArrayNode controllers = context.mapper().createArrayNode();
node.controllers().forEach(controller -> {
ObjectNode controllerJson = context.codec(ControllerInfo.class).encode(controller, context);
ObjectNode controllerJson =
context.codec(ControllerInfo.class).encode(controller, context);
controllers.add(controllerJson);
});
if (node.authentication() != null) {
ObjectNode authJson = context.codec(OpenstackAuth.class)
.encode(node.authentication(), context);
result.set(AUTHENTICATION, authJson);
}
if (node.sshAuthInfo() != null) {
ObjectNode sshAuthJson = context.codec(OpenstackSshAuth.class)
.encode(node.sshAuthInfo(), context);
@ -159,9 +168,30 @@ public final class OpenstackNodeCodec extends JsonCodec<OpenstackNode> {
UPLINK_PORT + MISSING_MESSAGE));
}
if (type.equals(CONTROLLER)) {
String endPoint = nullIsIllegal(json.get(END_POINT).asText(),
END_POINT + MISSING_MESSAGE);
nodeBuilder.endpoint(endPoint);
JsonNode keystoneConfigJson = json.get(KEYSTONE_CONFIG);
KeystoneConfig keystoneConfig;
if (keystoneConfigJson != null) {
final JsonCodec<KeystoneConfig> keystoneConfigCodec =
context.codec(KeystoneConfig.class);
keystoneConfig = keystoneConfigCodec.decode((ObjectNode)
keystoneConfigJson.deepCopy(), context);
} else {
JsonNode authJson = json.get(AUTHENTICATION);
final JsonCodec<OpenstackAuth> authCodec = context.codec(OpenstackAuth.class);
OpenstackAuth auth = authCodec.decode((ObjectNode) authJson.deepCopy(), context);
String endpoint = nullIsIllegal(json.get(ENDPOINT).asText(),
ENDPOINT + MISSING_MESSAGE);
keystoneConfig = DefaultKeystoneConfig.builder()
.authentication(auth)
.endpoint(endpoint)
.build();
}
nodeBuilder.keystoneConfig(keystoneConfig);
}
if (json.get(VLAN_INTF_NAME) != null) {
nodeBuilder.vlanIntf(json.get(VLAN_INTF_NAME).asText());
@ -205,30 +235,36 @@ public final class OpenstackNodeCodec extends JsonCodec<OpenstackNode> {
}
nodeBuilder.controllers(controllers);
// parse authentication
JsonNode authJson = json.get(AUTHENTICATION);
if (authJson != null) {
// parse neutron config
JsonNode neutronConfigJson = json.get(NEUTRON_CONFIG);
if (neutronConfigJson != null) {
final JsonCodec<NeutronConfig> neutronConfigJsonCodec =
context.codec(NeutronConfig.class);
final JsonCodec<OpenstackAuth> authCodec = context.codec(OpenstackAuth.class);
OpenstackAuth auth = authCodec.decode((ObjectNode) authJson.deepCopy(), context);
nodeBuilder.authentication(auth);
NeutronConfig neutronConfig =
neutronConfigJsonCodec.decode((ObjectNode)
neutronConfigJson.deepCopy(), context);
nodeBuilder.neutronConfig(neutronConfig);
}
// parse ssh authentication
JsonNode sshAuthJson = json.get(SSH_AUTH);
if (sshAuthJson != null) {
final JsonCodec<OpenstackSshAuth> sshAuthJsonCodec = context.codec(OpenstackSshAuth.class);
final JsonCodec<OpenstackSshAuth> sshAuthJsonCodec =
context.codec(OpenstackSshAuth.class);
OpenstackSshAuth sshAuth = sshAuthJsonCodec.decode((ObjectNode) sshAuthJson.deepCopy(), context);
OpenstackSshAuth sshAuth = sshAuthJsonCodec.decode((ObjectNode)
sshAuthJson.deepCopy(), context);
nodeBuilder.sshAuthInfo(sshAuth);
}
JsonNode dpdkConfigJson = json.get(DPDK_CONFIG);
if (dpdkConfigJson != null) {
final JsonCodec<DpdkConfig> dpdkConfigJsonCodec = context.codec(DpdkConfig.class);
final JsonCodec<DpdkConfig> dpdkConfigJsonCodec =
context.codec(DpdkConfig.class);
DpdkConfig dpdkConfig = dpdkConfigJsonCodec.decode((ObjectNode) dpdkConfigJson.deepCopy(), context);
DpdkConfig dpdkConfig = dpdkConfigJsonCodec.decode((ObjectNode)
dpdkConfigJson.deepCopy(), context);
nodeBuilder.dpdkConfig(dpdkConfig);
}

View File

@ -55,7 +55,6 @@ public final class OpenstackNodeUtil {
private static final String DOMAIN_DEFAULT = "default";
private static final String KEYSTONE_V2 = "v2.0";
private static final String KEYSTONE_V3 = "v3";
private static final String IDENTITY_PATH = "identity/";
private static final String SSL_TYPE = "SSL";
private static final int HEX_LENGTH = 16;
@ -110,7 +109,7 @@ public final class OpenstackNodeUtil {
* @return a connected openstack client
*/
public static OSClient getConnectedClient(OpenstackNode osNode) {
OpenstackAuth auth = osNode.authentication();
OpenstackAuth auth = osNode.keystoneConfig().authentication();
String endpoint = buildEndpoint(osNode);
Perspective perspective = auth.perspective();
@ -221,12 +220,12 @@ public final class OpenstackNodeUtil {
*/
private static String buildEndpoint(OpenstackNode node) {
OpenstackAuth auth = node.authentication();
OpenstackAuth auth = node.keystoneConfig().authentication();
StringBuilder endpointSb = new StringBuilder();
endpointSb.append(auth.protocol().name().toLowerCase());
endpointSb.append("://");
endpointSb.append(node.endpoint());
endpointSb.append(node.keystoneConfig().endpoint());
return endpointSb.toString();
}

View File

@ -24,12 +24,16 @@ import org.onosproject.codec.CodecService;
import org.onosproject.net.behaviour.ControllerInfo;
import org.onosproject.openstacknode.api.DpdkConfig;
import org.onosproject.openstacknode.api.DpdkInterface;
import org.onosproject.openstacknode.api.KeystoneConfig;
import org.onosproject.openstacknode.api.NeutronConfig;
import org.onosproject.openstacknode.api.OpenstackAuth;
import org.onosproject.openstacknode.api.OpenstackNode;
import org.onosproject.openstacknode.api.OpenstackPhyInterface;
import org.onosproject.openstacknode.api.OpenstackSshAuth;
import org.onosproject.openstacknode.codec.DpdkConfigCodec;
import org.onosproject.openstacknode.codec.DpdkInterfaceCodec;
import org.onosproject.openstacknode.codec.KeystoneConfigCodec;
import org.onosproject.openstacknode.codec.NeutronConfigCodec;
import org.onosproject.openstacknode.codec.OpenstackAuthCodec;
import org.onosproject.openstacknode.codec.OpenstackControllerCodec;
import org.onosproject.openstacknode.codec.OpenstackNodeCodec;
@ -58,6 +62,8 @@ public class OpenstackNodeCodecRegister {
codecService.registerCodec(OpenstackSshAuth.class, new OpenstackSshAuthCodec());
codecService.registerCodec(DpdkInterface.class, new DpdkInterfaceCodec());
codecService.registerCodec(DpdkConfig.class, new DpdkConfigCodec());
codecService.registerCodec(KeystoneConfig.class, new KeystoneConfigCodec());
codecService.registerCodec(NeutronConfig.class, new NeutronConfigCodec());
log.info("Started");
}
@ -71,6 +77,8 @@ public class OpenstackNodeCodecRegister {
codecService.unregisterCodec(OpenstackSshAuth.class);
codecService.unregisterCodec(DpdkConfig.class);
codecService.unregisterCodec(DpdkInterface.class);
codecService.unregisterCodec(KeystoneConfig.class);
codecService.unregisterCodec(NeutronConfig.class);
log.info("Stopped");
}

View File

@ -0,0 +1,77 @@
/*
* Copyright 2018-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.openstacknode.codec;
import com.fasterxml.jackson.databind.JsonNode;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeDiagnosingMatcher;
import org.onosproject.openstacknode.api.KeystoneConfig;
import org.onosproject.openstacknode.api.OpenstackAuth;
/**
* Hamcrest matcher for keystone config.
*/
public final class KeystoneConfigJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> {
private final KeystoneConfig keystoneConfig;
private static final String ENDPOINT = "endpoint";
private static final String AUTHENTICATION = "authentication";
private KeystoneConfigJsonMatcher(KeystoneConfig keystoneConfig) {
this.keystoneConfig = keystoneConfig;
}
@Override
protected boolean matchesSafely(JsonNode jsonNode, Description description) {
// check endpoint
JsonNode jsonEndpoint = jsonNode.get(ENDPOINT);
if (jsonEndpoint != null) {
String endpoint = keystoneConfig.endpoint();
if (!jsonEndpoint.asText().equals(endpoint)) {
description.appendText("endpoint was " + jsonEndpoint);
return false;
}
}
// check openstack auth
JsonNode jsonAuth = jsonNode.get(AUTHENTICATION);
if (jsonAuth != null) {
OpenstackAuth auth = keystoneConfig.authentication();
OpenstackAuthJsonMatcher authMatcher =
OpenstackAuthJsonMatcher.matchOpenstackAuth(auth);
return authMatcher.matches(jsonAuth);
}
return true;
}
@Override
public void describeTo(Description description) {
description.appendText(keystoneConfig.toString());
}
/**
* Factory to allocate keystone config matcher.
*
* @param config keystone config object we are looking for
* @return matcher
*/
public static KeystoneConfigJsonMatcher matchKeystoneConfig(KeystoneConfig config) {
return new KeystoneConfigJsonMatcher(config);
}
}

View File

@ -0,0 +1,77 @@
/*
* Copyright 2018-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.openstacknode.codec;
import com.fasterxml.jackson.databind.JsonNode;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeDiagnosingMatcher;
import org.onosproject.openstacknode.api.NeutronConfig;
/**
* Hamcrest matcher for neutron config.
*/
public final class NeutronConfigJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> {
private final NeutronConfig neutronConfig;
private static final String USE_METADATA_PROXY = "useMetadataProxy";
private static final String METADATA_PROXY_SECRET = "metadataProxySecret";
private NeutronConfigJsonMatcher(NeutronConfig neutronConfig) {
this.neutronConfig = neutronConfig;
}
@Override
protected boolean matchesSafely(JsonNode jsonNode, Description description) {
// check useMetaDataProxy
JsonNode jsonUseMetadataProxy = jsonNode.get(USE_METADATA_PROXY);
if (jsonUseMetadataProxy != null) {
boolean useMetadataProxy = neutronConfig.useMetadataProxy();
if (jsonUseMetadataProxy.asBoolean() != useMetadataProxy) {
description.appendText("useMetadataProxy was " + jsonUseMetadataProxy);
return false;
}
}
// check metadataProxySecret
JsonNode jsonMetadataProxySecret = jsonNode.get(METADATA_PROXY_SECRET);
if (jsonMetadataProxySecret != null) {
String metadataProxySecret = neutronConfig.metadataProxySecret();
if (!jsonMetadataProxySecret.asText().equals(metadataProxySecret)) {
description.appendText("metadataProxySecret was " + jsonUseMetadataProxy);
return false;
}
}
return true;
}
@Override
public void describeTo(Description description) {
description.appendText(neutronConfig.toString());
}
/**
* Factory to allocate neutron config matcher.
*
* @param config neutron config object we are looking for
* @return matcher
*/
public static NeutronConfigJsonMatcher matchNeutronConfig(NeutronConfig config) {
return new NeutronConfigJsonMatcher(config);
}
}

View File

@ -33,6 +33,8 @@ import org.onosproject.openstacknode.api.DefaultOpenstackAuth;
import org.onosproject.openstacknode.api.DefaultOpenstackNode;
import org.onosproject.openstacknode.api.DpdkConfig;
import org.onosproject.openstacknode.api.DpdkInterface;
import org.onosproject.openstacknode.api.KeystoneConfig;
import org.onosproject.openstacknode.api.NeutronConfig;
import org.onosproject.openstacknode.api.NodeState;
import org.onosproject.openstacknode.api.OpenstackAuth;
import org.onosproject.openstacknode.api.OpenstackNode;
@ -40,6 +42,8 @@ import org.onosproject.openstacknode.api.OpenstackPhyInterface;
import org.onosproject.openstacknode.api.OpenstackSshAuth;
import org.onosproject.openstacknode.impl.DefaultDpdkConfig;
import org.onosproject.openstacknode.impl.DefaultDpdkInterface;
import org.onosproject.openstacknode.api.DefaultKeystoneConfig;
import org.onosproject.openstacknode.api.DefaultNeutronConfig;
import org.onosproject.openstacknode.impl.DefaultOpenstackPhyInterface;
import org.onosproject.openstacknode.impl.DefaultOpenstackSshAuth;
@ -65,6 +69,7 @@ import static org.onosproject.openstacknode.codec.OpenstackNodeJsonMatcher.match
*/
public class OpenstackNodeCodecTest {
MockCodecContext context;
JsonCodec<OpenstackNode> openstackNodeCodec;
JsonCodec<OpenstackPhyInterface> openstackPhyIntfJsonCodec;
JsonCodec<ControllerInfo> openstackControllerJsonCodec;
@ -72,6 +77,8 @@ public class OpenstackNodeCodecTest {
JsonCodec<OpenstackSshAuth> openstackSshAuthJsonCodec;
JsonCodec<DpdkConfig> dpdkConfigJsonCodec;
JsonCodec<DpdkInterface> dpdkInterfaceJsonCodec;
JsonCodec<KeystoneConfig> keystoneConfigJsonCodec;
JsonCodec<NeutronConfig> neutronConfigJsonCodec;
final CoreService mockCoreService = createMock(CoreService.class);
private static final String REST_APP_ID = "org.onosproject.rest";
@ -86,6 +93,8 @@ public class OpenstackNodeCodecTest {
openstackSshAuthJsonCodec = new OpenstackSshAuthCodec();
dpdkConfigJsonCodec = new DpdkConfigCodec();
dpdkInterfaceJsonCodec = new DpdkInterfaceCodec();
keystoneConfigJsonCodec = new KeystoneConfigCodec();
neutronConfigJsonCodec = new NeutronConfigCodec();
assertThat(openstackNodeCodec, notNullValue());
assertThat(openstackPhyIntfJsonCodec, notNullValue());
@ -94,6 +103,8 @@ public class OpenstackNodeCodecTest {
assertThat(openstackSshAuthJsonCodec, notNullValue());
assertThat(dpdkConfigJsonCodec, notNullValue());
assertThat(dpdkInterfaceJsonCodec, notNullValue());
assertThat(keystoneConfigJsonCodec, notNullValue());
assertThat(neutronConfigJsonCodec, notNullValue());
expect(mockCoreService.registerApplication(REST_APP_ID))
.andReturn(APP_ID).anyTimes();
@ -257,13 +268,25 @@ public class OpenstackNodeCodecTest {
.perspective(OpenstackAuth.Perspective.PUBLIC)
.build();
String endpoint = "172.16.130.10:35357/v2.0";
KeystoneConfig keystoneConfig = DefaultKeystoneConfig.builder()
.endpoint(endpoint)
.authentication(auth)
.build();
NeutronConfig neutronConfig = DefaultNeutronConfig.builder()
.useMetadataProxy(true)
.metadataProxySecret("onos")
.build();
OpenstackNode node = DefaultOpenstackNode.builder()
.hostname("controller")
.type(OpenstackNode.NodeType.CONTROLLER)
.state(NodeState.INIT)
.managementIp(IpAddress.valueOf("172.16.130.10"))
.endpoint("keystone-end-point-url")
.authentication(auth)
.keystoneConfig(keystoneConfig)
.neutronConfig(neutronConfig)
.build();
ObjectNode nodeJson = openstackNodeCodec.encode(node, context);
@ -280,9 +303,10 @@ public class OpenstackNodeCodecTest {
assertThat(node.hostname(), is("controller"));
assertThat(node.type().name(), is("CONTROLLER"));
assertThat(node.managementIp().toString(), is("172.16.130.10"));
assertThat(node.endpoint(), is("keystone-end-point-url"));
OpenstackAuth auth = node.authentication();
KeystoneConfig keystoneConfig = node.keystoneConfig();
OpenstackAuth auth = keystoneConfig.authentication();
String endpoint = keystoneConfig.endpoint();
assertThat(auth.version(), is("v2.0"));
assertThat(auth.protocol(), is(OpenstackAuth.Protocol.HTTP));
@ -290,6 +314,38 @@ public class OpenstackNodeCodecTest {
assertThat(auth.password(), is("nova"));
assertThat(auth.project(), is("admin"));
assertThat(auth.perspective(), is(OpenstackAuth.Perspective.PUBLIC));
assertThat(endpoint, is("172.16.130.10:35357/v2.0"));
NeutronConfig neutronConfig = node.neutronConfig();
assertThat(neutronConfig.useMetadataProxy(), is(true));
assertThat(neutronConfig.metadataProxySecret(), is("onos"));
}
/**
* Tests the openstack obsolete controller node decoding.
*/
@Test
public void testOpenstackObsoleteControllerNodeDecode() throws IOException {
OpenstackNode node = getOpenstackNode("OpenstackObsoleteControllerNode.json");
assertThat(node.hostname(), is("controller"));
assertThat(node.type().name(), is("CONTROLLER"));
assertThat(node.managementIp().toString(), is("172.16.130.10"));
KeystoneConfig keystoneConfig = node.keystoneConfig();
OpenstackAuth auth = keystoneConfig.authentication();
String endpoint = keystoneConfig.endpoint();
assertThat(auth.version(), is("v2.0"));
assertThat(auth.protocol(), is(OpenstackAuth.Protocol.HTTP));
assertThat(auth.username(), is("admin"));
assertThat(auth.password(), is("nova"));
assertThat(auth.project(), is("admin"));
assertThat(auth.perspective(), is(OpenstackAuth.Perspective.PUBLIC));
assertThat(endpoint, is("172.16.130.10:35357/v2.0"));
}
/**
@ -349,6 +405,12 @@ public class OpenstackNodeCodecTest {
if (entityClass == DpdkInterface.class) {
return (JsonCodec<T>) dpdkInterfaceJsonCodec;
}
if (entityClass == KeystoneConfig.class) {
return (JsonCodec<T>) keystoneConfigJsonCodec;
}
if (entityClass == NeutronConfig.class) {
return (JsonCodec<T>) neutronConfigJsonCodec;
}
return manager.getCodec(entityClass);
}

View File

@ -21,7 +21,6 @@ import org.hamcrest.TypeSafeDiagnosingMatcher;
import org.onosproject.net.behaviour.ControllerInfo;
import org.onosproject.openstacknode.api.Constants;
import org.onosproject.openstacknode.api.DpdkConfig;
import org.onosproject.openstacknode.api.OpenstackAuth;
import org.onosproject.openstacknode.api.OpenstackNode;
import org.onosproject.openstacknode.api.OpenstackPhyInterface;
import org.onosproject.openstacknode.api.OpenstackSshAuth;
@ -113,17 +112,6 @@ public final class OpenstackNodeJsonMatcher extends TypeSafeDiagnosingMatcher<Js
}
}
// check openstack auth
JsonNode jsonAuth = jsonNode.get(AUTHENTICATION);
if (jsonAuth != null) {
OpenstackAuth auth = node.authentication();
OpenstackAuthJsonMatcher authMatcher =
OpenstackAuthJsonMatcher.matchOpenstackAuth(auth);
if (!authMatcher.matches(jsonAuth)) {
return false;
}
}
// check openstack ssh auth
JsonNode jsonSshAuth = jsonNode.get(SSH_AUTH);
if (jsonSshAuth != null) {
@ -142,16 +130,6 @@ public final class OpenstackNodeJsonMatcher extends TypeSafeDiagnosingMatcher<Js
}
// check endpoint URL
JsonNode jsonEndpoint = jsonNode.get(END_POINT);
if (jsonEndpoint != null) {
String endpoint = node.endpoint();
if (!jsonEndpoint.asText().equals(endpoint)) {
description.appendText("endpoint URL was " + jsonEndpoint);
return false;
}
}
// check physical interfaces
JsonNode jsonPhyIntfs = jsonNode.get(PHYSICAL_INTERFACES);
if (jsonPhyIntfs != null) {

View File

@ -71,8 +71,9 @@ import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.openstacknode.api.DefaultOpenstackNode;
import org.onosproject.openstacknode.api.DpdkConfig;
import org.onosproject.openstacknode.api.KeystoneConfig;
import org.onosproject.openstacknode.api.NeutronConfig;
import org.onosproject.openstacknode.api.NodeState;
import org.onosproject.openstacknode.api.OpenstackAuth;
import org.onosproject.openstacknode.api.OpenstackNode;
import org.onosproject.openstacknode.api.OpenstackPhyInterface;
import org.onosproject.openstacknode.api.OpenstackSshAuth;
@ -501,10 +502,10 @@ public class DefaultOpenstackNodeHandlerTest {
NodeState state,
Set<OpenstackPhyInterface> phyIntfs,
Set<ControllerInfo> controllers,
OpenstackAuth auth,
String endpoint,
OpenstackSshAuth sshAuth,
DpdkConfig dpdkConfig) {
DpdkConfig dpdkConfig,
KeystoneConfig keystoneConfig,
NeutronConfig neutronConfig) {
super(hostname,
type,
intgBridge,
@ -515,10 +516,10 @@ public class DefaultOpenstackNodeHandlerTest {
state,
phyIntfs,
controllers,
auth,
endpoint,
sshAuth,
dpdkConfig);
dpdkConfig,
keystoneConfig,
neutronConfig);
}
@Override

View File

@ -2,14 +2,19 @@
"hostname": "controller",
"type": "CONTROLLER",
"managementIp": "172.16.130.10",
"endpoint": "keystone-end-point-url",
"authentication": {
"version": "v2.0",
"port": 35357,
"protocol": "HTTP",
"project": "admin",
"username": "admin",
"password": "nova",
"perspective": "PUBLIC"
"keystoneConfig": {
"endpoint": "172.16.130.10:35357/v2.0",
"authentication": {
"version": "v2.0",
"protocol": "HTTP",
"project": "admin",
"username": "admin",
"password": "nova",
"perspective": "PUBLIC"
}
},
"neutronConfig": {
"useMetadataProxy": true,
"metadataProxySecret": "onos"
}
}

View File

@ -0,0 +1,18 @@
{
"hostname": "controller",
"type": "CONTROLLER",
"managementIp": "172.16.130.10",
"neutronConfig": {
"useMetadataProxy": true,
"metadataProxySecret": "onos"
},
"endpoint": "172.16.130.10:35357/v2.0",
"authentication": {
"version": "v2.0",
"protocol": "HTTP",
"project": "admin",
"username": "admin",
"password": "nova",
"perspective": "PUBLIC"
}
}

View File

@ -1,126 +1,112 @@
{
"apps" : {
"org.onosproject.openstacknode" : {
"openstacknode" : {
"nodes" : [
"nodes": [
{
"hostname": "compute-01",
"type": "COMPUTE",
"managementIp": "172.16.130.4",
"dataIp": "172.16.130.4",
"vlanPort": "eth2",
"integrationBridge": "of:00000000000000a1",
"phyIntfs": [
{
"network": "mgmtnetwork",
"intf": "eth3"
},
{
"network": "oamnetwork",
"intf": "eth4"
},
{
"network": "datanetwork",
"intf": "dpdk0"
}
],
"sshAuth": {
"id": "id",
"password": "password"
},
"dpdkConfig": {
"datapathType": "netdev",
"socketDir": "/var/lib/libvirt/qemu",
"dpdkIntfs": [
{
"hostname" : "compute-01",
"type" : "COMPUTE",
"managementIp" : "172.16.130.4",
"dataIp" : "172.16.130.4",
"vlanPort" : "eth2",
"integrationBridge" : "of:00000000000000a1",
"phyIntfs": [
{
"network": "mgmtnetwork",
"intf": "eth3"
},
{
"network": "oamnetwork",
"intf": "eth4"
},
{
"network": "datanetwork",
"intf": "dpdk0"
}
],
"sshAuth" : {
"id": "id",
"password" : "password"
},
"dpdkConfig" : {
"datapathType" : "netdev",
"socketDir" : "/var/lib/libvirt/qemu",
"dpdkIntfs" : [
{
"intf" : "dpdk0",
"mtu" : 1500,
"deviceName" : "br-int",
"pciAddress" : "0000:85:00.0",
"type" : "dpdk"
},
{
"intf" : "dpdk1",
"mtu" : 1500,
"deviceName" : "br-tun",
"pciAddress" : "0000:85:00.1",
"type" : "dpdk"
}
]
},
"controllers": [
{
"ip": "10.10.10.2",
"port": 6653
},
{
"ip": "10.10.10.3",
"port": 6653
},
{
"ip": "10.10.10.4",
"port": 6653
}
]
"intf": "dpdk0",
"mtu": 1500,
"deviceName": "br-int",
"pciAddress": "0000:85:00.0",
"type": "dpdk"
},
{
"hostname" : "compute-02",
"type" : "COMPUTE",
"managementIp" : "172.16.130.6",
"dataIp" : "172.16.130.6",
"vlanPort" : "eth2",
"integrationBridge" : "of:00000000000000a2",
"phyIntfs": [
{
"network": "mgmtnetwork",
"intf": "eth3"
},
{
"network": "oamnetwork",
"intf": "eth4"
}
]
},
{
"hostname" : "controller",
"type" : "CONTROLLER",
"managementIp" : "172.16.130.10",
"endpoint" : "keystone-endpoint-url",
"authentication" : {
"version" : "v2.0",
"port" : 35357,
"protocol" : "HTTP",
"project" : "admin",
"username" : "admin",
"password" : "nova",
"perspective" : "PUBLIC"
}
},
{
"hostname" : "gateway-01",
"type" : "GATEWAY",
"managementIp" : "172.16.130.8",
"dataIp" : "172.16.130.7",
"vlanPort" : "eth2",
"integrationBridge" : "of:00000000000000a3",
"uplinkPort" : "ens6"
"intf": "dpdk1",
"mtu": 1500,
"deviceName": "br-tun",
"pciAddress": "0000:85:00.1",
"type": "dpdk"
}
]
}
}
},
"devices" : {
"of:00000000000000a1" : {
"basic" : {
"driver" : "sona"
},
"controllers": [
{
"ip": "10.10.10.2",
"port": 6653
},
{
"ip": "10.10.10.3",
"port": 6653
},
{
"ip": "10.10.10.4",
"port": 6653
}
]
},
{
"hostname": "compute-02",
"type": "COMPUTE",
"managementIp": "172.16.130.6",
"dataIp": "172.16.130.6",
"vlanPort": "eth2",
"integrationBridge": "of:00000000000000a2",
"phyIntfs": [
{
"network": "mgmtnetwork",
"intf": "eth3"
},
{
"network": "oamnetwork",
"intf": "eth4"
}
]
},
{
"hostname": "controller",
"type": "CONTROLLER",
"managementIp": "172.16.130.10",
"keystoneConfig": {
"endpoint": "172.16.130.10:35357/v2.0",
"authentication": {
"version": "v2.0",
"protocol": "HTTP",
"project": "admin",
"username": "admin",
"password": "nova",
"perspective": "PUBLIC"
}
},
"neutronConfig": {
"useMetadataProxy": true,
"metadataProxySecret": "onos"
}
},
"of:00000000000000a2" : {
"basic" : {
"driver" : "sona"
}
{
"hostname": "gateway-01",
"type": "GATEWAY",
"managementIp": "172.16.130.8",
"dataIp": "172.16.130.7",
"vlanPort": "eth2",
"integrationBridge": "of:00000000000000a3",
"uplinkPort": "ens6"
}
}
]
}