@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);
    }
  }
  @Override
  public Answer execute(
      final PvlanSetupCommand command, final CitrixResourceBase citrixResourceBase) {
    final Connection conn = citrixResourceBase.getConnection();

    final String primaryPvlan = command.getPrimary();
    final String isolatedPvlan = command.getIsolated();
    final String op = command.getOp();
    final String dhcpName = command.getDhcpName();
    final String dhcpMac = command.getDhcpMac();
    final String dhcpIp = command.getDhcpIp();
    final String vmMac = command.getVmMac();
    final String networkTag = command.getNetworkTag();

    String nwNameLabel = null;
    try {
      final XsLocalNetwork nw =
          citrixResourceBase.getNativeNetworkForTraffic(conn, TrafficType.Guest, networkTag);
      if (nw == null) {
        s_logger.error("Network is not configured on the backend for pvlan " + primaryPvlan);
        throw new CloudRuntimeException(
            "Network for the backend is not configured correctly for pvlan primary: "
                + primaryPvlan);
      }
      nwNameLabel = nw.getNetwork().getNameLabel(conn);
    } catch (final XenAPIException e) {
      s_logger.warn("Fail to get network", e);
      return new Answer(command, false, e.toString());
    } catch (final XmlRpcException e) {
      s_logger.warn("Fail to get network", e);
      return new Answer(command, false, e.toString());
    }

    String result = null;
    if (command.getType() == PvlanSetupCommand.Type.DHCP) {
      result =
          citrixResourceBase.callHostPlugin(
              conn,
              "ovs-pvlan",
              "setup-pvlan-dhcp",
              "op",
              op,
              "nw-label",
              nwNameLabel,
              "primary-pvlan",
              primaryPvlan,
              "isolated-pvlan",
              isolatedPvlan,
              "dhcp-name",
              dhcpName,
              "dhcp-ip",
              dhcpIp,
              "dhcp-mac",
              dhcpMac);

      if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) {
        s_logger.warn("Failed to program pvlan for dhcp server with mac " + dhcpMac);
        return new Answer(command, false, result);
      } else {
        s_logger.info("Programmed pvlan for dhcp server with mac " + dhcpMac);
      }
    } else if (command.getType() == PvlanSetupCommand.Type.VM) {
      result =
          citrixResourceBase.callHostPlugin(
              conn,
              "ovs-pvlan",
              "setup-pvlan-vm",
              "op",
              op,
              "nw-label",
              nwNameLabel,
              "primary-pvlan",
              primaryPvlan,
              "isolated-pvlan",
              isolatedPvlan,
              "vm-mac",
              vmMac);

      if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) {
        s_logger.warn("Failed to program pvlan for vm with mac " + vmMac);
        return new Answer(command, false, result);
      } else {
        s_logger.info("Programmed pvlan for vm with mac " + vmMac);
      }
    }
    return new Answer(command, true, result);
  }
  @Override
  public Answer execute(
      final CheckNetworkCommand command, final CitrixResourceBase citrixResourceBase) {
    if (s_logger.isDebugEnabled()) {
      s_logger.debug("Checking if network name setup is done on the resource");
    }

    final List<PhysicalNetworkSetupInfo> infoList = command.getPhysicalNetworkInfoList();

    try {
      boolean errorout = false;
      String msg = "";
      for (final PhysicalNetworkSetupInfo info : infoList) {
        if (!citrixResourceBase.isNetworkSetupByName(info.getGuestNetworkName())) {
          msg =
              "For Physical Network id:"
                  + info.getPhysicalNetworkId()
                  + ", Guest Network is not configured on the backend by name "
                  + info.getGuestNetworkName();
          errorout = true;
          break;
        }
        if (!citrixResourceBase.isNetworkSetupByName(info.getPrivateNetworkName())) {
          msg =
              "For Physical Network id:"
                  + info.getPhysicalNetworkId()
                  + ", Private Network is not configured on the backend by name "
                  + info.getPrivateNetworkName();
          errorout = true;
          break;
        }
        if (!citrixResourceBase.isNetworkSetupByName(info.getPublicNetworkName())) {
          msg =
              "For Physical Network id:"
                  + info.getPhysicalNetworkId()
                  + ", Public Network is not configured on the backend by name "
                  + info.getPublicNetworkName();
          errorout = true;
          break;
        }
        /*if(!isNetworkSetupByName(info.getStorageNetworkName())){
            msg = "For Physical Network id:"+ info.getPhysicalNetworkId() + ", Storage Network is not configured on the backend by name " + info.getStorageNetworkName();
            errorout = true;
            break;
        }*/
      }
      if (errorout) {
        s_logger.error(msg);
        return new CheckNetworkAnswer(command, false, msg);
      } else {
        return new CheckNetworkAnswer(command, true, "Network Setup check by names is done");
      }

    } catch (final XenAPIException e) {
      final String msg =
          "CheckNetworkCommand failed with XenAPIException:"
              + e.toString()
              + " host:"
              + citrixResourceBase.getHost().getUuid();
      s_logger.warn(msg, e);
      return new CheckNetworkAnswer(command, false, msg);
    } catch (final Exception e) {
      final String msg =
          "CheckNetworkCommand failed with Exception:"
              + e.getMessage()
              + " host:"
              + citrixResourceBase.getHost().getUuid();
      s_logger.warn(msg, e);
      return new CheckNetworkAnswer(command, false, msg);
    }
  }
  @Override
  public Answer execute(final ScaleVmCommand command, final CitrixResourceBase citrixResourceBase) {
    final VirtualMachineTO vmSpec = command.getVirtualMachine();
    final String vmName = vmSpec.getName();
    try {
      final Connection conn = citrixResourceBase.getConnection();
      final Set<VM> vms = VM.getByNameLabel(conn, vmName);
      final Host host = Host.getByUuid(conn, citrixResourceBase.getHost().getUuid());

      // If DMC is not enable then don't execute this command.
      if (!citrixResourceBase.isDmcEnabled(conn, host)) {
        throw new CloudRuntimeException(
            "Unable to scale the vm: "
                + vmName
                + " as DMC - Dynamic memory control is not enabled for the XenServer:"
                + citrixResourceBase.getHost().getUuid()
                + " ,check your license and hypervisor version.");
      }

      if (vms == null || vms.size() == 0) {
        s_logger.info(
            "No running VM "
                + vmName
                + " exists on XenServer"
                + citrixResourceBase.getHost().getUuid());
        return new ScaleVmAnswer(command, false, "VM does not exist");
      }

      // stop vm which is running on this host or is in halted state
      final Iterator<VM> iter = vms.iterator();
      while (iter.hasNext()) {
        final VM vm = iter.next();
        final VM.Record vmr = vm.getRecord(conn);

        if (vmr.powerState == VmPowerState.HALTED
            || vmr.powerState == VmPowerState.RUNNING
                && !citrixResourceBase.isRefNull(vmr.residentOn)
                && !vmr.residentOn.getUuid(conn).equals(citrixResourceBase.getHost().getUuid())) {
          iter.remove();
        }
      }

      for (final VM vm : vms) {
        vm.getRecord(conn);
        try {
          citrixResourceBase.scaleVM(conn, vm, vmSpec, host);
        } catch (final Exception e) {
          final String msg =
              "Catch exception "
                  + e.getClass().getName()
                  + " when scaling VM:"
                  + vmName
                  + " due to "
                  + e.toString();
          s_logger.debug(msg);
          return new ScaleVmAnswer(command, false, msg);
        }
      }
      final String msg = "scaling VM " + vmName + " is successful on host " + host;
      s_logger.debug(msg);
      return new ScaleVmAnswer(command, true, msg);

    } catch (final XenAPIException e) {
      final String msg = "Upgrade Vm " + vmName + " fail due to " + e.toString();
      s_logger.warn(msg, e);
      return new ScaleVmAnswer(command, false, msg);
    } catch (final XmlRpcException e) {
      final String msg = "Upgrade Vm " + vmName + " fail due to " + e.getMessage();
      s_logger.warn(msg, e);
      return new ScaleVmAnswer(command, false, msg);
    } catch (final Exception e) {
      final String msg = "Unable to upgrade " + vmName + " due to " + e.getMessage();
      s_logger.warn(msg, e);
      return new ScaleVmAnswer(command, false, msg);
    }
  }