volume_message
-
openstack volume message명령어에 나타나는 메시지들은 블록 스토리지 서비스인cinder에서 볼륨과 관련된 작업(생성, 삭제, 확장, 연결 등)을 수행하다가 실패했을 때 기록되는 오류 로그들입니다. -
사용자가 API를 통해 내부 작업을 진행하다가,
cinder내부에서 오류가 발생한 경우 이를 알 수 있도록 사용자에게 메시지를 남기는 기능이라고 볼 수 있습니다. -
보통
가용 공간 부족, 적합한 스토리지 호스트 없음, 이미지로부터 볼륨 생성 실패, 볼륨 삭제 실패(사용중), 볼륨 확장 실패(사용중), 볼륨 연결 및 해제 실패등의 시나리오에서 에러 메시지가 발생합니다. -
따라서
volume_message에 대해 삭제, 목록 확인, 상세 정보 확인 기능을 제공하는 코드입니다.
volume_message docs 분석
https://docs.openstack.org/python-openstackclient/latest/cli/command-objects/volume-message.html
volume message delete
openstack volume message delete <message-id> [<message-id> ...]
- volume 실패 메시지의 id를 인자로 입력하여, 해당 메시지를 삭제합니다.
volume message list
openstack volume message list
[--sort-column SORT_COLUMN]
[--sort-ascending | --sort-descending]
[--project <project>]
[--project-domain <project-domain>]
[--limit <limit>]
[--marker <marker>]
-
volume 실패 메시지 리스트를 확인합니다.
-
--sort-column SORT_COLUMN데이터를 정렬할 특정 컬럼값을 지정합니다. 먼저 지정된 컬럼이 우선순위를 가지며, 존재하지 않는 컬럼은 무시됩니다. (반복 가능) -
--sort-ascending컬럼들을 오름차순으로 정렬합니다. -
--sort-descending컬럼들을 내림차순으로 정렬합니다. -
--project <project>결과값을 프로젝트 기준(이름, ID값)으로 필터링합니다. (관리자 기능) -
--project-domain <project-domain>프로젝트 도메인 기준(이름, ID값)으로 결과를 필터링합니다. 프로젝트 이름이 충돌하는 경우 사용이 가능합니다. -
--limit <limit>반환할 엔트리의 개수를 제한합니다. 서버 지정 최댓값을 초과하는 경우, 최댓값이 사용됩니다. -
--marker <marker>결과를 반환할 컬렉션의 첫 번째 위치를 지정합니다. 이전 요청에서 반환된 값이어야 합니다.
-
volume message show
openstack volume message show <message-id>
- volume 실패 메시지의 id를 인자로 입력하여, 해당 메시지를 확인합니다.
volume_message 코드 분석
-
volume message delete (
DeleteMessage(…))def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'message_ids', metavar='<message-id>', nargs='+', help=_('Message(s) to delete (ID)'), ) return parserget_parser부분에서는 삭제하려는message_id를 인자로 받습니다.
def take_action(self, parsed_args): volume_client = self.app.client_manager.volume if volume_client.api_version < api_versions.APIVersion('3.3'): msg = _( "--os-volume-api-version 3.3 or greater is required to " "support the 'volume message delete' command" ) raise exceptions.CommandError(msg) # ...-
take_action부분에서는 제일 먼저 volume 관련 기능을 사용하기 위해volume_client를 받아옵니다. -
현재 사용하고 있는
volume_client의 api 버전이 3.3 미만이라면, 명령어를 지원하지 않습니다.-
openstack --os-volume-api-version 3.3 volume message ...- 실행할 때 명시적으로 api 버전을 3.3으로 지정하면 임시 해결이 가능합니다.
-
def take_action(self, parsed_args): # ... errors = 0 for message_id in parsed_args.message_ids: try: volume_client.messages.delete(message_id) except Exception: LOG.error(_('Failed to delete message: %s'), message_id) errors += 1 # ...-
이후
errors = 0으로 지정해두고, 입력한 전체message_id값들에 대해 반복하여 실제 메시지 삭제를 진행합니다. -
만약 도중에 메시지 삭제를 실패한 경우,
errors값을 증가시켜 에러 수를 기록합니다.
def take_action(self, parsed_args): # ... if errors > 0: total = len(parsed_args.message_ids) msg = _('Failed to delete %(errors)s of %(total)s messages.') % { 'errors': errors, 'total': total, } raise exceptions.CommandError(msg)- 이후 메시지 삭제를 완료하면, 에러 발생 횟수를 체크하여 입력한 전체
message_id중 몇 개나 에러가 발생했는지 보여줍니다.
-
volume message list (
ListMessages(…))def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( '--project', metavar='<project>', help=_('Filter results by project (name or ID) (admin only)'), ) identity_common.add_project_domain_option_to_parser(parser) pagination.add_marker_pagination_option_to_parser(parser) return parser-
get_parser에서는 프로젝트 이름, ID를 통해 데이터를 필터링하는--project에 대한 부분만 해당 함수에 작성되어 있습니다. -
나머지 옵션들은
identity_common.add_project_domain_option_to_parser(parser)pagination.add_marker_pagination_option_to_parser(parser)이 두 부분에 구현된 것을 가져와서 현재parser에 적용시킵니다.
def take_action(self, parsed_args): volume_client = self.app.client_manager.volume identity_client = self.app.client_manager.identity if volume_client.api_version < api_versions.APIVersion('3.3'): msg = _( "--os-volume-api-version 3.3 or greater is required to " "support the 'volume message list' command" ) raise exceptions.CommandError(msg) column_headers = ( 'ID', 'Event ID', 'Resource Type', 'Resource UUID', 'Message Level', 'User Message', 'Request ID', 'Created At', 'Guaranteed Until', ) # ...-
volume_client와identity_client를 동시에 가져옵니다. -
API 버전 3.3 검사는 동일하게 진행합니다.
-
이 함수 내부에서
column_headers목록을 직접 작성해둔 것을 확인할 수 있습니다.
def take_action(self, parsed_args): # ... project_id = None if parsed_args.project: project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id search_opts = { 'project_id': project_id, } data = volume_client.messages.list( search_opts=search_opts, marker=parsed_args.marker, limit=parsed_args.limit, ) return ( column_headers, (utils.get_item_properties(s, column_headers) for s in data), )-
이후 만약
--project옵션을 사용했다면, 그 부분을 반영하기 위한 코드가 구현되어 있습니다.- 이 때, 해당 옵션이 관리자 전용이라
identity_client를 통해 권한을 검사하는 것도 확인할 수 있습니다.
- 이 때, 해당 옵션이 관리자 전용이라
-
data에 커맨드라인에서 입력했던 옵션들을 통해 필터링한 메시지 목록만 가져와 할당합니다. -
마지막
return구문에서는 표 형태로 결과를 반환합니다.- 앞에서 정의했던
column_headers값들과, 그에 대응되는 실제 데이터를data에서 뽑아 함께 반환합니다.
- 앞에서 정의했던
-
-
volume message show (
ShowMessage(…))def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( 'message_id', metavar='<message-id>', help=_('Message to show (ID).'), ) return parserget_parser부분에서는 확인하려는message_id를 인자로 받습니다.
def take_action(self, parsed_args): volume_client = self.app.client_manager.volume if volume_client.api_version < api_versions.APIVersion('3.3'): msg = _( "--os-volume-api-version 3.3 or greater is required to " "support the 'volume message show' command" ) raise exceptions.CommandError(msg) message = volume_client.messages.get(parsed_args.message_id) return zip(*sorted(message._info.items()))-
volume_client를 받아오고, api 3.3 이상 버전을 검사하는 부분은 동일합니다. -
인자로 입력했던
message_id를 통해 실제 메시지 데이터를message에 받아옵니다. -
메시지 정보 값(
key-value형태)들을key값 기준으로 정렬한 후,zip명령어로key값끼리,value값끼리 각각 묶어서 튜플을 만들고 반환합니다.
volume_message 기능 분석
-
기능 실제 테스트를 위해
cinder사용이 필요합니다. -
우선 NHN 클라우드에서 전용 인스턴스를 생성하여
devstack을 구성합니다. -
volume 에러 메시지를 생성하려고 사용중인 볼륨의 삭제를 시도했습니다.
-
이렇게 에러가 발생한 것을 확인할 수 있지만,
-
openstack --os-volume-api-version 3.3 volume message list해당 명령어로 확인할 수 없어서 다음 과제 진행시 함께 추가로 작성하도록 하겠습니다.
-