Use metadata secret var in openstack node, support PUT/POST/DELETE
Change-Id: Id744b6443b49a3a0e73f9d497462f48ba64ab0a7
(cherry picked from commit 4665093b0fb126fc9bf11d6594977752d304762c)
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackMetadataProxyHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackMetadataProxyHandler.java
index 1a225ea..c7fc417 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackMetadataProxyHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackMetadataProxyHandler.java
@@ -16,13 +16,11 @@
package org.onosproject.openstacknetworking.impl;
-import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableSet;
import org.apache.commons.lang.StringUtils;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Modified;
-import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.http.Header;
@@ -31,8 +29,10 @@
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
@@ -46,8 +46,6 @@
import org.onlab.packet.IpPrefix;
import org.onlab.packet.TCP;
import org.onlab.packet.TpPort;
-import org.onlab.util.Tools;
-import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.LeadershipService;
import org.onosproject.cluster.NodeId;
@@ -72,13 +70,12 @@
import org.onosproject.openstacknode.api.OpenstackNodeListener;
import org.onosproject.openstacknode.api.OpenstackNodeService;
import org.openstack4j.model.network.Port;
-import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import java.io.IOException;
import java.nio.ByteBuffer;
-import java.util.Dictionary;
import java.util.Objects;
+import java.util.Set;
import static org.onosproject.openstacknetworking.api.Constants.DHCP_ARP_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_DHCP_RULE;
@@ -121,17 +118,13 @@
private static final String HTTP_GET_METHOD = "GET";
private static final String HTTP_POST_METHOD = "POST";
-
- private static final String METADATA_SECRET = "metadataSecret";
- private static final String DEFAULT_METADATA_SECRET = "nova";
+ private static final String HTTP_PUT_METHOD = "PUT";
+ private static final String HTTP_DELETE_METHOD = "DELETE";
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected ComponentConfigService configService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PacketService packetService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -152,13 +145,11 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected OpenstackFlowRuleService osFlowRuleService;
- @Property(name = METADATA_SECRET, value = DEFAULT_METADATA_SECRET,
- label = "Metadata secret")
- private String metadataSecret = DEFAULT_METADATA_SECRET;
-
private final PacketProcessor packetProcessor = new InternalPacketProcessor();
private final OpenstackNodeListener osNodeListener = new InternalNodeEventListener();
+ private Set<String> excludedHeaders = ImmutableSet.of("content-type", "content-length");
+
private ApplicationId appId;
private NodeId localNodeId;
@@ -166,7 +157,6 @@
protected void activate() {
appId = coreService.registerApplication(Constants.OPENSTACK_NETWORKING_APP_ID);
localNodeId = clusterService.getLocalNode().id();
- configService.registerProperties(getClass());
osNodeService.addListener(osNodeListener);
packetService.addProcessor(packetProcessor, PacketProcessor.director(0));
leadershipService.runForLeadership(appId.name());
@@ -177,32 +167,21 @@
@Deactivate
protected void deactivate() {
packetService.removeProcessor(packetProcessor);
- configService.unregisterProperties(getClass(), false);
osNodeService.removeListener(osNodeListener);
leadershipService.withdraw(appId.name());
log.info("Stopped");
}
- @Modified
- protected void modified(ComponentContext context) {
- Dictionary<?, ?> properties = context.getProperties();
- String updatedMetadataSecret;
-
- updatedMetadataSecret = Tools.get(properties, METADATA_SECRET);
-
- if (!Strings.isNullOrEmpty(updatedMetadataSecret) &&
- !updatedMetadataSecret.equals(metadataSecret)) {
- metadataSecret = updatedMetadataSecret;
- }
-
- log.info("Modified");
- }
-
private class InternalPacketProcessor implements PacketProcessor {
@Override
public void process(PacketContext context) {
+
+ if (!useMetadataProxy()) {
+ return;
+ }
+
if (context.isHandled()) {
return;
}
@@ -224,12 +203,16 @@
return;
}
+ // (three-way handshaking)
+ // reply TCP SYN-ACK packet with receiving TCP SYN packet
if (tcpPacket.getFlags() == SYN_FLAG) {
Ethernet ethReply = buildTcpSynAckPacket(ethPacket, ipv4Packet, tcpPacket);
sendReply(context, ethReply);
return;
}
+ // (four-way handshaking)
+ // reply TCP ACK and TCP FIN-ACK packets with receiving TCP FIN-ACK packet
if (tcpPacket.getFlags() == FIN_ACK_FLAG) {
Ethernet ackReply = buildTcpAckPacket(ethPacket, ipv4Packet, tcpPacket);
sendReply(context, ackReply);
@@ -238,6 +221,7 @@
return;
}
+ // normal TCP data transmission
Data data = (Data) tcpPacket.getPayload();
byte[] byteData = data.getData();
@@ -252,7 +236,7 @@
}
// attempt to send HTTP request to the meta-data server (nova-api),
- // obtain the HTTP response
+ // obtain the HTTP response, relay the response to VM through packet-out
CloseableHttpResponse proxyResponse = proxyHttpRequest(request, instPort);
if (proxyResponse == null) {
@@ -434,19 +418,30 @@
return null;
}
- log.info("Sending request to metadata endpoint {}...", url);
-
HttpRequestBase request;
- switch (oldRequest.getRequestLine().getMethod()) {
+ String method = oldRequest.getRequestLine().getMethod().toUpperCase();
+
+ log.info("Sending HTTP {} request to metadata endpoint {}...", method, url);
+
+ switch (method) {
case HTTP_GET_METHOD:
request = new HttpGet(url);
break;
case HTTP_POST_METHOD:
request = new HttpPost(url);
- HttpEntityEnclosingRequest entityRequest =
+ HttpEntityEnclosingRequest postRequest =
(HttpEntityEnclosingRequest) oldRequest;
- ((HttpPost) request).setEntity(entityRequest.getEntity());
+ ((HttpPost) request).setEntity(postRequest.getEntity());
+ break;
+ case HTTP_PUT_METHOD:
+ request = new HttpPut(url);
+ HttpEntityEnclosingRequest putRequest =
+ (HttpEntityEnclosingRequest) oldRequest;
+ ((HttpPut) request).setEntity(putRequest.getEntity());
+ break;
+ case HTTP_DELETE_METHOD:
+ request = new HttpDelete(url);
break;
default:
request = new HttpGet(url);
@@ -455,6 +450,13 @@
// configure headers from original HTTP request
for (Header header : oldRequest.getAllHeaders()) {
+ if (method.equals(HTTP_POST_METHOD) ||
+ method.equals(HTTP_PUT_METHOD)) {
+ // we DO NOT add duplicated HTTP headers for POST and PUT methods
+ if (excludedHeaders.contains(header.getName().toLowerCase())) {
+ continue;
+ }
+ }
request.addHeader(header);
}
@@ -463,11 +465,12 @@
Port port = osNetworkService.port(instPort.portId());
request.addHeader(new BasicHeader(INSTANCE_ID_HEADER, port.getDeviceId()));
- request.addHeader(new BasicHeader(INSTANCE_ID_SIGNATURE_HEADER,
- hmacEncrypt(metadataSecret, port.getDeviceId())));
request.addHeader(new BasicHeader(TENANT_ID_HEADER, port.getTenantId()));
- request.addHeader(new BasicHeader(
- FORWARDED_FOR_HEADER, instPort.ipAddress().toString()));
+ request.addHeader(new BasicHeader(FORWARDED_FOR_HEADER, instPort.ipAddress().toString()));
+ if (metadataSecret() != null) {
+ request.addHeader(new BasicHeader(INSTANCE_ID_SIGNATURE_HEADER,
+ hmacEncrypt(metadataSecret(), port.getDeviceId())));
+ }
try {
return client.execute(request);
@@ -508,7 +511,7 @@
// do not allow to proceed without leadership
NodeId leader = leadershipService.getLeader(appId.name());
return Objects.equals(localNodeId, leader) &&
- event.subject().type() == COMPUTE;
+ event.subject().type() == COMPUTE && useMetadataProxy();
}
@Override
@@ -559,6 +562,28 @@
}
}
+ private boolean useMetadataProxy() {
+ OpenstackNode gw = osNodeService.completeNodes(CONTROLLER)
+ .stream().findFirst().orElse(null);
+
+ if (gw != null && gw.neutronConfig() != null) {
+ return gw.neutronConfig().useMetadataProxy();
+ }
+
+ return false;
+ }
+
+ private String metadataSecret() {
+ OpenstackNode controller = osNodeService.completeNodes(CONTROLLER)
+ .stream().findFirst().orElse(null);
+
+ if (controller != null && controller.neutronConfig() != null) {
+ return controller.neutronConfig().metadataProxySecret();
+ }
+
+ return null;
+ }
+
/**
* Implements Http packet format.
*/
diff --git a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/DistributedOpenstackNodeStore.java b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/DistributedOpenstackNodeStore.java
index 0b713b4..571890b 100644
--- a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/DistributedOpenstackNodeStore.java
+++ b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/DistributedOpenstackNodeStore.java
@@ -26,6 +26,8 @@
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.behaviour.ControllerInfo;
+import org.onosproject.openstacknode.api.DefaultKeystoneConfig;
+import org.onosproject.openstacknode.api.DefaultNeutronConfig;
import org.onosproject.openstacknode.api.DefaultOpenstackAuth;
import org.onosproject.openstacknode.api.DefaultOpenstackNode;
import org.onosproject.openstacknode.api.DpdkConfig;
@@ -98,6 +100,8 @@
.register(DefaultOpenstackAuth.Perspective.class)
.register(DefaultOpenstackAuth.Protocol.class)
.register(DefaultOpenstackSshAuth.class)
+ .register(DefaultKeystoneConfig.class)
+ .register(DefaultNeutronConfig.class)
.register(Collection.class)
.build();