Retrieve project information associated with an instance in OpenStack

이태곤·2023년 10월 18일
0

Cloud

목록 보기
6/8
post-thumbnail

1. 프로젝트 생성

  • 인증 → 프로젝트 → 프로젝트 생성

2. admin 사용자에 프로젝트 등록

  • 추가할 프로젝트 클릭 → 멤버 관리 → admin 추가


3. Prometheus에 Libvirt exporter가 수집하고 있는 IP:PORT 추가


4. 수집되고 있는 정보 확인


→ Instance의 Project Id를 통해서 Instance가 현재 속해있는 Project의 정보를 받아오도록 구현할 예정이다.


5. 프로젝트 정보 가져오기

  1. Java + Spring boot를 사용하여 Libvirt exporter가 수집하고 있는 Instance name, project Id를 받아오고 pasing하는 코드 작성
    • Java version: 11
    • Spring Framework version: 2.7.16
package openstack.prometheus.libvirt;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.net.URISyntaxException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@RestController
@Slf4j
public class PrometheusDataFetcher {

    private final RestTemplate restTemplate;

    @Autowired
    public PrometheusDataFetcher(RestTemplateBuilder restTemplateBuilder) {
        this.restTemplate = restTemplateBuilder.build();
    }

    @GetMapping("/prometheus-metrics")
    public ResponseEntity<String> getPrometheusMetrics() throws URISyntaxException {

        // Prometheus 메트릭 데이터를 가져올 URL 설정
        String prometheusMetricsURL = "http://133.186.215.103:9000/metrics";

        // RestTemplate을 사용하여 메트릭 데이터를 문자열로 가져오기
        ResponseEntity<String> response = restTemplate.getForEntity(prometheusMetricsURL, String.class);
        String metricData = response.getBody();

        // 정규 표현식 패턴
        Pattern pattern = Pattern.compile("instanceName=\"([^\"]+)\".*projectId=\"([^\"]+)\"");
        Matcher matcher = pattern.matcher(metricData);

        StringBuilder result = new StringBuilder();
        while (matcher.find()) {
            String instanceName = matcher.group(1);
            String projectId = matcher.group(2);

            result.append("Instance Name: ").append(instanceName).append("\n");
            result.append("Project Id: ").append(projectId).append("\n");
        }

        return ResponseEntity.ok(result.toString());
    }
}
  1. 하이퍼바이저 위에 생성된 인스턴스 들의 이름과 Project Id가 정상적으로 요청 & 응답 된다.
    해당 정보로부터 Openstack API를 활용하여 프로젝트 정보를 가져와보겠다.
package openstack.prometheus.libvirt;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;

@Component
@Slf4j
public class Token {

    private final RestTemplate restTemplate;

    // RestTemplate을 초기화하기 위한 생성자
    @Autowired
    public Token(RestTemplateBuilder restTemplateBuilder) {
        this.restTemplate = restTemplateBuilder.build();

        // OpenStack Identity 기본 설정 값을 초기화
        this.username = "admin";
        this.password = "20secret23";
        this.authUrl = "http://133.186.215.103/identity/v3/auth/tokens";
    }

    private String authUrl;
    
    private String username;
    
    private String password;

    public String fetchToken() throws URISyntaxException {

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        // 인증을 위한 JSON 요청 생성
        String jsonRequest = "{\"auth\": {\"identity\": {\"methods\": [\"password\"],\"password\": {\"user\": {\"name\": \"" + username + "\",\"domain\": {\"id\": \"default\"},\"password\": \"" + password + "\"}},\"scope\": {\"domain\": {\"id\": \"default\"}}}}}";

        // JSON 요청, 헤더, HTTP 메서드로 RequestEntity 생성
        RequestEntity<String> requestEntity = new RequestEntity<>(jsonRequest, headers, HttpMethod.POST, new URI(authUrl));

        // 인증 요청을 보내고 응답을 받음
        ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class);

        // 응답에서 헤더 정보를 추출
        HttpHeaders responseHeaders = responseEntity.getHeaders();
        log.info(responseHeaders.toString());

        // 응답 헤더에서 X-Subject-Token (인증 토큰) 추출
        List<String> tokenList = responseHeaders.get("X-Subject-Token");

        // 성공 로그를 기록하고 인증 토큰 반환
        log.info("인증 성공");
        return tokenList.get(0);
    }
}
  1. Controller 부분에 Token을 생성할 수 있는 로직을 추가하였다.

    • Issue: 토큰 값이 정상적으로 파싱되어 확인할 수 있었지만, http://localhost:8080/prometheus-metrics 로 요청을 보내면 401 Unauthorized에 의해서 사이트 접속이 차단 되었다.
    • 하지만 받아온 토큰 값을 이용해서 Openstack 커널에서 Openstack API를 통해 요청을 하면 아래와 같이 정상적으로 값이 받아와졌다.
    • 문제점은 http://localhost:8080/prometheus-metrics 요청할 때, 헤더에 토큰 값을 넣어주지 않았다.
      인증 & 인가를 위해서 필수적으로 헤더에 해당 정보를 포함해줘야하는 것을 알고있었는데 security, jwt를 사용안한지 오래되어 까맣게 잊고 있었다.
      CS공부를 더 열심히 해야겠다.
      아래는 수정된 코드이다.
      → GET 요청을 보낼 때 헤더에 받아온 Token을 set
      헤더를 수정하기 위해 getForEntity가 아닌, restTemplate의 exchange 메소드를 사용하였다.
    • 결과

0개의 댓글