/*
* Copyright (c) 2015 NEC Corporation. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.nic.vtn.renderer;
import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
import static java.net.HttpURLConnection.HTTP_CLIENT_TIMEOUT;
import static java.net.HttpURLConnection.HTTP_CONFLICT;
import static java.net.HttpURLConnection.HTTP_GONE;
import static java.net.HttpURLConnection.HTTP_INTERNAL_ERROR;
import static java.net.HttpURLConnection.HTTP_NOT_ACCEPTABLE;
import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
import static java.net.HttpURLConnection.HTTP_OK;
import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED;
import static java.net.HttpURLConnection.HTTP_UNAVAILABLE;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
import org.opendaylight.nic.utils.MdsalUtils;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.flow.cond.rev150313.RemoveFlowConditionInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.flow.cond.rev150313.SetFlowConditionInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.flow.cond.rev150313.SetFlowConditionOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.flow.cond.rev150313.VtnFlowConditionService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.flow.filter.rev150907.RemoveFlowFilterInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.flow.filter.rev150907.RemoveFlowFilterOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.flow.filter.rev150907.SetFlowFilterInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.flow.filter.rev150907.SetFlowFilterOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.flow.filter.rev150907.VtnFlowFilterService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.mapping.port.rev150907.VtnPortMapService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.mapping.vlan.rev150907.AddVlanMapInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.mapping.vlan.rev150907.AddVlanMapOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.mapping.vlan.rev150907.RemoveVlanMapInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.mapping.vlan.rev150907.RemoveVlanMapOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.mapping.vlan.rev150907.VtnVlanMapService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.rev150328.RemoveVtnInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.rev150328.RemoveVtnInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.rev150328.UpdateVtnInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.rev150328.UpdateVtnInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.rev150328.UpdateVtnOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.rev150328.VtnService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.rev150328.Vtns;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.rev150328.vtns.Vtn;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.rev150328.vtns.VtnKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.types.rev150209.VnodeName;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.types.rev150209.VnodeUpdateMode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.types.rev150209.VtnErrorTag;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.types.rev150209.VtnUpdateOperationType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.types.rev150209.VtnUpdateType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.vbridge.rev150907.RemoveVbridgeInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.vbridge.rev150907.RemoveVbridgeInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.vbridge.rev150907.UpdateVbridgeInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.vbridge.rev150907.UpdateVbridgeInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.vbridge.rev150907.UpdateVbridgeOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.vbridge.rev150907.VtnVbridgeService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.vbridge.rev150907.vtn.vbridge.info.VbridgeConfig;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.vbridge.rev150907.vtn.vbridge.list.Vbridge;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.vbridge.rev150907.vtn.vbridge.list.VbridgeKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.vinterface.rev150907.RemoveVinterfaceInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.vinterface.rev150907.UpdateVinterfaceInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.vinterface.rev150907.UpdateVinterfaceOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.vinterface.rev150907.VtnVinterfaceService;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.ImmutableMap;
/**
* {@code VTNManagerService} provides interfaces to control VTN Manager.
*/
public final class VTNManagerService {
/**
* Logger instance.
*/
private static final Logger LOG =
LoggerFactory.getLogger(VTNManagerService.class);
/**
* A map that keeps pairs of HTTP status code associated with VTN error
* tag.
*/
private static final Map<String, Integer> VTN_ERROR_CODES;
/**
* The number of seconds to wait for completion of RPC.
*/
private static final long RPC_TIMEOUT = 60L;
/**
* MD-SAL utility service.
*/
private final MdsalUtils mdSal;
/**
* RPC service for VTN management.
*/
private final VtnService vtnService;
/**
* RPC service for vBridge management.
*/
private final VtnVbridgeService vbridgeService;
/**
* RPC service for virtual interface management.
*/
private final VtnVinterfaceService vinterfaceService;
/**
* RPC service for port mapping management.
*/
private final VtnPortMapService portMapService;
/**
* RPC service for port mapping management.
*/
private final VtnVlanMapService vlanMapService;
/**
* RPC service for Flowcondition management.
*/
private final VtnFlowConditionService flowConditionService;
/**
* RPC service for Flowcondition management.
*/
private final VtnFlowFilterService flowFilterService;
/**
* Initialize statis field.
*/
static {
VTN_ERROR_CODES = ImmutableMap.<String, Integer>builder()
.put(VtnErrorTag.BADREQUEST.toString(), HTTP_BAD_REQUEST)
.put(VtnErrorTag.UNAUTHORIZED.toString(), HTTP_UNAUTHORIZED)
.put(VtnErrorTag.NOTFOUND.toString(), HTTP_NOT_FOUND)
.put(VtnErrorTag.NOTACCEPTABLE.toString(), HTTP_NOT_ACCEPTABLE)
.put(VtnErrorTag.TIMEOUT.toString(), HTTP_CLIENT_TIMEOUT)
.put(VtnErrorTag.CONFLICT.toString(), HTTP_CONFLICT)
.put(VtnErrorTag.GONE.toString(), HTTP_GONE)
.put(VtnErrorTag.NOSERVICE.toString(), HTTP_UNAVAILABLE)
.put(VtnErrorTag.INTERNALERROR.toString(), HTTP_INTERNAL_ERROR)
.build();
}
/**
* {@code VTNRpcResult} describes a result of VTN RPC invocation.
*
* @param <O> The type of the RPC output.
*/
private static final class VTNRpcResult<O> {
/**
* HTTP status code.
*/
private final int statusCode;
/**
* The output of the RPC.
*/
private final O output;
/**
* An error message.
*/
private final String errorMessage;
/**
* Construct a new instance that indicates successful completion.
*
* @param out The output of the RPC.
*/
private VTNRpcResult(O out) {
statusCode = HTTP_OK;
output = out;
errorMessage = null;
}
/**
* Construct a new instance that indicates an internal error.
*
* @param msg An error message.
*/
private VTNRpcResult(String msg) {
statusCode = HTTP_INTERNAL_ERROR;
output = null;
errorMessage = msg;
}
/**
* Construct a new instance.
*
* @param msg An error message.
* @param code A HTTP status code that indicates the cause of error.
*/
private VTNRpcResult(String msg, int code) {
statusCode = code;
output = null;
errorMessage = msg;
}
/**
* Return the HTTP status code that indicates the result of the RPC
* invocation.
*
* @return A HTTP status code.
* {@link java.net.HttpURLConnection#HTTP_OK} indicates
* successful completion.
*/
private int getStatusCode() {
return statusCode;
}
/**
* Return the output of the RPC invocation.
*
* @return The RPC output.
*/
private O getOutput() {
return output;
}
/**
* Return an error message.
*
* @return An error message.
*/
private String getErrorMessage() {
return errorMessage;
}
}
/**
* Return an instance identifier that specifies the VTN.
*
* @param tname The name of the VTN.
* @return An {@link InstanceIdentifier} instance.
*/
public static InstanceIdentifier<Vtn> getTenantPath(String tname) {
VtnKey vtnKey = new VtnKey(new VnodeName(tname));
return InstanceIdentifier.builder(Vtns.class)
.child(Vtn.class, vtnKey)
.build();
}
/**
* Return an instance identifier that specifies the vBridge configuration.
*
* @param tname The name of the VTN.
* @param bname The name of the vBridge.
* @return An {@link InstanceIdentifier} instance.
*/
public static InstanceIdentifier<VbridgeConfig> getBridgeConfigPath(
String tname, String bname) {
VtnKey vtnKey = new VtnKey(new VnodeName(tname));
VbridgeKey vbrKey = new VbridgeKey(new VnodeName(bname));
return InstanceIdentifier.builder(Vtns.class)
.child(Vtn.class, vtnKey)
.child(Vbridge.class, vbrKey)
.child(VbridgeConfig.class)
.build();
}
/**
* Wait for completion of the RPC task associated with the given future.
*
* @param f A {@link Future} instance associated with the RPC task.
* @param <O> The type of the RPC output.
* @return A {@link VTNRpcResult} instance that contains the result of
* the RPC invocation.
*/
private static <O> VTNRpcResult<O> getRpcResult(Future<RpcResult<O>> f) {
return getRpcResult(f, false);
}
/**
* Wait for completion of the RPC task associated with the given future.
*
* @param f A {@link Future} instance associated with the RPC task.
* @param nillable Set {@code true} if the result can be null.
* @param <O> The type of the RPC output.
* @return A {@link VTNRpcResult} instance that contains the result of
* the RPC invocation.
*/
private static <O> VTNRpcResult<O> getRpcResult(Future<RpcResult<O>> f,
boolean nillable) {
RpcResult<O> result;
try {
result = f.get(RPC_TIMEOUT, TimeUnit.SECONDS);
} catch (Exception e) {
String msg =
"Caught an exception while waiting for RPC completion";
LOG.error(msg, e);
return new VTNRpcResult<O>(msg + ": " + e.toString());
}
VTNRpcResult<O> vres;
if (result == null) {
// This should never happen.
vres = new VTNRpcResult<O>("RPC did not set result.");
} else if (result.isSuccessful()) {
O res = result.getResult();
if (!nillable && res == null) {
// This should never happen.
vres = new VTNRpcResult<O>("RPC did not set output.");
} else {
vres = new VTNRpcResult<O>(res);
}
} else {
vres = getRpcErrorResult(result);
}
return vres;
}
/**
* Construct a {@link VTNRpcResult} instance that indicates an error.
*
* @param result An {@link RpcResult} instance that indicates an error.
* @param <O> The type of the RPC output.
* @return A {@link VTNRpcResult} instance that contains the result of
* the RPC invocation.
*/
private static <O> VTNRpcResult<O> getRpcErrorResult(RpcResult<O> result) {
VTNRpcResult<O> vres;
Collection<RpcError> errors = result.getErrors();
if (errors == null || errors.isEmpty()) {
// This should never happen.
String msg = "RPC failed without error information: " + result;
vres = new VTNRpcResult<O>(msg);
} else {
// VTN RPC sets only one RpcError, and it contains encoded
// VtnErrorTag value in application tag.
RpcError rerr = errors.iterator().next();
String appTag = rerr.getApplicationTag();
Integer code = VTN_ERROR_CODES.get(appTag);
if (code != null) {
String msg = appTag + ": " + rerr.getMessage();
vres = new VTNRpcResult<O>(msg, code.intValue());
} else {
// Unexpected error.
int index = 0;
for (RpcError re: errors) {
Throwable cause = re.getCause();
String msg = "RPC failed: error[" + index + "]=" + re;
if (cause == null) {
LOG.error(msg);
} else {
LOG.error(msg, cause);
}
index++;
}
vres = new VTNRpcResult<O>("Internal error");
}
}
return vres;
}
/**
* Construct a new instance.
*
* @param md A {@link MdsalUtils} instance.
* @param rpc A {@link RpcConsumerRegistry} instance.
*/
public VTNManagerService(MdsalUtils md, RpcConsumerRegistry rpc) {
mdSal = md;
vtnService = rpc.getRpcService(VtnService.class);
vbridgeService = rpc.getRpcService(VtnVbridgeService.class);
vinterfaceService = rpc.getRpcService(VtnVinterfaceService.class);
portMapService = rpc.getRpcService(VtnPortMapService.class);
vlanMapService = rpc.getRpcService(VtnVlanMapService.class);
flowConditionService = rpc.getRpcService(VtnFlowConditionService.class);
flowFilterService = rpc.getRpcService(VtnFlowFilterService.class);
}
/**
* Create or update a VTN with default parameters.
*
* @param name The name of the VTN.
* @param mode A {@link VnodeUpdateMode} instance that specifies how to
* update the VTN.
* {@code null} implies {@link VnodeUpdateMode#UPDATE}.
* @return True is returned on successful completion,
else false is returned.
*/
public boolean updateTenant(String name, VnodeUpdateMode mode) {
UpdateVtnInput input = new UpdateVtnInputBuilder()
.setTenantName(name)
.setUpdateMode(mode)
.setOperation(VtnUpdateOperationType.SET)
.build();
VTNRpcResult<UpdateVtnOutput> result =
getRpcResult(vtnService.updateVtn(input));
int code = result.getStatusCode();
if (code != HTTP_OK) {
LOG.error("Failed to update VTN: input={}, err={}",
input, result.getErrorMessage());
return false;
} else {
VtnUpdateType utype = result.getOutput().getStatus();
String msg;
if (utype == VtnUpdateType.CREATED) {
msg = "A VTN has been created";
} else if (utype == VtnUpdateType.CHANGED) {
msg = "A VTN has been changed";
} else {
assert utype == null;
msg = "A VTN is present and not changed";
}
LOG.debug("{}: name={}", msg, name);
return true;
}
}
/**
* Remove the specified VTN.
*
* @param name The name of the VTN.
* @return True is returned on successful completion,
else false is returned.
*/
public boolean removeTenant(String name) {
RemoveVtnInput input = new RemoveVtnInputBuilder()
.setTenantName(name).build();
VTNRpcResult<?> result =
getRpcResult(vtnService.removeVtn(input), true);
int code = result.getStatusCode();
if (code == HTTP_OK) {
LOG.debug("A VTN has been removed: name={}", name);
return true;
} else {
LOG.error("Failed to remove VTN: name={}, err={}",
name, result.getErrorMessage());
return false;
}
}
/**
* Determine whether the specified VTN contains at least one vBridge or
* not.
*
* @param tname The name of the VTN.
* @return True is returned on successful completion,
else false is returned.
*/
public boolean hasBridge(String tname) {
Vtn opt = mdSal.read(LogicalDatastoreType.OPERATIONAL, getTenantPath(tname));
boolean ret;
if (opt != null) {
List<Vbridge> vbridges = opt.getVbridge();
ret = (vbridges != null && !vbridges.isEmpty());
} else {
ret = false;
}
return ret;
}
/**
* Create or update the specified vBridge.
*
* @param tname The name of the VTN.
* @param bname The name of the vBridge.
* @param desc A brief description about the vBridge.
* @param mode A {@link VnodeUpdateMode} instance that specifies how to
* update the vBridge.
* {@code null} implies {@link VnodeUpdateMode#UPDATE}.
* @return True is returned on successful completion,
else false is returned.
*/
public boolean updateBridge(String tname, String bname, String desc,
VnodeUpdateMode mode) {
UpdateVbridgeInput input = new UpdateVbridgeInputBuilder()
.setTenantName(tname)
.setBridgeName(bname)
.setDescription(desc)
.setUpdateMode(mode)
.setOperation(VtnUpdateOperationType.SET)
.build();
VTNRpcResult<UpdateVbridgeOutput> result =
getRpcResult(vbridgeService.updateVbridge(input));
int code = result.getStatusCode();
if (code == HTTP_CONFLICT) {
return true;
}
if (code != HTTP_OK) {
LOG.error("Failed to update vBridge: input={}, err={}",
input, result.getErrorMessage());
return false;
} else {
VtnUpdateType utype = result.getOutput().getStatus();
String msg;
if (utype == VtnUpdateType.CREATED) {
msg = "A vBridge has been created";
} else if (utype == VtnUpdateType.CHANGED) {
msg = "A vBridge has been changed";
} else {
assert utype == null;
msg = "A vBridge is present and not changed";
}
LOG.debug("{}: path={}/{}, desc={}", msg, tname, bname, desc);
return true;
}
}
/**
* Remove the specified vBridge.
*
* @param tname The name of the VTN.
* @param bname The name of the vBridge.
* @return A HTTP status code that indicates the result.
* {@link java.net.HttpURLConnection#HTTP_OK} indicates
* successful completion.
*/
public int removeBridge(String tname, String bname) {
RemoveVbridgeInput input = new RemoveVbridgeInputBuilder()
.setTenantName(tname)
.setBridgeName(bname)
.build();
VTNRpcResult<?> result =
getRpcResult(vbridgeService.removeVbridge(input), true);
int code = result.getStatusCode();
if (code == HTTP_OK) {
LOG.debug("A vBridge has been removed: path={}/{}", tname, bname);
} else {
LOG.error("Failed to remove vBridge: path={}/{}, err={}",
tname, bname, result.getErrorMessage());
}
return code;
}
/**
* Return the current configuration of the specified vBridge.
*
* @param tname The name of the VTN.
* @param bname The name of the vBridge.
* @return A {@link VbridgeConfig} instance if the specified vBridge is
* present. {@code null} otherwise.
*/
public VbridgeConfig getBridgeConfig(String tname, String bname) {
LogicalDatastoreType oper = LogicalDatastoreType.OPERATIONAL;
return mdSal.read(oper, getBridgeConfigPath(tname, bname));
}
/**
* Create or update the specified virtual interface.
*
* @param input A {@link UpdateVinterfaceInput} instance.
* @return A HTTP status code that indicates the result.
* {@link java.net.HttpURLConnection#HTTP_OK} indicates
* successful completion.
*/
public int updateInterface(UpdateVinterfaceInput input) {
VTNRpcResult<UpdateVinterfaceOutput> result =
getRpcResult(vinterfaceService.updateVinterface(input));
int code = result.getStatusCode();
if (code != HTTP_OK) {
LOG.error("Failed to update virtual interface: input={}, err={}",
input, result.getErrorMessage());
} else if (LOG.isDebugEnabled()) {
VtnUpdateType utype = result.getOutput().getStatus();
String msg;
if (utype == VtnUpdateType.CREATED) {
msg = "A virtual interface has been created";
} else if (utype == VtnUpdateType.CHANGED) {
msg = "A virtual interface has been changed";
} else {
assert utype == null;
msg = "A virtual interface is present and not changed";
}
LOG.debug("{}: input={}", msg, input);
}
return code;
}
/**
* Remove the specified virtual interface.
*
* @param input A {@link RemoveVinterfaceInput} instance.
* @return A HTTP status code that indicates the result.
* {@link java.net.HttpURLConnection#HTTP_OK} indicates
* successful completion.
*/
public int removeInterface(RemoveVinterfaceInput input) {
VTNRpcResult<?> result =
getRpcResult(vinterfaceService.removeVinterface(input), true);
int code = result.getStatusCode();
if (code == HTTP_OK) {
LOG.debug("A virtual interface has been removed: input={}",
input);
} else {
LOG.error("Failed to remove virtual interface: input={}, err={}",
input, result.getErrorMessage());
}
return code;
}
/**
* Configure vlan Mapping into the virtual interface specified by the
* given RPC input.
*
* @param input A {@link AddVlanMapInput} instance.
* @return True is returned on successful completion,
else false is returned.
*/
public boolean setVlanMap(AddVlanMapInput input) {
VTNRpcResult<AddVlanMapOutput> result =
getRpcResult(vlanMapService.addVlanMap(input));
int code = result.getStatusCode();
if (code == HTTP_CONFLICT) {
return true;
}
if (code != HTTP_OK) {
LOG.error("Failed to set VlanMap: input={}, err={}",
input, result.getErrorMessage());
return false;
} else {
return true;
}
}
/**
* Remove the Vlan mapping configuration from the specified virtual
* interface.
*
* @param input A {@link RemoveVlanMapInput} instance.
* @return True is returned on successful completion,
else false is returned.
*/
public boolean removeVlanMap(RemoveVlanMapInput input) {
VTNRpcResult<RemoveVlanMapOutput> result =
getRpcResult(vlanMapService.removeVlanMap(input), true);
int code = result.getStatusCode();
if (code != HTTP_OK) {
LOG.error("Failed to remove VlanMap: input={}, err={}",
input, result.getErrorMessage());
return false;
} else {
return true;
}
}
/**
* Configure a FlowCondition into the virtual interface specified by the
* given RPC input.
*
* @param input A {@link SetFlowConditionInput} instance.
* @return True is returned on successful completion,
else false is returned.
*/
public boolean setFlowCond(SetFlowConditionInput input) {
VTNRpcResult<SetFlowConditionOutput> result =
getRpcResult(flowConditionService.setFlowCondition(input));
int code = result.getStatusCode();
if (code != HTTP_OK) {
LOG.error("Failed to set FlowCondition: input={}, err={}",
input, result.getErrorMessage());
return false;
} else {
VtnUpdateType utype = result.getOutput().getStatus();
String msg;
if (utype == VtnUpdateType.CREATED) {
msg = "Flow Conditon has been created";
} else if (utype == VtnUpdateType.CHANGED) {
msg = "Flow COndition has been changed";
}
return true;
}
}
/**
* Unset a FlowCondition into the virtual interface specified by the
* given RPC input.
*
* @param input A {@link RemoveFlowConditionInput} instance.
* @return True is returned on successful completion,
else false is returned.
*/
public boolean unsetFlowCond(RemoveFlowConditionInput input) {
VTNRpcResult result =
getRpcResult(flowConditionService.removeFlowCondition(input), true);
int code = result.getStatusCode();
if (code != HTTP_OK) {
LOG.error("Failed to unset FlowCondition: input={}, err={}",
input, result.getErrorMessage());
return false;
} else {
return true;
}
}
/**
* Set FlowFilter into the virtual interface specified by the
* given RPC input.
*
* @param input A {@link SetFlowFilterInput} instance.
* @return True is returned on successful completion,
else false is returned.
*/
public boolean setFlowFilter(SetFlowFilterInput input) {
VTNRpcResult<SetFlowFilterOutput> result =
getRpcResult(flowFilterService.setFlowFilter(input));
int code = result.getStatusCode();
return (code == HTTP_OK);
}
/**
* Unset a FlowFilter into the virtual interface specified by the
* given RPC input.
*
* @param input A {@link RemoveFlowFilterInput} instance.
* @return True is returned on successful completion,
else false is returned.
*/
public boolean unSetFlowFilter(RemoveFlowFilterInput input) {
VTNRpcResult<RemoveFlowFilterOutput> result =
getRpcResult(flowFilterService.removeFlowFilter(input), true);
int code = result.getStatusCode();
if (code != HTTP_OK) {
LOG.error("Failed to unset Flow Filter: input={}, err={}",
input, result.getErrorMessage());
return false;
} else {
return true;
}
}
}