/*
  	 * (non-Javadoc)
  	 *
  	 * @see com.msi.tough.query.AbstractProxyAction#
  	protected DescribeDBParameterGroupsActionResultMessage doWork0(DescribeDBParameterGroupsActionRequestMessage req,
  ServiceRequestContext context) throws Exception {

  	 * javax.servlet.http.HttpServletRequest,
  	 * javax.servlet.http.HttpServletResponse, java.util.Map)
  	 */
  @Override
  protected DescribeDBParameterGroupsActionResultMessage doWork0(
      DescribeDBParameterGroupsActionRequestMessage req, ServiceRequestContext context)
      throws Exception {

    DescribeDBParameterGroupsActionResultMessage.Builder resp = null;
    String msg = "";
    final Session sess = HibernateUtil.newSession();
    try {
      sess.beginTransaction();
      final AccountBean ac = context.getAccountBean();
      final long userID = ac.getId();
      final String grpName = req.getDbParameterGroupName();
      final String marker = req.getMarker();
      final int maxRecords = ValidationManager.validateMaxRecords(req.getMaxRecords(), false);

      logger.info(
          "DescribeDBParameterGroups: "
              + " account = "
              + ac.getId()
              + " DBParameterGroupName = "
              + grpName
              + " Marker = "
              + marker
              + " MaxRecords = "
              + maxRecords);

      // select the list of DBParameterGroups.
      final List<RdsDbparameterGroup> result =
          ParameterGroupEntity.selectDBParameterGroups(
              sess, grpName, ac.getId(), marker, maxRecords);

      if (grpName != null && (result == null || result.size() == 0)) {
        throw RDSQueryFaults.DBParameterGroupNotFound();
      }

      // build response document
      final List<DBParameterGroup> grl = new ArrayList<DBParameterGroup>();
      if (result != null) {
        logger.debug(
            result.size() + " DBParameterGroups are selected from custom DBParameterGroups.");
        for (final RdsDbparameterGroup gb : result) {
          grl.add(toDBParameterGroup(gb));
        }
      }
      resp = DescribeDBParameterGroupsActionResultMessage.newBuilder();
      resp.addAllDbParameterGroups(grl);
      sess.getTransaction().commit();
    } catch (final ErrorResponse rde) {
      sess.getTransaction().rollback();
      throw rde;
    } catch (final Exception e) {
      e.printStackTrace();
      sess.getTransaction().rollback();
      msg = "DescribeDBParameterGroups: Class: " + e.getClass() + "Msg:" + e.getMessage();
      logger.error(msg);
      throw RDSQueryFaults.InternalFailure();
    } finally {
      sess.close();
    }
    return resp.buildPartial();
  }
  /*
   * (non-Javadoc)
   *
   * @see
   * com.msi.tough.workflow.core.AbstractWorker#doWork0(com.google.protobuf
   * .Message, com.msi.tough.query.ServiceRequestContext)
   */
  @Override
  protected AssociateAddressResponse doWork0(
      AssociateAddressRequest req, ServiceRequestContext context) throws Exception {

    final AssociateAddressResponse.Builder result = AssociateAddressResponse.newBuilder();
    final AccountBean account = context.getAccountBean();

    final CloudProvider cloudProvider =
        DaseinHelper.getProvider(
            account.getDefZone(), account.getTenant(),
            account.getAccessKey(), account.getSecretKey());
    final ComputeServices compute = cloudProvider.getComputeServices();
    final VirtualMachineSupport vmSupport = compute.getVirtualMachineSupport();

    final String publicIp = req.getPublicIp();
    final String instanceId = req.getInstanceId();

    VirtualMachine vm = vmSupport.getVirtualMachine(instanceId);
    // Check if instance id refers to existing instance
    if (vm == null) {
      throw ComputeFaults.instanceDoesNotExist(instanceId);
    }

    final NetworkServices network = cloudProvider.getNetworkServices();
    final IpAddressSupport ipsupport = network.getIpAddressSupport();

    // check if specified address exists in the pool
    IpAddress address = null;
    for (final IpAddress i : ipsupport.listIpPool(IPVersion.IPV4, false)) {
      if (i.getRawAddress().getIpAddress().equals(publicIp)) {
        address = i;
        break;
      }
    }
    if (address == null || "".equals(address.getRawAddress().getIpAddress())) {
      throw ComputeFaults.IpAddressDoesNotExist(publicIp);
    }

    logger.debug("Address info - BEGIN: \n" + address.toString() + "\n - END");
    logger.debug("Address ID: " + address.getProviderIpAddressId());

    // Currently Dasein gets for the actual string "null" rather than the
    // null object for address.getServerId() if there is no assigned
    // instance
    // According to AWS docs, if address is associated with another
    // instance, disassociate it and reassociate to the instance specified
    // in the request.
    if (address.getServerId() != null && !address.getServerId().equals("null")) {
      logger.info("The address " + publicIp + " is currently associated with an instance.");
      logger.info("Diassociating address...");
      ipsupport.releaseFromServer(address.getProviderIpAddressId());
    }

    logger.info(
        "Associating address "
            + address.getRawAddress().getIpAddress()
            + " to instance "
            + instanceId);

    if ("OpenStack".equals(cloudProvider.getProviderName())) {
      String privateIp = null;
      int retryCount = 0;
      while (privateIp == null && retryCount++ < RETRY_MAX) {
        // Must avoid associating too early; instance should have a fixed IP.
        if (vm.getPrivateAddresses() != null && vm.getPrivateAddresses().length > 0) {
          privateIp = vm.getPrivateAddresses()[0].getIpAddress();
        }
        if (privateIp == null || privateIp.length() == 0 || privateIp.equals("0.0.0.0")) {
          logger.debug("Instance does not have private IP, waiting for network ready.");
          privateIp = null;
          Thread.sleep(RETRY_SECS * 1000);
          vm = vmSupport.getVirtualMachine(instanceId);
        }
      }
      if (retryCount >= RETRY_MAX) {
        logger.error("Error assigning IP Address: instance doesn't " + "have a private IP.");
        throw QueryFaults.invalidState();
      }
    }

    /*
     * TODO: Add VPC Support.
     *   THIS IMPLEMENTATION SUPPORTS EC2-CLASSIC ONLY!
     */
    try {
      ipsupport.assign(address.getProviderIpAddressId(), instanceId);
    } catch (final CloudException e) {
      final ExceptionItems eitms = NovaException.parseException(e.getHttpCode(), e.getMessage());
      throw new Exception("Error assigning IP Address: error type = " + eitms.type.toString());
    }

    /* If execution arrives here, no exceptions occurred */
    result.setReturn(true);
    return result.buildPartial();
  }