/*
   * Utility method for JSON'izing a single LB
   */
  protected String LbToJson(LoadBalancer lb, String action) throws JSONException {

    JSONObject jsonResponseObject = new JSONObject();
    try {
      // internal fields for worker IPC only
      if (action != null) {
        jsonResponseObject.put(HPCS_REQUESTID, ++requestId);
        jsonResponseObject.put(HPCS_ACTION, action);
        jsonResponseObject.put(HPCS_DEVICE, lb.getDevice());
      }
      jsonResponseObject.put("name", lb.getName());
      jsonResponseObject.put("id", lb.getId());
      jsonResponseObject.put("protocol", lb.getProtocol());
      jsonResponseObject.put("port", lb.getPort());
      jsonResponseObject.put("algorithm", lb.getAlgorithm());
      jsonResponseObject.put("status", lb.getStatus());
      jsonResponseObject.put("created", lb.getCreated());
      jsonResponseObject.put("updated", lb.getUpdated());

      // vips
      JSONArray jsonVipArray = new JSONArray();
      VirtualIps vips = lb.getVirtualIps();
      if (vips != null) {
        List<VirtualIp> vipslist = vips.getVirtualIps();
        if (vipslist != null)
          for (int x = 0; x < vipslist.size(); x++) {
            JSONObject jsonVIP = new JSONObject();
            jsonVIP.put("address", vipslist.get(x).getAddress());
            jsonVIP.put("id", vipslist.get(x).getId());
            jsonVIP.put("type", vipslist.get(x).getType());
            jsonVIP.put("ipVersion", vipslist.get(x).getIpVersion());
            jsonVipArray.put(jsonVIP);
          }
      }
      jsonResponseObject.put("virtualIps", jsonVipArray);

      // nodes
      JSONArray jsonNodeArray = new JSONArray();
      Nodes nodes = lb.getNodes();
      if (nodes != null) {
        List<Node> nodeList = nodes.getNodes();
        for (int y = 0; y < nodeList.size(); y++) {
          JSONObject jsonNode = new JSONObject();
          jsonNode.put("address", nodeList.get(y).getAddress());
          jsonNode.put("id", nodeList.get(y).getId());
          jsonNode.put("port", nodeList.get(y).getPort());
          jsonNode.put("status", nodeList.get(y).getStatus());
          jsonNodeArray.put(jsonNode);
        }
      }
      jsonResponseObject.put("nodes", jsonNodeArray);

      return jsonResponseObject.toString();
    } catch (JSONException jsone) {
      throw jsone;
    }
  }
  /*
   * Create a new LB
   */
  @POST
  @Consumes("application/json")
  @Produces("application/json")
  public String post(String content) {
    logger.info("POST loadbalancers");

    Device device = null;

    // process POSTed body
    LoadBalancerDataModel lbModel = new LoadBalancerDataModel();
    LoadBalancer lb = new LoadBalancer();
    Integer lbId = 0;
    int x = 0;
    try {
      JSONObject jsonObject = new JSONObject(content);
      String name = (String) jsonObject.get("name");
      lb.setName(name);
      logger.info("   name = " + name);

      // minimally request needs nodes
      if (!jsonObject.has("nodes")) {
        throw new LBaaSException("nodes are required", 400); //  bad request			
      }

      // check to ensure protocol is supported
      if (jsonObject.has("protocol")) {
        String protocol = (String) jsonObject.get("protocol");
        if (!ProtocolHandler.exists(protocol)) {
          throw new LBaaSException(
              "protocol specified not supported : " + protocol, 400); //  bad request				
        } else {
          logger.info("   protocol = " + protocol);
          lb.setProtocol(protocol);
          lb.setPort(ProtocolHandler.getPort(protocol));
          logger.info("   port = " + lb.getPort());
        }
      }

      // nodes
      Nodes nodes = new Nodes();
      JSONArray jsonNodesArray = (JSONArray) jsonObject.get("nodes");
      for (x = 0; x < jsonNodesArray.length(); x++) {
        Node node = new Node();
        // logger.info("node["+x+"] = "+ jsonNodesArray.getJSONObject(x));
        JSONObject jsonNode = jsonNodesArray.getJSONObject(x);
        String address = (String) jsonNode.get("address");
        node.setAddress(address);
        String port = (String) jsonNode.get("port");
        node.setPort(Integer.valueOf(port));
        node.setStatus("ONLINE");
        node.setId(new Integer(x + 1));
        logger.info("   Node[" + x + "]");
        logger.info("      address = " + address);
        logger.info("      port = " + port);
        logger.info("      status = " + node.getStatus());
        nodes.getNodes().add(node);
      }
      lb.setNodes(nodes);

      // vips
      VirtualIps virtualIps = new VirtualIps();
      if (jsonObject.has("virtualIps")) {
        JSONArray jsonVIPArray = (JSONArray) jsonObject.get("virtualIps");
        for (x = 0; x < jsonVIPArray.length(); x++) {
          VirtualIp virtualIp = new VirtualIp();
          // logger.info("vip["+x+"] = "+ jsonVIPArray.getJSONObject(x));
          JSONObject jsonVip = jsonVIPArray.getJSONObject(x);

          String address = (String) jsonVip.get("address");
          virtualIp.setAddress(address);

          if (jsonVip.get("ipVersion").toString().equalsIgnoreCase("IPV4"))
            virtualIp.setIpVersion(IpVersion.IPV_4);
          else virtualIp.setIpVersion(IpVersion.IPV_6);

          if (jsonVip.get("type").toString().equalsIgnoreCase("public"))
            virtualIp.setType(VipType.PUBLIC);
          else virtualIp.setType(VipType.PRIVATE);

          virtualIp.setId(new Integer(x + 1));

          logger.info("   VIP[" + x + "]");
          logger.info("      address = " + virtualIp.getAddress());
          logger.info("      ipversion = " + virtualIp.getIpVersion().toString());
          logger.info("      type = " + virtualIp.getType().toString());
          virtualIps.getVirtualIps().add(virtualIp);
        }
        lb.setVirtualIps(virtualIps);
      }

      // find free device to use
      DeviceDataModel deviceModel = new DeviceDataModel();
      device = deviceModel.findFreeDevice();
      if (device == null) {
        throw new LBaaSException("cannot find free device available", 503); //  not available
      }

      logger.info("found free device at id : " + device.getId().toString());

      // create new LB
      lb.setDevice(device.getId()); // set lb device id
      lbId = lbModel.createLoadBalancer(lb); // write it to datamodel

      // set device lb and write it back to data model
      device.setLbId(lbId);
      deviceModel.setDevice(device);

    } catch (JSONException e) {
      return e.toString();
    }

    // read LB back from data model, it will now have valid id
    LoadBalancer lbResponse = lbModel.getLoadBalancer(lbId);

    // have the device process the request
    try {
      lbaasTaskManager.sendJob(lbResponse.getDevice(), LbToJson(lb, ACTION_CREATE));
    } catch (JSONException jsone) {
      throw new LBaaSException(
          "internal server error JSON exception :" + jsone.toString(), 500); //  internal error
    }

    // respond with JSON
    try {
      return LbToJson(lbResponse, null);
    } catch (JSONException jsone) {
      throw new LBaaSException(
          "internal server error JSON exception :" + jsone.toString(), 500); //  internal error
    }
  }