[OSSCA] Master 1주차 - Designate 기여하기

OhJiwoo·2024년 8월 27일
post-thumbnail

기여 내용

GET /v2/zones/{zone_id}/nameservers API를 이용하여 Name Server 목록을 불러오는 CLI 명령어 만들기.

1) 네임서버 목록 불러오기

designate client로부터 name server 리스트 불러오기

designate client는 다음과 같이 사용할 수 있다.

client = self.app.client_manager.dns

출력해보면 <designateclient.v2.client.Client object at 0x1038f35b0>라고 나오는데, designate client를 불러온다는 것을 확인할 수 있다.

print(client.nameservers)

designate client 코드를 보면, nameservers.py 파일에 NameServerController라는 클래스가 존재한다. 이것이 nameserver를 불러오는 클래스라는 것을 직관적으로 알 수 있다. 위처럼 client.nameservers를 출력해보면 <designateclient.v2.nameservers.NameServerController object at 0x110180cd0>임을 알 수 있다.

designateclient의 NameServerController의 코드는 다음과 같다.

class NameServerController(V2Controller):
    def list(self, zone):
        zone = v2_utils.resolve_by_name(self.client.zones.list, zone)

        url = f'/zones/{zone}/nameservers'

        return self._get(url, response_key='nameservers')

즉, list라는 메소드를 통해 네임서버 목록을 불러오는 것으로 보인다. 인자 값으로 zone의 id를 함께 보내야 하므로 다음과 같이 코드를 작성할 수 있다.

zones = client.zones.list()

for s in zones:
	for t in client.nameservers.list(s['id']):
		print(t)

zone의 리스트를 불러와서 그 id를 이용해 네임서버 목록을 불러온다. 결과는 다음과 같다.

2) 결과 출력하기

표에 포함될 컬럼 정하기

columns = ['hostname', 'priority', 'zone_id', 'zone_name']
column_headers = ['Name Server', 'Priority', 'Zone Id', 'Zone Name']

name server의 이름과 priority 뿐만 아니라 zone id랑 name까지 같이 출력하기로 했다.

표 모양으로 결과 출력하기

우선 기존에 상속받는 클래스로 command.Command를 설정했는데, 이것을 ListServer와 동일하게 command.Lister로 변경하자 표 모양이 생성되었다. (그런데, 안에 내용이 채워지지는 않았음)

ListServer에서는 어떤 식으로 표에 내용을 채워넣는 지 알아내기 위해 코드를 분석했고, 다음과 같이 테이블 형태로 결과를 리턴함을 확인하였다.

table = (
	column_headers,
    (
		utils.get_item_properties(
        	s,
            columns,
            mixed_case_fields=(
            	'task_state',
                'power_state',
                'availability_zone',
                host',
            ,
            formatters={
            	'power_state': PowerStateColumn,
                'addresses': AddressesColumn,
                'metadata': format_columns.DictColumn,
                'security_groups_name': format_columns.ListColumn,
                'hypervisor_hostname': HostColumn,
            },
		)
        for s in data
	),
)
return table

data는 리스트 형태이고, 이 리스트에서 설정한 columns와 일치하는 것의 값을 가져오는 방식인 것 같다. 그래서 동일하게 data 라는 리스트 내에 딕셔너리 형태로 네임서버를 하나씩 저장하기로 했다. 다음이 네임서버 정보를 data 라는 리스트에 저장하는 코드이다.

data = []
for s in zones:
	m = {}
    for t in client.nameservers.list(s['id']):
    	m['zone_id'] = s['id']
        m['zone_name'] = s['name']
        m['priority'] = t['priority']
        m['hostname'] = t['hostname']

	data.append(m)

각각의 zone에 대해 id를 이용하여 네임서버 목록을 불러오고, 이를 m 딕셔너리에 하나씩 저장한다. 이러한 딕셔너리를 data 리스트에 추가하면, 결과적으로 다음과 같은 형태가 된다.

현재는 zone도 1개고, nameserver도 1개여서 하나만 출력되는 것을 확인할 수 있다.

이제 이를 위에 table 형태로 추출할 수 있게 해줘야 한다. ListServer에서는 data에 저장된 값이 openstack.compute.v2.server.Server 객체 형태이기 때문에 utils.get_item_properties() 함수를 이용했었다. 그런데 지금은 리스트 내에 dictionary 형태이므로 인식을 하지 못하는 문제가 발생했다. (표에 값이 채워지지 않음) 그래서 utils 모듈에 다른 어떤 함수가 있는지 확인해본 결과, get_dict_properties() 함수를 발견했다. 다음은 해당 함수의 설명이다.

Return a tuple containing the item properties.

:param item: a single dict resource
:param fields: tuple of strings with the desired field names
:param mixed_case_fields: tuple of field names to preserve case
:param formatters: dictionary mapping field names to callables
    to format the values

단일 딕셔너리 리소스로부터 tuple을 리턴해주는 함수이다. 딱 내가 원하던 함수! 그래서 바로 적용해보았다.

table = (
	column_headers,
	(
		utils.get_dict_properties(
        	s,
            columns,
        )
        for s in data
    ),
)
return table

이렇게 코드를 작성하니 비로소 테이블에 값이 채워졌다.

결과이다! zone 추가했을 때 네임서버도 추가로 출력되는지 확인해보자.

전체 코드

from osc_lib.command import command
from openstackclient.i18n import _
from osc_lib import utils


class ListNameServer(command.Lister):
    _description = _("List name servers")

    def get_parser(self, prog_name):
        parser = super().get_parser(prog_name)

        return parser

    def take_action(self, parsed_args):
        client = self.app.client_manager.dns
        zones = client.zones.list()

        columns = ['hostname', 'priority', 'zone_id', 'zone_name']
        column_headers = ['Name Server', 'Priority', 'Zone Id', 'Zone Name']

        data = []
        for s in zones:
            m = {}
            for t in client.nameservers.list(s['id']):
                m['zone_id'] = s['id']
                m['zone_name'] = s['name']
                m['priority'] = t['priority']
                m['hostname'] = t['hostname']

            data.append(m)

        table = (
            column_headers,
            (
                utils.get_dict_properties(
                    s,
                    columns,
                )
                for s in data
            ),
        )
        return table
profile
아키텍트를 목표로 공부하는 2년차 시스템 관리자

0개의 댓글