]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/pybind/mgr/dashboard/controllers/rgw.py
update ceph source to reef 18.2.1
[ceph.git] / ceph / src / pybind / mgr / dashboard / controllers / rgw.py
index b29e424206e3ccb6f3dca4bff9b5c90b82a23322..9ccf4b36b2b119785efdd3258c45988fb6ced7a9 100644 (file)
@@ -2,20 +2,22 @@
 
 import json
 import logging
+import re
 from typing import Any, Dict, List, NamedTuple, Optional, Union
 
 import cherrypy
 
+from .. import mgr
 from ..exceptions import DashboardException
 from ..rest_client import RequestException
 from ..security import Permission, Scope
 from ..services.auth import AuthManager, JwtManager
 from ..services.ceph_service import CephService
-from ..services.rgw_client import NoRgwDaemonsException, RgwClient
+from ..services.rgw_client import NoRgwDaemonsException, RgwClient, RgwMultisite
 from ..tools import json_str_to_object, str_to_bool
-from . import APIDoc, APIRouter, BaseController, CRUDCollectionMethod, \
-    CRUDEndpoint, Endpoint, EndpointDoc, ReadPermission, RESTController, \
-    UIRouter, allow_empty_body
+from . import APIDoc, APIRouter, BaseController, CreatePermission, \
+    CRUDCollectionMethod, CRUDEndpoint, Endpoint, EndpointDoc, ReadPermission, \
+    RESTController, UIRouter, UpdatePermission, allow_empty_body
 from ._crud import CRUDMeta, Form, FormField, FormTaskInfo, Icon, MethodType, \
     TableAction, Validator, VerticalContainer
 from ._version import APIVersion
@@ -79,6 +81,43 @@ class Rgw(BaseController):
         return status
 
 
+@UIRouter('/rgw/multisite')
+class RgwMultisiteStatus(RESTController):
+    @Endpoint()
+    @ReadPermission
+    # pylint: disable=R0801
+    def status(self):
+        status = {'available': True, 'message': None}
+        multisite_instance = RgwMultisite()
+        is_multisite_configured = multisite_instance.get_multisite_status()
+        if not is_multisite_configured:
+            status['available'] = False
+            status['message'] = 'Multi-site provides disaster recovery and may also \
+                serve as a foundation for content delivery networks'  # type: ignore
+        return status
+
+    @RESTController.Collection(method='PUT', path='/migrate')
+    @allow_empty_body
+    # pylint: disable=W0102,W0613
+    def migrate(self, daemon_name=None, realm_name=None, zonegroup_name=None, zone_name=None,
+                zonegroup_endpoints=None, zone_endpoints=None, access_key=None,
+                secret_key=None):
+        multisite_instance = RgwMultisite()
+        result = multisite_instance.migrate_to_multisite(realm_name, zonegroup_name,
+                                                         zone_name, zonegroup_endpoints,
+                                                         zone_endpoints, access_key,
+                                                         secret_key)
+        return result
+
+    @RESTController.Collection(method='GET', path='/sync_status')
+    @allow_empty_body
+    # pylint: disable=W0102,W0613
+    def get_sync_status(self):
+        multisite_instance = RgwMultisite()
+        result = multisite_instance.get_multisite_sync_status()
+        return result
+
+
 @APIRouter('/rgw/daemon', Scope.RGW)
 @APIDoc("RGW Daemon Management API", "RgwDaemon")
 class RgwDaemon(RESTController):
@@ -105,7 +144,7 @@ class RgwDaemon(RESTController):
                     'zonegroup_name': metadata['zonegroup_name'],
                     'zone_name': metadata['zone_name'],
                     'default': instance.daemon.name == metadata['id'],
-                    'port': int(metadata['frontend_config#0'].split('port=')[1])
+                    'port': int(re.findall(r'port=(\d+)', metadata['frontend_config#0'])[0])
                 }
 
                 daemons.append(daemon)
@@ -138,6 +177,12 @@ class RgwDaemon(RESTController):
         daemon['rgw_status'] = status
         return daemon
 
+    @RESTController.Collection(method='PUT', path='/set_multisite_config')
+    @allow_empty_body
+    def set_multisite_config(self, realm_name=None, zonegroup_name=None,
+                             zone_name=None, daemon_name=None):
+        CephService.set_multisite_config(realm_name, zonegroup_name, zone_name, daemon_name)
+
 
 class RgwRESTController(RESTController):
     def proxy(self, daemon_name, method, path, params=None, json_response=True):
@@ -395,6 +440,38 @@ class RgwBucket(RgwRESTController):
         return CephService.get_encryption_config(daemon_name)
 
 
+@UIRouter('/rgw/bucket', Scope.RGW)
+class RgwBucketUi(RgwBucket):
+    @Endpoint('GET')
+    @ReadPermission
+    # pylint: disable=W0613
+    def buckets_and_users_count(self, daemon_name=None):
+        buckets_count = 0
+        users_count = 0
+        daemon_object = RgwDaemon()
+        daemons = json.loads(daemon_object.list())
+        unique_realms = set()
+        for daemon in daemons:
+            realm_name = daemon.get('realm_name', None)
+            if realm_name:
+                if realm_name not in unique_realms:
+                    unique_realms.add(realm_name)
+                    buckets = json.loads(RgwBucket.list(self, daemon_name=daemon['id']))
+                    users = json.loads(RgwUser.list(self, daemon_name=daemon['id']))
+                    users_count += len(users)
+                    buckets_count += len(buckets)
+            else:
+                buckets = json.loads(RgwBucket.list(self, daemon_name=daemon['id']))
+                users = json.loads(RgwUser.list(self, daemon_name=daemon['id']))
+                users_count = len(users)
+                buckets_count = len(buckets)
+
+        return {
+            'buckets_count': buckets_count,
+            'users_count': users_count
+        }
+
+
 @APIRouter('/rgw/user', Scope.RGW)
 @APIDoc("RGW User Management API", "RgwUser")
 class RgwUser(RgwRESTController):
@@ -683,3 +760,211 @@ class RgwUserRole(NamedTuple):
     CreateDate: str
     MaxSessionDuration: int
     AssumeRolePolicyDocument: str
+
+
+@APIRouter('/rgw/realm', Scope.RGW)
+class RgwRealm(RESTController):
+    @allow_empty_body
+    # pylint: disable=W0613
+    def create(self, realm_name, default):
+        multisite_instance = RgwMultisite()
+        result = multisite_instance.create_realm(realm_name, default)
+        return result
+
+    @allow_empty_body
+    # pylint: disable=W0613
+    def list(self):
+        multisite_instance = RgwMultisite()
+        result = multisite_instance.list_realms()
+        return result
+
+    @allow_empty_body
+    # pylint: disable=W0613
+    def get(self, realm_name):
+        multisite_instance = RgwMultisite()
+        result = multisite_instance.get_realm(realm_name)
+        return result
+
+    @Endpoint()
+    @ReadPermission
+    def get_all_realms_info(self):
+        multisite_instance = RgwMultisite()
+        result = multisite_instance.get_all_realms_info()
+        return result
+
+    @allow_empty_body
+    # pylint: disable=W0613
+    def set(self, realm_name: str, new_realm_name: str, default: str = ''):
+        multisite_instance = RgwMultisite()
+        result = multisite_instance.edit_realm(realm_name, new_realm_name, default)
+        return result
+
+    @Endpoint()
+    @ReadPermission
+    def get_realm_tokens(self):
+        try:
+            result = CephService.get_realm_tokens()
+            return result
+        except NoRgwDaemonsException as e:
+            raise DashboardException(e, http_status_code=404, component='rgw')
+
+    @Endpoint(method='POST')
+    @UpdatePermission
+    @allow_empty_body
+    # pylint: disable=W0613
+    def import_realm_token(self, realm_token, zone_name, port, placement_spec):
+        try:
+            multisite_instance = RgwMultisite()
+            result = CephService.import_realm_token(realm_token, zone_name, port, placement_spec)
+            multisite_instance.update_period()
+            return result
+        except NoRgwDaemonsException as e:
+            raise DashboardException(e, http_status_code=404, component='rgw')
+
+    def delete(self, realm_name):
+        multisite_instance = RgwMultisite()
+        result = multisite_instance.delete_realm(realm_name)
+        return result
+
+
+@APIRouter('/rgw/zonegroup', Scope.RGW)
+class RgwZonegroup(RESTController):
+    @allow_empty_body
+    # pylint: disable=W0613
+    def create(self, realm_name, zonegroup_name, default=None, master=None,
+               zonegroup_endpoints=None):
+        multisite_instance = RgwMultisite()
+        result = multisite_instance.create_zonegroup(realm_name, zonegroup_name, default,
+                                                     master, zonegroup_endpoints)
+        return result
+
+    @allow_empty_body
+    # pylint: disable=W0613
+    def list(self):
+        multisite_instance = RgwMultisite()
+        result = multisite_instance.list_zonegroups()
+        return result
+
+    @allow_empty_body
+    # pylint: disable=W0613
+    def get(self, zonegroup_name):
+        multisite_instance = RgwMultisite()
+        result = multisite_instance.get_zonegroup(zonegroup_name)
+        return result
+
+    @Endpoint()
+    @ReadPermission
+    def get_all_zonegroups_info(self):
+        multisite_instance = RgwMultisite()
+        result = multisite_instance.get_all_zonegroups_info()
+        return result
+
+    def delete(self, zonegroup_name, delete_pools, pools: Optional[List[str]] = None):
+        if pools is None:
+            pools = []
+        try:
+            multisite_instance = RgwMultisite()
+            result = multisite_instance.delete_zonegroup(zonegroup_name, delete_pools, pools)
+            return result
+        except NoRgwDaemonsException as e:
+            raise DashboardException(e, http_status_code=404, component='rgw')
+
+    @allow_empty_body
+    # pylint: disable=W0613,W0102
+    def set(self, zonegroup_name: str, realm_name: str, new_zonegroup_name: str,
+            default: str = '', master: str = '', zonegroup_endpoints: str = '',
+            add_zones: List[str] = [], remove_zones: List[str] = [],
+            placement_targets: List[Dict[str, str]] = []):
+        multisite_instance = RgwMultisite()
+        result = multisite_instance.edit_zonegroup(realm_name, zonegroup_name, new_zonegroup_name,
+                                                   default, master, zonegroup_endpoints, add_zones,
+                                                   remove_zones, placement_targets)
+        return result
+
+
+@APIRouter('/rgw/zone', Scope.RGW)
+class RgwZone(RESTController):
+    @allow_empty_body
+    # pylint: disable=W0613
+    def create(self, zone_name, zonegroup_name=None, default=False, master=False,
+               zone_endpoints=None, access_key=None, secret_key=None):
+        multisite_instance = RgwMultisite()
+        result = multisite_instance.create_zone(zone_name, zonegroup_name, default,
+                                                master, zone_endpoints, access_key,
+                                                secret_key)
+        return result
+
+    @allow_empty_body
+    # pylint: disable=W0613
+    def list(self):
+        multisite_instance = RgwMultisite()
+        result = multisite_instance.list_zones()
+        return result
+
+    @allow_empty_body
+    # pylint: disable=W0613
+    def get(self, zone_name):
+        multisite_instance = RgwMultisite()
+        result = multisite_instance.get_zone(zone_name)
+        return result
+
+    @Endpoint()
+    @ReadPermission
+    def get_all_zones_info(self):
+        multisite_instance = RgwMultisite()
+        result = multisite_instance.get_all_zones_info()
+        return result
+
+    def delete(self, zone_name, delete_pools, pools: Optional[List[str]] = None,
+               zonegroup_name=None):
+        if pools is None:
+            pools = []
+        if zonegroup_name is None:
+            zonegroup_name = ''
+        try:
+            multisite_instance = RgwMultisite()
+            result = multisite_instance.delete_zone(zone_name, delete_pools, pools, zonegroup_name)
+            return result
+        except NoRgwDaemonsException as e:
+            raise DashboardException(e, http_status_code=404, component='rgw')
+
+    @allow_empty_body
+    # pylint: disable=W0613,W0102
+    def set(self, zone_name: str, new_zone_name: str, zonegroup_name: str, default: str = '',
+            master: str = '', zone_endpoints: str = '', access_key: str = '', secret_key: str = '',
+            placement_target: str = '', data_pool: str = '', index_pool: str = '',
+            data_extra_pool: str = '', storage_class: str = '', data_pool_class: str = '',
+            compression: str = ''):
+        multisite_instance = RgwMultisite()
+        result = multisite_instance.edit_zone(zone_name, new_zone_name, zonegroup_name, default,
+                                              master, zone_endpoints, access_key, secret_key,
+                                              placement_target, data_pool, index_pool,
+                                              data_extra_pool, storage_class, data_pool_class,
+                                              compression)
+        return result
+
+    @Endpoint()
+    @ReadPermission
+    def get_pool_names(self):
+        pool_names = []
+        ret, out, _ = mgr.check_mon_command({
+            'prefix': 'osd lspools',
+            'format': 'json',
+        })
+        if ret == 0 and out is not None:
+            pool_names = json.loads(out)
+        return pool_names
+
+    @Endpoint('PUT')
+    @CreatePermission
+    def create_system_user(self, userName: str, zoneName: str):
+        multisite_instance = RgwMultisite()
+        result = multisite_instance.create_system_user(userName, zoneName)
+        return result
+
+    @Endpoint()
+    @ReadPermission
+    def get_user_list(self, zoneName=None):
+        multisite_instance = RgwMultisite()
+        result = multisite_instance.get_user_list(zoneName)
+        return result