-
[OpenStack] Nova-Compute IncompatibleObjectVersion 해결하기DevOps, 클라우드/Open Sources 2023. 3. 29. 19:38
개요
원래 1개의 데스크탑, 3개의 라즈베리파이에 우분투를 설치하고 개인 서버로 활용하고 있었다.
솔직히 데스크탑은 공부용, 개발서버용 정도로 쓰고 있었는데 라즈베리파이가 놀고 있는게 맘에 좀 걸렸다.
그러면서 또 여러 문제가 생겼는데 개인 서버가 있으니 클라우드를 활용하는 빈도가 현저히 적어졌다는 거다.
솔직히 돈도 돈 때문에 안쓴거긴 하지만...
그러다가 오픈스택을 함 올려볼까 싶었다.
그래서 고민 끝에 윈도우 데스크탑을 밀고 우분투 서버를 설치했다.
결과적으로 컴퓨팅 노드, 컨트롤 노드로 쓰일 데스크탑 서버 2대와 스토리지 노드로 쓰일 라즈베리파이 3대가 생겼다.
이걸 클러스터링해서 어떻게 오픈스택을 잘 올려보려고 했다.
문제 발생
설치 과정이나 개념 정리는 다음에 한번에 적어보기로 하고...
Keystone, Glance, Placement, Nova까지 잘 설치하고 Nova-compute를 준비할 차례가 됐다.
구성요소를 작성하고 설정을 적용하기 위해서
nova-compute
를 재시작하는데...openstack compute service list --service nova-compute
공식문서에 따르면 컨트롤 노드에서 컴퓨팅 노드에 설치한 Nova-compute 서비스를 찾아야 한다고 한다.
근데 컨트롤 노드에서 컴퓨팅 노드의 서비스를 찾지 못하고 있었다.
그래서 컴퓨팅 노드에서
nova-compute
의 서비스 상태를 확인해보니 서비스를 실행하자마자 비활성화 상태로 죽어버리는 상황이었다./var/log/nova/nova-compute.log
공식문서에 따르면 위 경로에 로그를 저장한다고 해서 로그를 열어봤다.
2023-03-29 18:28:57.796 8600 ERROR oslo_service.service Traceback (most recent call last): 2023-03-29 18:28:57.796 8600 ERROR oslo_service.service File "/usr/lib/python3/dist-packages/oslo_service/service.py", line 806, in run_service 2023-03-29 18:28:57.796 8600 ERROR oslo_service.service service.start() 2023-03-29 18:28:57.796 8600 ERROR oslo_service.service File "/usr/lib/python3/dist-packages/nova/service.py", line 162, in start 2023-03-29 18:28:57.796 8600 ERROR oslo_service.service self.manager.init_host(self.service_ref) 2023-03-29 18:28:57.796 8600 ERROR oslo_service.service File "/usr/lib/python3/dist-packages/nova/compute/manager.py", line 1638, in init_host 2023-03-29 18:28:57.796 8600 ERROR oslo_service.service evacuated_instances = self._destroy_evacuated_instances( 2023-03-29 18:28:57.796 8600 ERROR oslo_service.service File "/usr/lib/python3/dist-packages/nova/compute/manager.py", line 805, in _destroy_evacuated_instances 2023-03-29 18:28:57.796 8600 ERROR oslo_service.service evacuations = objects.MigrationList.get_by_filters(context, 2023-03-29 18:28:57.796 8600 ERROR oslo_service.service File "/usr/lib/python3/dist-packages/oslo_versionedobjects/base.py", line 175, in wrapper 2023-03-29 18:28:57.796 8600 ERROR oslo_service.service result = cls.indirection_api.object_class_action_versions( 2023-03-29 18:28:57.796 8600 ERROR oslo_service.service File "/usr/lib/python3/dist-packages/nova/conductor/rpcapi.py", line 240, in object_class_action_versions 2023-03-29 18:28:57.796 8600 ERROR oslo_service.service return cctxt.call(context, 'object_class_action_versions', 2023-03-29 18:28:57.796 8600 ERROR oslo_service.service File "/usr/lib/python3/dist-packages/oslo_messaging/rpc/client.py", line 190, in call 2023-03-29 18:28:57.796 8600 ERROR oslo_service.service result = self.transport._send( 2023-03-29 18:28:57.796 8600 ERROR oslo_service.service File "/usr/lib/python3/dist-packages/oslo_messaging/transport.py", line 123, in _send 2023-03-29 18:28:57.796 8600 ERROR oslo_service.service return self._driver.send(target, ctxt, message, 2023-03-29 18:28:57.796 8600 ERROR oslo_service.service File "/usr/lib/python3/dist-packages/oslo_messaging/_drivers/amqpdriver.py", line 689, in send 2023-03-29 18:28:57.796 8600 ERROR oslo_service.service return self._send(target, ctxt, message, wait_for_reply, timeout, 2023-03-29 18:28:57.796 8600 ERROR oslo_service.service File "/usr/lib/python3/dist-packages/oslo_messaging/_drivers/amqpdriver.py", line 681, in _send 2023-03-29 18:28:57.796 8600 ERROR oslo_service.service raise result 2023-03-29 18:28:57.796 8600 ERROR oslo_service.service oslo_messaging.rpc.client.RemoteError: Remote error: IncompatibleObjectVersion Version 1.5 of MigrationList is not supported, supported version is 1.4 2023-03-29 18:28:57.796 8600 ERROR oslo_service.service ['Traceback (most recent call last):\n', ' File "/usr/lib/python3/dist-packages/oslo_messaging/rpc/server.py", line 165, in _process_incoming\n res = self.dispatcher.dispatch(message)\n', ' File "/usr/lib/python3/dist-packages/oslo_messaging/rpc/dispatcher.py", line 276, in dispatch\n return self._do_dispatch(endpoint, method, ctxt, args)\n', ' File "/usr/lib/python3/dist-packages/oslo_messaging/rpc/dispatcher.py", line 196, in _do_dispatch\n result = func(ctxt, **new_args)\n', ' File "/usr/lib/python3/dist-packages/nova/conductor/manager.py", line 145, in object_class_action_versions\n objclass = nova_object.NovaObject.obj_class_from_name(\n', ' File "/usr/lib/python3/dist-packages/oslo_versionedobjects/base.py", line 383, in obj_class_from_name\n raise exception.IncompatibleObjectVersion(objname=objname,\n', 'oslo_versionedobjects.exception.IncompatibleObjectVersion: Version 1.5 of MigrationList is not supported, supported version is 1.4\n'].
로그를 열어보니 크리티컬한 오류는 아닌거 같았다.
대강 보면
MigrationList
라는 오브젝트의 버전이 현재 1.5가 설치되어 있고 1.4 버전이 지원된다는 것이었다.
해결 과정
첫 시도로
MigrationList
가 파이썬에서 제공하는 패키지인지 살펴봤다.pip list
를 통해서 조회한 파이썬 의존성 패키지에서는MigrationList
를 찾을 수 없었다.그래서 간단하게 코드를 살펴보기로 했다.
# oslo_versionedobjects/base.py # 357라인부터 @classmethod def obj_class_from_name(cls, objname, objver): """Returns a class from the registry based on a name and version.""" if objname not in VersionedObjectRegistry.obj_classes(): LOG.error('Unable to instantiate unregistered object type ' '%(objtype)s'), dict(objtype=objname) raise exception.UnsupportedObjectError(objtype=objname) # NOTE(comstud): If there's not an exact match, return the highest # compatible version. The objects stored in the class are sorted # such that highest version is first, so only set compatible_match # once below. compatible_match = None for objclass in VersionedObjectRegistry.obj_classes()[objname]: if objclass.VERSION == objver: return objclass if (not compatible_match and vutils.is_compatible(objver, objclass.VERSION)): compatible_match = objclass if compatible_match: return compatible_match # As mentioned above, latest version is always first in the list. latest_ver = VersionedObjectRegistry.obj_classes()[objname][0].VERSION raise exception.IncompatibleObjectVersion(objname=objname, ## <- 요기 objver=objver, supported=latest_ver)
# oslo_versionedobjects/exception.py class IncompatibleObjectVersion(VersionedObjectsException): msg_fmt = _('Version %(objver)s of %(objname)s is not supported, ' 'supported version is %(supported)s')
에러가 발생한 메서드 내부에서
objclass
의VERSION
프로퍼티나compatible_match
의 조건을 통과하지 못하면IncompatibleObjectVersion
예외처리를 발생시킨다.그런데 위의 코드에서 보면 오브젝트 클래스의 버전을
VersionedObjectRegistry
에서 끌고온다.물론 이 클래스를 직접 살펴봐도 큰 정보는 얻을 수 없었다.
어쨌건
oslo
라는 레지스트리에서 관리하는MigrationList
라는 객체가 버전 불일치로 오류가 발생했다는 것까지는 알았다.여기서부터 열심히 구글링을 하고 있었는데...
우연히 Nova의 객체 클래스의 코드를 보게 되었다.
... @base.NovaObjectRegistry.register class ImageMeta(base.NovaObject): # Version 1.0: Initial version # Version 1.1: updated ImageMetaProps # Version 1.2: ImageMetaProps version 1.2 # Version 1.3: ImageMetaProps version 1.3 # Version 1.4: ImageMetaProps version 1.4 # Version 1.5: ImageMetaProps version 1.5 # Version 1.6: ImageMetaProps version 1.6 # Version 1.7: ImageMetaProps version 1.7 # Version 1.8: ImageMetaProps version 1.8 VERSION = '1.8' ...
VersionedObjectRegistry
와 유사한 객체 레지스트리에서 객체 클래스의 버전을 위와 같이 관리하고 있었다.여기서 힌트를 얻었다.
분명
MigrationList
라는 객체 클래스가 의존성 패키지들 어딘가에 파이썬 코드로 존재할 것이고 그 코드에서 버전을 수정할 수 있다는 생각을 했다.그런데 나는
olso
하위의 패키지에서 이 클래스를 찾고 있었다. 하지만 위 코드는 nova 패키지 하위에 존재한다.nova 패키지 하위에는 objects를 모아놓은 디렉터리가 있었고 그 경로 아래에서 migrate, migration의 키워드를 가진 코드를 찾았다.
@base.NovaObjectRegistry.register class MigrationList(base.ObjectListBase, base.NovaObject): # Version 1.0: Initial version # Migration <= 1.1 # Version 1.1: Added use_slave to get_unconfirmed_by_dest_compute # Version 1.2: Migration version 1.2 # Version 1.3: Added a new function to get in progress migrations # for an instance. # Version 1.4: Added sort_keys, sort_dirs, limit, marker kwargs to # get_by_filters for migrations pagination support. # Version 1.5: Added a new function to get in progress migrations # and error migrations for a given host + node. VERSION = '1.5' ## <--- 요기 fields = { 'objects': fields.ListOfObjectsField('Migration'), } ...
그리고
migration.py
내부에서MigrationList
클래스를 찾았다!클래스 내부엔 버전이 1.5로 명시되어있었다.
해당 값을 1.4로 변경하고나서...
결과
컨트롤 노드에서 컴퓨팅 노드를 찾을 수 있게 됐다!
결론
사실 근본적으로 적합한 버전을 설치했다면 이런 일이 없었을 것이다.
버전도 강제로 변경했기에 다른 오류가 생길 수도 있지 않을까 싶었다.
하지만 구글링에서도 명확한 해답을 찾지 못했다는데 코드 하나하나 찾아가보면서 직접 오류를 고쳐보니 좀 성취감이 있긴 하다.