mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-10-15 09:21:06 +02:00
Use metadata secret var in openstack node, support PUT/POST/DELETE
Change-Id: Id744b6443b49a3a0e73f9d497462f48ba64ab0a7
This commit is contained in:
parent
c704b67f87
commit
4665093b0f
@ -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.HttpMessage;
|
||||
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.IpAddress;
|
||||
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.OpenstackNodeEvent;
|
||||
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,16 +118,12 @@ public class OpenstackMetadataProxyHandler {
|
||||
|
||||
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;
|
||||
|
||||
@ -152,13 +145,11 @@ public class OpenstackMetadataProxyHandler {
|
||||
@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 @@ public class OpenstackMetadataProxyHandler {
|
||||
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 @@ public class OpenstackMetadataProxyHandler {
|
||||
@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 @@ public class OpenstackMetadataProxyHandler {
|
||||
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 @@ public class OpenstackMetadataProxyHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
// normal TCP data transmission
|
||||
Data data = (Data) tcpPacket.getPayload();
|
||||
byte[] byteData = data.getData();
|
||||
|
||||
@ -252,7 +236,7 @@ public class OpenstackMetadataProxyHandler {
|
||||
}
|
||||
|
||||
// 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 @@ public class OpenstackMetadataProxyHandler {
|
||||
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 @@ public class OpenstackMetadataProxyHandler {
|
||||
|
||||
// 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 @@ public class OpenstackMetadataProxyHandler {
|
||||
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 @@ public class OpenstackMetadataProxyHandler {
|
||||
// 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 @@ public class OpenstackMetadataProxyHandler {
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
|
@ -26,6 +26,8 @@ import org.onlab.util.KryoNamespace;
|
||||
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 @@ public class DistributedOpenstackNodeStore
|
||||
.register(DefaultOpenstackAuth.Perspective.class)
|
||||
.register(DefaultOpenstackAuth.Protocol.class)
|
||||
.register(DefaultOpenstackSshAuth.class)
|
||||
.register(DefaultKeystoneConfig.class)
|
||||
.register(DefaultNeutronConfig.class)
|
||||
.register(Collection.class)
|
||||
.build();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user