]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: adapt create_osds interface change 34000/head
authorKiefer Chang <kiefer.chang@suse.com>
Tue, 17 Mar 2020 08:07:45 +0000 (16:07 +0800)
committerKiefer Chang <kiefer.chang@suse.com>
Tue, 17 Mar 2020 08:07:45 +0000 (16:07 +0800)
Support the parameter change of create_osds since
https://github.com/ceph/ceph/pull/33922.

Fixes: https://tracker.ceph.com/issues/44632
Signed-off-by: Kiefer Chang <kiefer.chang@suse.com>
qa/tasks/mgr/dashboard/test_osd.py
src/pybind/mgr/dashboard/controllers/osd.py
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-creation-preview-modal/osd-creation-preview-modal.component.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-form/drive-group.model.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-form/drive-groups.interface.ts [deleted file]
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-form/osd-form.component.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/api/osd.service.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/api/osd.service.ts
src/pybind/mgr/dashboard/services/orchestrator.py
src/pybind/mgr/dashboard/tests/test_osd.py

index 0c17be4f6a104cbf9da19bb6aa126d2e21c368de..1bd75e4b09472547d730064e591bc6ddbfdb0b71 100644 (file)
@@ -111,8 +111,10 @@ class OsdTest(DashboardTestCase):
     def test_create_with_drive_group(self):
         data = {
             'method': 'drive_groups',
-            'data': {
-                'test': {
+            'data': [
+                {
+                    'service_type': 'osd',
+                    'service_id': 'test',
                     'host_pattern': '*',
                     'data_devices': {
                         'vendor': 'abc',
@@ -136,7 +138,7 @@ class OsdTest(DashboardTestCase):
                     'db_slots': 5,
                     'encrypted': True
                 }
-            },
+            ],
             'tracking_id': 'test'
         }
         self._post('/api/osd', data)
index f65af062c51866bd3558915574fc7e6ad69c5dfc..4327f2e92fa9d1352f41809e5e4d4765d64ea081 100644 (file)
@@ -249,11 +249,12 @@ class Osd(RESTController):
 
     @raise_if_no_orchestrator
     @handle_orchestrator_error('osd')
-    def _create_with_drive_groups(self, drive_group):
+    def _create_with_drive_groups(self, drive_groups):
         """Create OSDs with DriveGroups."""
         orch = OrchClient.instance()
         try:
-            orch.osds.create(DriveGroupSpec.from_json(drive_group))
+            dg_specs = [DriveGroupSpec.from_json(dg) for dg in drive_groups]
+            orch.osds.create(dg_specs)
         except (ValueError, TypeError, DriveGroupValidationError) as e:
             raise DashboardException(e, component='osd')
 
@@ -262,7 +263,7 @@ class Osd(RESTController):
     def create(self, method, data, tracking_id):  # pylint: disable=W0622
         if method == 'bare':
             return self._create_bare(data)
-        if method == 'drive_group':
+        if method == 'drive_groups':
             return self._create_with_drive_groups(data)
         raise DashboardException(
             component='osd', http_status_code=400, msg='Unknown method: {}'.format(method))
index ae35da6d6b5406d54010d895ab891fe09b76028a..eb8ded17349bbb97477f7b65c9b26f755b0644ed 100644 (file)
@@ -9,7 +9,6 @@ import { CdFormBuilder } from '../../../../shared/forms/cd-form-builder';
 import { CdFormGroup } from '../../../../shared/forms/cd-form-group';
 import { FinishedTask } from '../../../../shared/models/finished-task';
 import { TaskWrapperService } from '../../../../shared/services/task-wrapper.service';
-import { DriveGroups } from '../osd-form/drive-groups.interface';
 
 @Component({
   selector: 'cd-osd-creation-preview-modal',
@@ -18,7 +17,7 @@ import { DriveGroups } from '../osd-form/drive-groups.interface';
 })
 export class OsdCreationPreviewModalComponent implements OnInit {
   @Input()
-  driveGroups: DriveGroups = {};
+  driveGroups: Object[] = [];
 
   @Output()
   submitAction = new EventEmitter();
@@ -47,7 +46,7 @@ export class OsdCreationPreviewModalComponent implements OnInit {
     this.taskWrapper
       .wrapTaskAroundCall({
         task: new FinishedTask('osd/' + URLVerbs.CREATE, {
-          tracking_id: _.join(_.keys(this.driveGroups), ', ')
+          tracking_id: _.join(_.map(this.driveGroups, 'service_id'), ', ')
         }),
         call: this.osdService.create(this.driveGroups)
       })
index 976a2a59c7fac3e255212c7d6610051ab8fc92d9..dd5d3b0b13ed8239499aee1313c5a7956dffe969 100644 (file)
@@ -1,9 +1,10 @@
+import * as _ from 'lodash';
+
 import { CdTableColumnFiltersChange } from '../../../../shared/models/cd-table-column-filters-change';
 import { FormatterService } from '../../../../shared/services/formatter.service';
 
 export class DriveGroup {
-  // DriveGroupSpec object.
-  spec = {};
+  spec: Object;
 
   // Map from filter column prop to device selection attribute name
   private deviceSelectionAttrs: {
@@ -16,6 +17,7 @@ export class DriveGroup {
   private formatterService: FormatterService;
 
   constructor() {
+    this.reset();
     this.formatterService = new FormatterService();
     this.deviceSelectionAttrs = {
       'sys_api.vendor': {
@@ -45,7 +47,14 @@ export class DriveGroup {
   }
 
   reset() {
-    this.spec = {};
+    this.spec = {
+      service_type: 'osd',
+      service_id: `dashboard-${_.now()}`
+    };
+  }
+
+  setName(name: string) {
+    this.spec['service_id'] = name;
   }
 
   setHostPattern(pattern: string) {
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-form/drive-groups.interface.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-form/drive-groups.interface.ts
deleted file mode 100644 (file)
index bccb7c9..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-export interface DriveGroups {
-  [key: string]: object;
-}
index 5defdbeecc5ba5cddd8cf2d740234eb1e00089da..e6be9f0ea5c9f92aadc365d0bb8c8b286a59ef51 100644 (file)
@@ -19,7 +19,6 @@ import { DevicesSelectionChangeEvent } from '../osd-devices-selection-groups/dev
 import { DevicesSelectionClearEvent } from '../osd-devices-selection-groups/devices-selection-clear-event.interface';
 import { OsdDevicesSelectionGroupsComponent } from '../osd-devices-selection-groups/osd-devices-selection-groups.component';
 import { DriveGroup } from './drive-group.model';
-import { DriveGroups } from './drive-groups.interface';
 import { OsdFeature } from './osd-feature.interface';
 
 @Component({
@@ -209,11 +208,9 @@ export class OsdFormComponent implements OnInit {
   submit() {
     // use user name and timestamp for drive group name
     const user = this.authStorageService.getUsername();
-    const driveGroups: DriveGroups = {
-      [`dashboard-${user}-${_.now()}`]: this.driveGroup.spec
-    };
+    this.driveGroup.setName(`dashboard-${user}-${_.now()}`);
     const modalRef = this.bsModalService.show(OsdCreationPreviewModalComponent, {
-      initialState: { driveGroups: driveGroups }
+      initialState: { driveGroups: [this.driveGroup.spec] }
     });
     modalRef.content.submitAction.subscribe(() => {
       this.router.navigate(['/osd']);
index 3f1abd4ace4f749842995145b2862d139be3cc2e..44db3f5c85a206fbb2372c5a71ad350f4da23660 100644 (file)
@@ -29,20 +29,24 @@ describe('OsdService', () => {
   it('should call create', () => {
     const post_data = {
       method: 'drive_groups',
-      data: {
-        all_hdd: {
+      data: [
+        {
+          service_name: 'osd',
+          service_id: 'all_hdd',
           host_pattern: '*',
           data_devices: {
             rotational: true
           }
         },
-        host1_ssd: {
+        {
+          service_name: 'osd',
+          service_id: 'host1_ssd',
           host_pattern: 'host1',
           data_devices: {
             rotational: false
           }
         }
-      },
+      ],
       tracking_id: 'all_hdd, host1_ssd'
     };
     service.create(post_data.data).subscribe();
index 30cdcd1ea3697e4bbd8015b3b9cdf4f26fcaa56e..8d6369a21623317288a1ca908f2216412292543e 100644 (file)
@@ -5,7 +5,6 @@ import { I18n } from '@ngx-translate/i18n-polyfill';
 import { map } from 'rxjs/operators';
 
 import * as _ from 'lodash';
-import { DriveGroups } from '../../ceph/cluster/osd/osd-form/drive-groups.interface';
 import { CdDevice } from '../models/devices';
 import { SmartDataResponseV1 } from '../models/smart';
 import { DeviceService } from '../services/device.service';
@@ -64,11 +63,11 @@ export class OsdService {
 
   constructor(private http: HttpClient, private i18n: I18n, private deviceService: DeviceService) {}
 
-  create(driveGroups: DriveGroups) {
+  create(driveGroups: Object[]) {
     const request = {
       method: 'drive_groups',
       data: driveGroups,
-      tracking_id: _.join(_.keys(driveGroups), ', ')
+      tracking_id: _.join(_.map(driveGroups, 'service_id'), ', ')
     };
     return this.http.post(this.path, request, { observe: 'response' });
   }
index a1fa708432475127a62ea317038685b736998f6c..400055c8620c15c7ca8453339f296c5e94c6fda8 100644 (file)
@@ -36,11 +36,15 @@ class OrchestratorAPI(OrchestratorClientMixin):
 def wait_api_result(method):
     @wraps(method)
     def inner(self, *args, **kwargs):
-        completion = method(self, *args, **kwargs)
-        self.api.orchestrator_wait([completion])
-        raise_if_exception(completion)
-        return completion.result
-
+        completions = method(self, *args, **kwargs)
+        if not isinstance(completions, list):
+            completions = [completions]
+        self.api.orchestrator_wait(completions)
+        for compl in completions:
+            raise_if_exception(compl)
+        if len(completions) == 1:
+            return completions[0].result
+        return [compl.result for compl in completions]
     return inner
 
 
@@ -105,8 +109,8 @@ class ServiceManager(ResourceManager):
 
 class OsdManager(ResourceManager):
     @wait_api_result
-    def create(self, drive_group):
-        return self.api.create_osds(drive_group)
+    def create(self, drive_group_specs):
+        return self.api.apply_drivegroups(drive_group_specs)
 
     @wait_api_result
     def remove(self, osd_ids):
index 549d8b477e74c9db306aa91ce8600b63ce85935d..aeb32ed576452503c1eb4c5f5743bf4d1684a912 100644 (file)
@@ -273,11 +273,20 @@ class OsdTest(ControllerTestCase):
         instance.return_value = fake_client
 
         # Valid DriveGroup
-        data = {'method': 'drive_group',
-                'data': {'service_type': 'osd', 'service_id': 'all_hdd',
-                         'data_devices': {'rotational': True},
-                         'host_pattern': '*'},
-                'tracking_id': 'all_hdd, b_ssd'}
+        data = {
+            'method': 'drive_groups',
+            'data': [
+                {
+                    'service_type': 'osd',
+                    'service_id': 'all_hdd',
+                    'data_devices': {
+                        'rotational': True
+                    },
+                    'host_pattern': '*',
+                }
+            ],
+            'tracking_id': 'all_hdd, b_ssd'
+        }
 
         # Without orchestrator service
         fake_client.available.return_value = False
@@ -288,11 +297,11 @@ class OsdTest(ControllerTestCase):
         fake_client.available.return_value = True
         self._task_post('/api/osd', data)
         self.assertStatus(201)
-        fake_client.osds.create.assert_called_with(
-            DriveGroupSpec(placement=PlacementSpec(host_pattern='*'),
-                           service_id='all_hdd',
-                           service_type='osd',
-                           data_devices=DeviceSelection(rotational=True)))
+        dg_specs = [DriveGroupSpec(placement=PlacementSpec(host_pattern='*'),
+                                   service_id='all_hdd',
+                                   service_type='osd',
+                                   data_devices=DeviceSelection(rotational=True))]
+        fake_client.osds.create.assert_called_with(dg_specs)
 
     @mock.patch('dashboard.controllers.orchestrator.OrchClient.instance')
     def test_osd_create_with_invalid_drive_groups(self, instance):
@@ -301,10 +310,19 @@ class OsdTest(ControllerTestCase):
         instance.return_value = fake_client
 
         # Invalid DriveGroup
-        data = {'method': 'drive_group',
-                'data': {'service_type': 'osd', 'service_id': 'invalid_dg',
-                         'data_devices': {'rotational': True},
-                         'host_pattern_wrong': 'unknown'},
-                'tracking_id': 'all_hdd, b_ssd'}
+        data = {
+            'method': 'drive_groups',
+            'data': [
+                {
+                    'service_type': 'osd',
+                    'service_id': 'invalid_dg',
+                    'data_devices': {
+                        'rotational': True
+                    },
+                    'host_pattern_wrong': 'unknown',
+                }
+            ],
+            'tracking_id': 'all_hdd, b_ssd'
+        }
         self._task_post('/api/osd', data)
         self.assertStatus(400)