You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by la...@apache.org on 2025/09/23 05:01:37 UTC

(airavata-custos) branch amie-decoder updated (53f2f81ea -> f958d512c)

This is an automated email from the ASF dual-hosted git repository.

lahirujayathilake pushed a change to branch amie-decoder
in repository https://gitbox.apache.org/repos/asf/airavata-custos.git


    from 53f2f81ea AMIE packet processing worker and handler skeleton
     new 1215b8f17 AmieClient replying to a packet method support
     new f958d512c AMIE account creation handler implementation

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../org/apache/custos/amie/client/AmieClient.java  | 56 ++++++++++---
 .../amie/handler/RequestAccountCreateHandler.java  | 96 ++++++++++++++++++++++
 2 files changed, 140 insertions(+), 12 deletions(-)
 create mode 100644 amie-decoder/src/main/java/org/apache/custos/amie/handler/RequestAccountCreateHandler.java


(airavata-custos) 01/02: AmieClient replying to a packet method support

Posted by la...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lahirujayathilake pushed a commit to branch amie-decoder
in repository https://gitbox.apache.org/repos/asf/airavata-custos.git

commit 1215b8f1729746784c1cb86780dce2825f5e04e1
Author: lahiruj <la...@gmail.com>
AuthorDate: Tue Sep 23 00:40:45 2025 -0400

    AmieClient replying to a packet method support
---
 .../org/apache/custos/amie/client/AmieClient.java  | 56 +++++++++++++++++-----
 1 file changed, 44 insertions(+), 12 deletions(-)

diff --git a/amie-decoder/src/main/java/org/apache/custos/amie/client/AmieClient.java b/amie-decoder/src/main/java/org/apache/custos/amie/client/AmieClient.java
index 1b787a14d..679b74bc6 100644
--- a/amie-decoder/src/main/java/org/apache/custos/amie/client/AmieClient.java
+++ b/amie-decoder/src/main/java/org/apache/custos/amie/client/AmieClient.java
@@ -30,14 +30,15 @@ import org.springframework.http.HttpMethod;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Component;
+import org.springframework.web.client.HttpClientErrorException;
 import org.springframework.web.client.RestClientException;
 import org.springframework.web.client.RestTemplate;
-import org.springframework.web.util.UriComponentsBuilder;
 
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 
 /**
  * A client for Access CI AMIE REST API
@@ -65,20 +66,14 @@ public class AmieClient {
      * @return A list of packets. Returns an empty list if the call fails or no packets are found.
      */
     public List<JsonNode> fetchInProgressPackets() {
-        URI uri = UriComponentsBuilder.fromHttpUrl(properties.getBaseUrl())
-                .path(PACKETS_PATH)
-                .build(properties.getSiteCode());
-
-        HttpHeaders headers = new HttpHeaders();
-        headers.set(HEADER_XA_SITE, properties.getSiteCode());
-        headers.set(HEADER_XA_API_KEY, properties.getApiKey());
-        headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
+        String url = String.format("%s/packets/%s/", properties.getBaseUrl(), properties.getSiteCode());
+        LOGGER.info("Polling for AMIE packets at URL: {}", url);
 
+        HttpHeaders headers = createAmieHeaders();
         HttpEntity<String> entity = new HttpEntity<>(headers);
 
         try {
-            LOGGER.debug("Fetching in-progress packets from {}", uri);
-            ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.GET, entity, String.class);
+            ResponseEntity<String> response = restTemplate.exchange(URI.create(url), HttpMethod.GET, entity, String.class);
 
             if (!response.getStatusCode().is2xxSuccessful() || response.getBody() == null) {
                 LOGGER.warn("Received a non-successful response from AMIE API: {} {}", response.getStatusCode(), response.getBody());
@@ -88,11 +83,48 @@ public class AmieClient {
             return parsePacketsFromResponse(response.getBody());
 
         } catch (RestClientException e) {
-            LOGGER.error("Failed to fetch packets from AMIE API at {}", uri, e);
+            LOGGER.error("An unexpected error occurred while fetching packets.", e);
             return Collections.emptyList();
         }
     }
 
+    /**
+     * Sends a reply packet to the AMIE API to continue a transaction.
+     * For example, sending a 'notify_project_create' in response to a 'request_project_create'.
+     *
+     * @param packetRecId The ID of the packet this reply is for.
+     * @param replyBody   A Map representing the JSON body of the reply packet.
+     */
+    public void replyToPacket(long packetRecId, Map<String, Object> replyBody) {
+        String url = String.format("%s/packets/%s/%d/reply", properties.getBaseUrl(), properties.getSiteCode(), packetRecId);
+        LOGGER.info("Sending reply to URL: {}", url);
+
+        HttpHeaders headers = createAmieHeaders();
+        headers.setContentType(MediaType.APPLICATION_JSON);
+
+        HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(replyBody, headers);
+
+        try {
+            ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
+            if (response.getStatusCode().is2xxSuccessful()) {
+                LOGGER.info("Successfully sent reply for packet_rec_id [{}].", packetRecId);
+            } else {
+                LOGGER.error("Failed to send reply for packet_rec_id [{}]. Status: {}, Body: {}", packetRecId, response.getStatusCode(), response.getBody());
+            }
+        } catch (HttpClientErrorException e) {
+            LOGGER.error("HTTP error sending reply for packet_rec_id [{}]: {} {}", packetRecId, e.getStatusCode(), e.getResponseBodyAsString(), e);
+            throw e;
+        }
+    }
+
+    private HttpHeaders createAmieHeaders() {
+        HttpHeaders headers = new HttpHeaders();
+        headers.set(HEADER_XA_SITE, properties.getSiteCode());
+        headers.set(HEADER_XA_API_KEY, properties.getApiKey());
+        headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
+        return headers;
+    }
+
     private List<JsonNode> parsePacketsFromResponse(String responseBody) {
         List<JsonNode> packets = new ArrayList<>();
         try {


(airavata-custos) 02/02: AMIE account creation handler implementation

Posted by la...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lahirujayathilake pushed a commit to branch amie-decoder
in repository https://gitbox.apache.org/repos/asf/airavata-custos.git

commit f958d512c5051bc3999655fd4d9171d3725c5070
Author: lahiruj <la...@gmail.com>
AuthorDate: Tue Sep 23 01:01:24 2025 -0400

    AMIE account creation handler implementation
---
 .../amie/handler/RequestAccountCreateHandler.java  | 96 ++++++++++++++++++++++
 1 file changed, 96 insertions(+)

diff --git a/amie-decoder/src/main/java/org/apache/custos/amie/handler/RequestAccountCreateHandler.java b/amie-decoder/src/main/java/org/apache/custos/amie/handler/RequestAccountCreateHandler.java
new file mode 100644
index 000000000..9fe14b712
--- /dev/null
+++ b/amie-decoder/src/main/java/org/apache/custos/amie/handler/RequestAccountCreateHandler.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.custos.amie.handler;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.apache.custos.amie.client.AmieClient;
+import org.apache.custos.amie.model.PacketEntity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.util.Assert;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * Handles the 'request_account_create' AMIE packet.
+ * <p>
+ * This transaction asks the local site to create an account for a user on a project.
+ * This includes creating a local user account with the specified project (a Unix account) if one does not exist.
+ * Upon successful processing sends a 'notify_account_create' reply back to AMIE.
+ */
+@Component
+public class RequestAccountCreateHandler implements PacketHandler {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(RequestAccountCreateHandler.class);
+
+    private final AmieClient amieClient;
+
+    public RequestAccountCreateHandler(AmieClient amieClient) {
+        this.amieClient = amieClient;
+    }
+
+    @Override
+    public String supportsType() {
+        return "request_account_create";
+    }
+
+    @Override
+    public void handle(JsonNode packetJson, PacketEntity packetEntity) throws Exception {
+        LOGGER.info("Starting 'request_account_create' handler for packet amie_id [{}].", packetEntity.getAmieId());
+
+        JsonNode body = packetJson.path("body");
+        String projectId = body.path("ProjectID").asText();
+        String grantNumber = body.path("GrantNumber").asText();
+        String userFirstName = body.path("UserFirstName").asText();
+        String userLastName = body.path("UserLastName").asText();
+        String userEmail = body.path("UserEmail").asText();
+
+        Assert.hasText(projectId, "'ProjectID' (the local project ID) must not be empty.");
+        Assert.hasText(userFirstName, "'UserFirstName' must not be empty.");
+        Assert.hasText(userLastName, "'UserLastName' must not be empty.");
+        LOGGER.info("Packet validated successfully for user [{} {}] on project [{}].", userFirstName, userLastName, projectId);
+
+        // TODO invoke actual cluster's user provisioning service. For the time being generating a local user ID and a username
+        String localUserPersonId = UUID.randomUUID().toString();
+        String localUsername = (userFirstName.charAt(0) + userLastName).toLowerCase();
+
+        LOGGER.info("Created local user account with PersonID [{}] and username [{}]", localUserPersonId, localUsername);
+
+        // Build and send the 'notify_account_create' reply
+        Map<String, Object> replyBody = new HashMap<>();
+        Map<String, Object> bodyContent = new HashMap<>();
+        bodyContent.put("ProjectID", projectId);
+        bodyContent.put("UserPersonID", localUserPersonId);
+
+        // User login name (Unix username) on the actual resource
+        bodyContent.put("UserRemoteSiteLogin", localUsername);
+
+        bodyContent.put("GrantNumber", grantNumber);
+
+        replyBody.put("type", "notify_account_create");
+        replyBody.put("body", bodyContent);
+
+        amieClient.replyToPacket(packetEntity.getAmieId(), replyBody);
+
+        LOGGER.info("Successfully completed 'request_account_create' handler and sent reply for packet amie_id [{}].", packetEntity.getAmieId());
+    }
+}