@Override
  public Answer execute(final PlugNicCommand command, final CitrixResourceBase citrixResourceBase) {
    final Connection conn = citrixResourceBase.getConnection();
    final String vmName = command.getVmName();
    try {
      final Set<VM> vms = VM.getByNameLabel(conn, vmName);
      if (vms == null || vms.isEmpty()) {
        return new PlugNicAnswer(command, false, "Can not find VM " + vmName);
      }
      final VM vm = vms.iterator().next();
      final NicTO nic = command.getNic();

      String mac = nic.getMac();
      final Set<VIF> routerVIFs = vm.getVIFs(conn);
      mac = mac.trim();

      int counter = 0;
      for (final VIF vif : routerVIFs) {
        final String lmac = vif.getMAC(conn);
        if (lmac.trim().equals(mac)) {
          counter++;
        }
      }
      // We allow 2 routers with the same mac. It's needed for the redundant vpc routers.
      // [FIXME] Find a way to identify the type of the router or if it's
      // redundant.
      if (counter > 2) {
        final String msg =
            " Plug Nic failed due to a VIF with the same mac "
                + nic.getMac()
                + " exists in more than 2 routers.";
        s_logger.error(msg);
        return new PlugNicAnswer(command, false, msg);
      }

      // Wilder Rodrigues - replaced this code with the code above.
      // VIF vif = getVifByMac(conn, vm, nic.getMac());
      // if (vif != null) {
      // final String msg = " Plug Nic failed due to a VIF with the same mac " + nic.getMac() + "
      // exists";
      // s_logger.warn(msg);
      // return new PlugNicAnswer(cmd, false, msg);
      // }

      final String deviceId = citrixResourceBase.getLowestAvailableVIFDeviceNum(conn, vm);
      nic.setDeviceId(Integer.parseInt(deviceId));
      final VIF vif = citrixResourceBase.createVif(conn, vmName, vm, null, nic);
      // vif = createVif(conn, vmName, vm, null, nic);
      vif.plug(conn);
      return new PlugNicAnswer(command, true, "success");
    } catch (final Exception e) {
      final String msg = " Plug Nic failed due to " + e.toString();
      s_logger.error(msg, e);
      return new PlugNicAnswer(command, false, msg);
    }
  }
  /**
   * Experimental driver to configure direct networking in libvirt. This should only be used on an
   * LXC cluster that does not run any system VMs.
   *
   * @param nic
   * @param guestOsType
   * @return
   * @throws InternalErrorException
   * @throws LibvirtException
   */
  public LibvirtVMDef.InterfaceDef plug(NicTO nic, String guestOsType)
      throws InternalErrorException, LibvirtException {
    LibvirtVMDef.InterfaceDef intf = new LibvirtVMDef.InterfaceDef();

    if (nic.getType() == Networks.TrafficType.Guest) {
      intf.defDirectNet(
          _libvirtComputingResource.getNetworkDirectDevice(),
          null,
          nic.getMac(),
          getGuestNicModel(guestOsType),
          _libvirtComputingResource.getNetworkDirectSourceMode());

    } else if (nic.getType() == Networks.TrafficType.Public) {
      intf.defDirectNet(
          _libvirtComputingResource.getNetworkDirectDevice(),
          null,
          nic.getMac(),
          getGuestNicModel(guestOsType),
          _libvirtComputingResource.getNetworkDirectSourceMode());
    }

    return intf;
  }
  @Override
  public LibvirtVMDef.InterfaceDef plug(NicTO nic, String guestOsType, String nicAdapter)
      throws InternalErrorException, LibvirtException {

    if (s_logger.isDebugEnabled()) {
      s_logger.debug("nic=" + nic);
      if (nicAdapter != null && !nicAdapter.isEmpty()) {
        s_logger.debug("custom nic adapter=" + nicAdapter);
      }
    }

    LibvirtVMDef.InterfaceDef intf = new LibvirtVMDef.InterfaceDef();

    String vNetId = null;
    String protocol = null;
    if (nic.getBroadcastType() == Networks.BroadcastDomainType.Vlan
        || nic.getBroadcastType() == Networks.BroadcastDomainType.Vxlan) {
      vNetId = Networks.BroadcastDomainType.getValue(nic.getBroadcastUri());
      protocol = Networks.BroadcastDomainType.getSchemeValue(nic.getBroadcastUri()).scheme();
    } else if (nic.getBroadcastType() == Networks.BroadcastDomainType.Lswitch) {
      throw new InternalErrorException(
          "Nicira NVP Logicalswitches are not supported by the BridgeVifDriver");
    }
    String trafficLabel = nic.getName();
    Integer networkRateKBps = 0;
    if (libvirtVersion > ((10 * 1000 + 10))) {
      networkRateKBps =
          (nic.getNetworkRateMbps() != null && nic.getNetworkRateMbps().intValue() != -1)
              ? nic.getNetworkRateMbps().intValue() * 128
              : 0;
    }

    if (nic.getType() == Networks.TrafficType.Guest) {
      if ((nic.getBroadcastType() == Networks.BroadcastDomainType.Vlan)
              && (vNetId != null)
              && (protocol != null)
              && (!vNetId.equalsIgnoreCase("untagged"))
          || (nic.getBroadcastType() == Networks.BroadcastDomainType.Vxlan)) {
        if (trafficLabel != null && !trafficLabel.isEmpty()) {
          s_logger.debug(
              "creating a vNet dev and bridge for guest traffic per traffic label " + trafficLabel);
          String brName = createVnetBr(vNetId, trafficLabel, protocol);
          intf.defBridgeNet(
              brName,
              null,
              nic.getMac(),
              getGuestNicModel(guestOsType, nicAdapter),
              networkRateKBps);
        } else {
          String brName = createVnetBr(vNetId, "private", protocol);
          intf.defBridgeNet(
              brName,
              null,
              nic.getMac(),
              getGuestNicModel(guestOsType, nicAdapter),
              networkRateKBps);
        }
      } else {
        String brname = "";
        if (trafficLabel != null && !trafficLabel.isEmpty()) {
          brname = trafficLabel;
        } else {
          brname = _bridges.get("guest");
        }
        intf.defBridgeNet(
            brname, null, nic.getMac(), getGuestNicModel(guestOsType, nicAdapter), networkRateKBps);
      }
    } else if (nic.getType() == Networks.TrafficType.Control) {
      /* Make sure the network is still there */
      createControlNetwork();
      intf.defBridgeNet(
          _bridges.get("linklocal"), null, nic.getMac(), getGuestNicModel(guestOsType, nicAdapter));
    } else if (nic.getType() == Networks.TrafficType.Public) {
      if ((nic.getBroadcastType() == Networks.BroadcastDomainType.Vlan)
              && (vNetId != null)
              && (protocol != null)
              && (!vNetId.equalsIgnoreCase("untagged"))
          || (nic.getBroadcastType() == Networks.BroadcastDomainType.Vxlan)) {
        if (trafficLabel != null && !trafficLabel.isEmpty()) {
          s_logger.debug(
              "creating a vNet dev and bridge for public traffic per traffic label "
                  + trafficLabel);
          String brName = createVnetBr(vNetId, trafficLabel, protocol);
          intf.defBridgeNet(
              brName,
              null,
              nic.getMac(),
              getGuestNicModel(guestOsType, nicAdapter),
              networkRateKBps);
        } else {
          String brName = createVnetBr(vNetId, "public", protocol);
          intf.defBridgeNet(
              brName,
              null,
              nic.getMac(),
              getGuestNicModel(guestOsType, nicAdapter),
              networkRateKBps);
        }
      } else {
        intf.defBridgeNet(
            _bridges.get("public"),
            null,
            nic.getMac(),
            getGuestNicModel(guestOsType, nicAdapter),
            networkRateKBps);
      }
    } else if (nic.getType() == Networks.TrafficType.Management) {
      intf.defBridgeNet(
          _bridges.get("private"), null, nic.getMac(), getGuestNicModel(guestOsType, nicAdapter));
    } else if (nic.getType() == Networks.TrafficType.Storage) {
      String storageBrName = nic.getName() == null ? _bridges.get("private") : nic.getName();
      intf.defBridgeNet(
          storageBrName, null, nic.getMac(), getGuestNicModel(guestOsType, nicAdapter));
    }
    if (nic.getPxeDisable() == true) {
      intf.setPxeDisable(true);
    }
    return intf;
  }