|
16 | 16 | from .ceph_service import CephService |
17 | 17 |
|
18 | 18 | try: |
19 | | - from typing import List, Optional |
| 19 | + from typing import Dict, List, Optional |
20 | 20 | except ImportError: |
21 | 21 | pass # For typing only |
22 | 22 |
|
@@ -318,11 +318,11 @@ def _rbd_image(cls, ioctx, pool_name, namespace, image_name, # pylint: disable= |
318 | 318 | stat['mirror_mode'] = 'journal' |
319 | 319 | elif mirror_mode == rbd.RBD_MIRROR_IMAGE_MODE_SNAPSHOT: |
320 | 320 | stat['mirror_mode'] = 'snapshot' |
321 | | - schedule_status = json.loads(_rbd_support_remote( |
322 | | - 'mirror_snapshot_schedule_status')[1]) |
323 | | - for scheduled_image in schedule_status['scheduled_images']: |
324 | | - if scheduled_image['image'] == get_image_spec(pool_name, namespace, image_name): |
325 | | - stat['schedule_info'] = scheduled_image |
| 321 | + schedule_info = RbdMirroringService.get_snapshot_schedule_info( |
| 322 | + get_image_spec(pool_name, namespace, image_name) |
| 323 | + ) |
| 324 | + if schedule_info: |
| 325 | + stat['schedule_info'] = schedule_info[0] |
326 | 326 |
|
327 | 327 | stat['name'] = image_name |
328 | 328 |
|
@@ -758,6 +758,74 @@ def snapshot_schedule_add(cls, image_spec: str, interval: str): |
758 | 758 | def snapshot_schedule_remove(cls, image_spec: str): |
759 | 759 | _rbd_support_remote('mirror_snapshot_schedule_remove', image_spec) |
760 | 760 |
|
| 761 | + @classmethod |
| 762 | + def snapshot_schedule_list(cls, image_spec: str = ''): |
| 763 | + return _rbd_support_remote('mirror_snapshot_schedule_list', image_spec) |
| 764 | + |
| 765 | + @classmethod |
| 766 | + def snapshot_schedule_status(cls, image_spec: str = ''): |
| 767 | + return _rbd_support_remote('mirror_snapshot_schedule_status', image_spec) |
| 768 | + |
| 769 | + @classmethod |
| 770 | + def get_snapshot_schedule_info(cls, image_spec: str = ''): |
| 771 | + """ |
| 772 | + Retrieve snapshot schedule information by merging schedule list and status. |
| 773 | +
|
| 774 | + Args: |
| 775 | + image_spec (str, optional): Specification of an RBD image. If empty, |
| 776 | + retrieves all schedule information. |
| 777 | + Format: "<pool_name>/<namespace_name>/<image_name>". |
| 778 | +
|
| 779 | + Returns: |
| 780 | + Optional[List[Dict[str, Any]]]: A list of merged schedule information |
| 781 | + dictionaries if found, otherwise None. |
| 782 | + """ |
| 783 | + schedule_info: List[Dict] = [] |
| 784 | + |
| 785 | + # schedule list and status provide the schedule interval |
| 786 | + # and schedule timestamp respectively. |
| 787 | + schedule_list_raw = cls.snapshot_schedule_list(image_spec) |
| 788 | + schedule_status_raw = cls.snapshot_schedule_status(image_spec) |
| 789 | + |
| 790 | + try: |
| 791 | + schedule_list = json.loads( |
| 792 | + schedule_list_raw[1]) if schedule_list_raw and schedule_list_raw[1] else {} |
| 793 | + schedule_status = json.loads( |
| 794 | + schedule_status_raw[1]) if schedule_status_raw and schedule_status_raw[1] else {} |
| 795 | + except (json.JSONDecodeError, TypeError): |
| 796 | + return None |
| 797 | + |
| 798 | + if not schedule_list or not schedule_status: |
| 799 | + return None |
| 800 | + |
| 801 | + scheduled_images = schedule_status.get("scheduled_images", []) |
| 802 | + |
| 803 | + for _, schedule in schedule_list.items(): |
| 804 | + name = schedule.get("name") |
| 805 | + if not name: |
| 806 | + continue |
| 807 | + |
| 808 | + # find status entry for this schedule |
| 809 | + # by matching with the image name |
| 810 | + image = next(( |
| 811 | + sched_image for sched_image in scheduled_images |
| 812 | + if sched_image.get("image") == name), None) |
| 813 | + if not image: |
| 814 | + continue |
| 815 | + |
| 816 | + # eventually we are merging both the list and status entries |
| 817 | + # all the needed info are fetched above and here we are just mapping |
| 818 | + # it to the dictionary so that in one function we get |
| 819 | + # the schedule related information. |
| 820 | + merged = { |
| 821 | + "name": name, |
| 822 | + "schedule_interval": schedule.get("schedule", []), |
| 823 | + "schedule_time": image.get("schedule_time") |
| 824 | + } |
| 825 | + schedule_info.append(merged) |
| 826 | + |
| 827 | + return schedule_info if schedule_info else None |
| 828 | + |
761 | 829 |
|
762 | 830 | class RbdImageMetadataService(object): |
763 | 831 | def __init__(self, image): |
|
0 commit comments