private JMXConnector initJMXConnector(String svcName)
      throws IOException, AttachNotSupportedException, AgentLoadException,
          AgentInitializationException {
    int pid = PlatformUtils.getServicePid(svcName);
    log.info("{} service pid {}", svcName, pid);

    VirtualMachine vm = VirtualMachine.attach(String.valueOf(pid));
    try {
      String connectorAddress = vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);
      if (connectorAddress == null) {
        String agent =
            Strings.join(
                File.separator,
                vm.getSystemProperties().getProperty("java.home"),
                "lib",
                "management-agent.jar");
        vm.loadAgent(agent);

        connectorAddress = vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);
      }

      JMXServiceURL serviceURL = new JMXServiceURL(connectorAddress);
      return JMXConnectorFactory.connect(serviceURL);
    } finally {
      vm.detach();
    }
  }
  @POST
  @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
  @Path("/natcheck")
  public VdcNatCheckResponse checkIfBehindNat(
      VdcNatCheckParam checkParam, @HeaderParam("X-Forwarded-For") String clientIp) {
    if (checkParam == null) {
      log.error("checkParam is null, X-Forwarded-For is {}", clientIp);
      throw GeoException.fatals.invalidNatCheckCall("(null)", clientIp);
    }

    String ipv4Str = checkParam.getIPv4Address();
    String ipv6Str = checkParam.getIPv6Address();
    log.info(
        String.format(
            "Performing NAT check, client address connecting to VIP: %s. Client reports its IPv4 = %s, IPv6 = %s",
            clientIp, ipv4Str, ipv6Str));

    InetAddress ipv4Addr = parseInetAddress(ipv4Str);
    InetAddress ipv6Addr = parseInetAddress(ipv6Str);
    InetAddress directAddr = parseInetAddress(clientIp);
    if (directAddr == null || ipv4Addr == null && ipv6Addr == null) {
      String ipAddrsStr = Strings.join("|", ipv4Str, ipv6Addr);
      log.error("checkParam is {}, X-Forwarded-For is {}", ipAddrsStr, clientIp);
      throw GeoException.fatals.invalidNatCheckCall(ipAddrsStr, clientIp);
    }

    VdcNatCheckResponse resp = new VdcNatCheckResponse();
    resp.setSeenIp(clientIp);
    resp.setBehindNAT(!directAddr.equals(ipv4Addr) && !directAddr.equals(ipv6Addr));

    return resp;
  }
 /**
  * Get controller ovf properties
  *
  * @return PropertyInfo controller ovf properties
  */
 public PropertyInfoExt getControllerOvfProperties() throws LocalRepositoryException {
   final String prefix = "getControllerOvfProperties(): ";
   _log.debug(prefix);
   final String[] cmd = {_SYSTOOL_CMD, _SYSTOOL_GET_CONTROLLEROVFPROPS};
   PropertyInfoExt overrides = new PropertyInfoExt(exec(prefix, cmd));
   _log.debug(prefix + "properties={}", Strings.repr(overrides));
   return overrides;
 }
  /**
   * get all remote nodes in the cluster, includes nodes in standby sites
   *
   * @return
   * @throws LocalRepositoryException
   */
  public String[] getAllRemoteNodesIncluster() throws LocalRepositoryException {
    final String prefix = "getAllRemoteNodesIncluster(): ";
    _log.debug(prefix);

    final String[] cmd = {_IPSECTOOL_CMD, IPSEC_GET_ALL_REMOTE_NODES};
    String[] ips = exec(prefix, cmd);

    _log.debug(prefix + "all remote ips the cluster: ", Strings.repr(ips));
    return ips;
  }
  /**
   * check ipsec connections between local machine and other nodes in vipr
   *
   * @return ips don't have ipsec connection with local machine
   * @throws LocalRepositoryException
   */
  public String[] checkIpsecConnection() throws LocalRepositoryException {
    final String prefix = "checkIpsecConnection(): ";
    _log.debug(prefix);

    final String[] cmd = {_IPSECTOOL_CMD, IPSEC_CHECK_CONNECTION};
    String[] ips = exec(prefix, cmd);

    _log.debug(prefix + "ips without ipsec connection: ", Strings.repr(ips));
    return ips;
  }
  /**
   * * Get data revision from disk
   *
   * @return DataRevisonTag
   */
  public PropertyInfoExt getDataRevisionPropertyInfo() throws LocalRepositoryException {
    final String prefix = "getDataRevisionPropertyInfo(): ";
    _log.debug(prefix);

    final String[] cmd1 = {_SYSTOOL_CMD, _SYSTOOL_GET_DATA_REVISION};
    String[] props = exec(prefix, cmd1);

    _log.debug(prefix + "properties={}", Strings.repr(props));
    return new PropertyInfoExt(props);
  }
  /**
   * *
   *
   * @return RepositoryState
   * @throws InvalidRepositoryInfoException
   */
  public RepositoryInfo getRepositoryInfo()
      throws LocalRepositoryException, InvalidRepositoryInfoException {
    final String prefix = "getRepositoryState(): ";
    _log.debug(prefix);

    final String[] cmd1 = {_SYSTOOL_CMD, _SYSTOOL_LIST};
    List<SoftwareVersion> versions =
        toSoftwareVersionList(prefix + _SYSTOOL_LIST, exec(prefix, cmd1));

    final String[] cmd2 = {_SYSTOOL_CMD, _SYSTOOL_GET_DEFAULT};
    final SoftwareVersion current =
        toSoftwareVersionList(prefix + _SYSTOOL_GET_DEFAULT, exec(prefix, cmd2)).get(0);

    _log.debug(prefix + "current={} versions={}", current, Strings.repr(versions));
    return new RepositoryInfo(current, versions);
  }
  /**
   * * Open an InputStream to a local image
   *
   * @param version - SoftwareVersion of the image
   * @return an opened InputStream (FileInputStream)
   */
  public InputStream getImageInputStream(SoftwareVersion version) throws LocalRepositoryException {
    final String prefix = "getImageInputStream(): version=" + version + ": ";
    final String[] cmd = {_SYSTOOL_CMD, _SYSTOOL_GET_IMAGE, version.toString()};
    final String[] images = exec(prefix, cmd);
    _log.debug(prefix + "images=" + Strings.repr(images));

    if (images == null) {
      throw SyssvcException.syssvcExceptions.localRepoError(prefix + "Internal error. Null output");
    } else if (images.length == 0) {
      throw SyssvcException.syssvcExceptions.localRepoError(prefix + "Internal error. No results.");
    }

    try {
      return new FileInputStream(images[0]);
    } catch (Exception e) {
      throw SyssvcException.syssvcExceptions.localRepoError(prefix + e);
    }
  }