|
1 | 1 | # Copyright (C) 2015-2020 OpenIO SAS, as part of OpenIO SDS |
| 2 | +# Copyright (C) 2021-2022 OVH SAS |
2 | 3 | # |
3 | 4 | # This program is free software: you can redistribute it and/or modify |
4 | 5 | # it under the terms of the GNU Affero General Public License as |
|
27 | 28 | M2_PROP_BUCKET_NAME, M2_PROP_CTIME, M2_PROP_DAMAGED_OBJECTS, \ |
28 | 29 | M2_PROP_DEL_EXC_VERSIONS, M2_PROP_MISSING_CHUNKS, \ |
29 | 30 | M2_PROP_OBJECTS, M2_PROP_QUOTA, M2_PROP_STORAGE_POLICY, \ |
30 | | - M2_PROP_USAGE, M2_PROP_VERSIONING_POLICY |
| 31 | + M2_PROP_USAGE, M2_PROP_VERSIONING_POLICY, CH_ENCODED_SEPARATOR, \ |
| 32 | + S3_MPU_CONTAINER_SUFFIX |
31 | 33 | from oio.common.easy_value import boolean_value, int_value, float_value |
32 | 34 |
|
33 | 35 |
|
@@ -857,26 +859,84 @@ class RefreshBucket(Command): |
857 | 859 | Refresh the counters of a bucket. |
858 | 860 |
|
859 | 861 | Reset all statistics counters and recompute them by summing |
860 | | - the counters of all shards (containers). |
| 862 | + the counters of all shards (containers) known by the account service. |
| 863 | +
|
| 864 | + Optionally trigger events (from meta2 services) to update the statistics |
| 865 | + known by the account service. |
861 | 866 | """ |
862 | 867 |
|
863 | 868 | log = getLogger(__name__ + '.RefreshBucket') |
864 | 869 |
|
865 | 870 | def get_parser(self, prog_name): |
866 | 871 | parser = super(RefreshBucket, self).get_parser(prog_name) |
| 872 | + parser.add_argument( |
| 873 | + '--touch', |
| 874 | + action='store_true', |
| 875 | + help='Ask each container (in meta2) to send a status event. (Slow)' |
| 876 | + ) |
| 877 | + parser.add_argument( |
| 878 | + '--recompute', |
| 879 | + action='store_true', |
| 880 | + help=('Recompute the statistics of the containers (in meta2) ' |
| 881 | + 'before sending the event (requires --touch). (Slower)') |
| 882 | + ) |
867 | 883 | parser.add_argument( |
868 | 884 | 'bucket', |
869 | 885 | help='Name of the bucket to refresh.' |
870 | 886 | ) |
871 | 887 | return parser |
872 | 888 |
|
| 889 | + def _touch_container(self, account, container, recompute=False): |
| 890 | + try: |
| 891 | + self.log.info('Triggering event for %s/%s', |
| 892 | + account, container) |
| 893 | + self.app.client_manager.storage.container_touch( |
| 894 | + account, container, recompute=recompute) |
| 895 | + except Exception as exc: |
| 896 | + self.log.error('Failed to touch %s/%s: %s', |
| 897 | + account, container, exc) |
| 898 | + |
873 | 899 | def take_action(self, parsed_args): |
874 | 900 | self.log.debug('take_action(%s)', parsed_args) |
875 | 901 |
|
876 | 902 | reqid = request_id(prefix='CLI-BUCKET-') |
877 | 903 | acct_client = self.app.client_manager.storage.account |
| 904 | + |
| 905 | + # 1. Reset bucket counters |
878 | 906 | acct_client.bucket_refresh(parsed_args.bucket, reqid=reqid) |
879 | 907 |
|
| 908 | + if parsed_args.touch: |
| 909 | + bucket_meta = acct_client.bucket_show(parsed_args.bucket, |
| 910 | + reqid=reqid) |
| 911 | + op_count = 0 |
| 912 | + for suffix in ('', S3_MPU_CONTAINER_SUFFIX): |
| 913 | + # 2. Recompute (or at least transmit) container counters |
| 914 | + self._touch_container( |
| 915 | + bucket_meta['account'], parsed_args.bucket + suffix, |
| 916 | + recompute=parsed_args.recompute) |
| 917 | + op_count += 1 |
| 918 | + prefix = parsed_args.bucket + suffix + CH_ENCODED_SEPARATOR |
| 919 | + # 3. Recurse on all CH shards |
| 920 | + listing = depaginate( |
| 921 | + self.app.client_manager.storage.container_list, |
| 922 | + item_key=lambda x: x[0], |
| 923 | + marker_key=lambda x: x[-1][0], |
| 924 | + account=bucket_meta['account'], |
| 925 | + prefix=prefix, |
| 926 | + reqid=reqid) |
| 927 | + for container in listing: |
| 928 | + self._touch_container(bucket_meta['account'], container, |
| 929 | + recompute=parsed_args.recompute) |
| 930 | + op_count += 1 |
| 931 | + # Show some progress (the whole operation can be long) |
| 932 | + if (op_count % 100) == 0: |
| 933 | + self.log.warning('%d events triggered so far', |
| 934 | + op_count) |
| 935 | + self.log.warning('%d events triggered', op_count) |
| 936 | + self.log.warning('After events have been consumed, you may ' |
| 937 | + 'need to run "bucket refresh" again (without ' |
| 938 | + '--touch).') |
| 939 | + |
880 | 940 |
|
881 | 941 | class RefreshContainer(ContainerCommandMixin, Command): |
882 | 942 | """ Refresh counters of an account (triggers asynchronous treatments) """ |
|
0 commit comments