]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: support snmp-gateway service creation from UI
authorAvan Thakkar <athakkar@redhat.com>
Thu, 27 Jan 2022 14:13:22 +0000 (19:43 +0530)
committerErnesto Puerta <epuertat@redhat.com>
Thu, 10 Feb 2022 11:55:35 +0000 (12:55 +0100)
Fixes: https://tracker.ceph.com/issues/54034
Signed-off-by: Avan Thakkar <athakkar@redhat.com>
(cherry picked from commit ad6fcfc05625b3fd8a088b8a2b5c3d5fbbf2c53a)

src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.ts

index 5582d300ddac868077730438d00ad9739e139c58..34b272baea0793cf0b875e8d4fdfdf3e40d1e83c 100644 (file)
             </div>
           </div>
         </ng-container>
+
+        <!-- SNMP-Gateway -->
+        <ng-container *ngIf="!serviceForm.controls.unmanaged.value && serviceForm.controls.service_type.value === 'snmp-gateway'">
+          <!-- snmp-version -->
+          <div class="form-group row">
+            <label class="cd-col-form-label required"
+                   for="snmp_version"
+                   i18n>Version</label>
+            <div class="cd-col-form-input">
+              <select id="snmp_version"
+                      name="snmp_version"
+                      class="form-control custom-select"
+                      formControlName="snmp_version"
+                      (change)="clearValidations()">
+                <option i18n
+                        [ngValue]="null">-- Select SNMP version --</option>
+                <option *ngFor="let snmpVersion of ['V2c', 'V3']"
+                        [value]="snmpVersion">{{ snmpVersion }}</option>
+              </select>
+              <span class="invalid-feedback"
+                    *ngIf="serviceForm.showError('snmp_version', frm, 'required')"
+                    i18n>This field is required.</span>
+            </div>
+          </div>
+          <!-- Destination -->
+          <div class="form-group row">
+            <label class="cd-col-form-label required"
+                   [ngClass]="{'required': ['snmp-gateway'].includes(serviceForm.controls.service_type.value)}"
+                   for="snmp_destination">
+              <span i18n>Destination</span>
+              <cd-helper>
+                <span i18n>Must be of the format hostname:port.</span>
+              </cd-helper>
+            </label>
+            <div class="cd-col-form-input">
+              <input id="snmp_destination"
+                     class="form-control"
+                     type="text"
+                     formControlName="snmp_destination">
+              <span class="invalid-feedback"
+                    *ngIf="serviceForm.showError('snmp_destination', frm, 'required')"
+                    i18n>This field is required.</span>
+            </div>
+          </div>
+          <!-- Engine id for snmp V3 -->
+          <div class="form-group row"
+               *ngIf="serviceForm.controls.snmp_version.value === 'V3'">
+            <label class="cd-col-form-label required"
+                   [ngClass]="{'required': ['snmp-gateway'].includes(serviceForm.controls.service_type.value)}"
+                   for="engine_id">
+              <span i18n>Engine Id</span>
+              <cd-helper>
+                <span i18n>Unique identifier for the device (in hex).</span>
+              </cd-helper>
+            </label>
+            <div class="cd-col-form-input">
+              <input id="engine_id"
+                     class="form-control"
+                     type="text"
+                     formControlName="engine_id">
+              <span class="invalid-feedback"
+                    *ngIf="serviceForm.showError('engine_id', frm, 'required')"
+                    i18n>This field is required.</span>
+            </div>
+          </div>
+          <!-- Auth protocol for snmp V3 -->
+          <div class="form-group row"
+               *ngIf="serviceForm.controls.snmp_version.value === 'V3'">
+            <label class="cd-col-form-label required"
+                   for="auth_protocol"
+                   i18n>Auth Protocol</label>
+            <div class="cd-col-form-input">
+              <select id="auth_protocol"
+                      name="auth_protocol"
+                      class="form-control custom-select"
+                      formControlName="auth_protocol">
+                <option i18n
+                        [ngValue]="null">-- Select auth protocol --</option>
+                <option *ngFor="let authProtocol of ['SHA', 'MD5']"
+                        [value]="authProtocol">
+                  {{ authProtocol }}
+                </option>
+              </select>
+              <span class="invalid-feedback"
+                    *ngIf="serviceForm.showError('auth_protocol', frm, 'required')"
+                    i18n>This field is required.</span>
+            </div>
+          </div>
+          <!-- Privacy protocol for snmp V3 -->
+          <div class="form-group row"
+               *ngIf="serviceForm.controls.snmp_version.value === 'V3'">
+            <label class="cd-col-form-label"
+                   for="privacy_protocol"
+                   i18n>Privacy Protocol</label>
+            <div class="cd-col-form-input">
+              <select id="privacy_protocol"
+                      name="privacy_protocol"
+                      class="form-control custom-select"
+                      formControlName="privacy_protocol">
+                <option i18n
+                        [ngValue]="null">-- Select privacy protocol --</option>
+                <option *ngFor="let privacyProtocol of ['DES', 'AES']"
+                        [value]="privacyProtocol">
+                  {{ privacyProtocol }}
+                </option>
+              </select>
+            </div>
+          </div>
+          <!-- Credentials -->
+          <fieldset>
+            <legend i18n>Credentials</legend>
+            <!-- snmp v2c snmp_community -->
+            <div class="form-group row"
+                 *ngIf="serviceForm.controls.snmp_version.value === 'V2c'">
+              <label class="cd-col-form-label required"
+                     [ngClass]="{'required': ['snmp-gateway'].includes(serviceForm.controls.service_type.value)}"
+                     for="snmp_community">
+                <span i18n>SNMP Community</span>
+              </label>
+              <div class="cd-col-form-input">
+                <input id="snmp_community"
+                       class="form-control"
+                       type="text"
+                       formControlName="snmp_community">
+                <span class="invalid-feedback"
+                      *ngIf="serviceForm.showError('snmp_community', frm, 'required')"
+                      i18n>This field is required.</span>
+              </div>
+            </div>
+            <!-- snmp v3 auth username -->
+            <div class="form-group row"
+                 *ngIf="serviceForm.controls.snmp_version.value === 'V3'">
+              <label class="cd-col-form-label required"
+                     [ngClass]="{'required': ['snmp-gateway'].includes(serviceForm.controls.service_type.value)}"
+                     for="snmp_v3_auth_username">
+                <span i18n>Username</span>
+              </label>
+              <div class="cd-col-form-input">
+                <input id="snmp_v3_auth_username"
+                       class="form-control"
+                       type="text"
+                       formControlName="snmp_v3_auth_username">
+                <span class="invalid-feedback"
+                      *ngIf="serviceForm.showError('snmp_v3_auth_username', frm, 'required')"
+                      i18n>This field is required.</span>
+              </div>
+            </div>
+            <!-- snmp v3 auth password -->
+            <div class="form-group row"
+                 *ngIf="serviceForm.controls.snmp_version.value === 'V3'">
+              <label class="cd-col-form-label required"
+                     [ngClass]="{'required': ['snmp-gateway'].includes(serviceForm.controls.service_type.value)}"
+                     for="snmp_v3_auth_password">
+                <span i18n>Password</span>
+              </label>
+              <div class="cd-col-form-input">
+                <input id="snmp_v3_auth_password"
+                       class="form-control"
+                       type="password"
+                       formControlName="snmp_v3_auth_password">
+                <span class="invalid-feedback"
+                      *ngIf="serviceForm.showError('snmp_v3_auth_password', frm, 'required')"
+                      i18n>This field is required.</span>
+              </div>
+            </div>
+            <!-- snmp v3 priv password -->
+            <div class="form-group row"
+                 *ngIf="serviceForm.controls.snmp_version.value === 'V3' && serviceForm.controls.privacy_protocol.value !== null && serviceForm.controls.privacy_protocol.value !== undefined">
+              <label class="cd-col-form-label required"
+                     [ngClass]="{'required': ['snmp-gateway'].includes(serviceForm.controls.service_type.value)}"
+                     for="snmp_v3_priv_password">
+                <span i18n>Encryption</span>
+              </label>
+              <div class="cd-col-form-input">
+                <input id="snmp_v3_priv_password"
+                       class="form-control"
+                       type="password"
+                       formControlName="snmp_v3_priv_password">
+                <span class="invalid-feedback"
+                      *ngIf="serviceForm.showError('snmp_v3_priv_password', frm, 'required')"
+                      i18n>This field is required.</span>
+              </div>
+            </div>
+          </fieldset>
+        </ng-container>
         <!-- RGW, Ingress & iSCSI -->
         <ng-container *ngIf="!serviceForm.controls.unmanaged.value && ['rgw', 'iscsi', 'ingress'].includes(serviceForm.controls.service_type.value)">
           <!-- ssl -->
index 183fd77b8cf311ff746602eb7bf3d8f3dcfcd66b..1667f6697b6e514590118ae82f825818a8972f08 100644 (file)
@@ -438,6 +438,54 @@ x4Ea7kGVgx9kWh5XjWz9wjZvY49UKIT5ppIAWPMbLl3UpfckiuNhTA==
       });
     });
 
+    describe('should test service snmp-gateway', () => {
+      beforeEach(() => {
+        formHelper.setValue('service_type', 'snmp-gateway');
+        formHelper.setValue('snmp_destination', '192.168.20.1:8443');
+      });
+
+      it('should test snmp-gateway service with V2c', () => {
+        formHelper.setValue('snmp_version', 'V2c');
+        formHelper.setValue('snmp_community', 'public');
+        component.onSubmit();
+        expect(cephServiceService.create).toHaveBeenCalledWith({
+          service_type: 'snmp-gateway',
+          placement: {},
+          unmanaged: false,
+          snmp_version: 'V2c',
+          snmp_destination: '192.168.20.1:8443',
+          credentials: {
+            snmp_community: 'public'
+          }
+        });
+      });
+      it('should test snmp-gateway service with V3', () => {
+        formHelper.setValue('snmp_version', 'V3');
+        formHelper.setValue('engine_id', '800C53F00000');
+        formHelper.setValue('auth_protocol', 'SHA');
+        formHelper.setValue('privacy_protocol', 'DES');
+        formHelper.setValue('snmp_v3_auth_username', 'testuser');
+        formHelper.setValue('snmp_v3_auth_password', 'testpass');
+        formHelper.setValue('snmp_v3_priv_password', 'testencrypt');
+        component.onSubmit();
+        expect(cephServiceService.create).toHaveBeenCalledWith({
+          service_type: 'snmp-gateway',
+          placement: {},
+          unmanaged: false,
+          snmp_version: 'V3',
+          snmp_destination: '192.168.20.1:8443',
+          engine_id: '800C53F00000',
+          auth_protocol: 'SHA',
+          privacy_protocol: 'DES',
+          credentials: {
+            snmp_v3_auth_username: 'testuser',
+            snmp_v3_auth_password: 'testpass',
+            snmp_v3_priv_password: 'testencrypt'
+          }
+        });
+      });
+    });
+
     describe('check edit fields', () => {
       beforeEach(() => {
         component.editing = true;
index d582922a0288c8ad5481b28564b94c74bf8526ca..28bae956298b0dfa6a3a3fd6aedad3288abe45fc 100644 (file)
@@ -212,6 +212,72 @@ export class ServiceFormComponent extends CdForm implements OnInit {
             [Validators.required, CdValidators.sslPrivKey()]
           )
         ]
+      ],
+      // snmp-gateway
+      snmp_version: [null, [Validators.required]],
+      snmp_destination: [
+        null,
+        [
+          CdValidators.requiredIf({
+            service_type: 'snmp-gateway',
+            unmanaged: false
+          })
+        ]
+      ],
+      engine_id: [
+        null,
+        [
+          CdValidators.requiredIf({
+            service_type: 'snmp-gateway',
+            unmanaged: false
+          })
+        ]
+      ],
+      auth_protocol: [
+        'SHA',
+        [
+          CdValidators.requiredIf({
+            service_type: 'snmp-gateway',
+            unmanaged: false
+          })
+        ]
+      ],
+      privacy_protocol: [null],
+      snmp_community: [
+        null,
+        [
+          CdValidators.requiredIf({
+            service_type: 'snmp-gateway',
+            unmanaged: false
+          })
+        ]
+      ],
+      snmp_v3_auth_username: [
+        null,
+        [
+          CdValidators.requiredIf({
+            service_type: 'snmp-gateway',
+            unmanaged: false
+          })
+        ]
+      ],
+      snmp_v3_auth_password: [
+        null,
+        [
+          CdValidators.requiredIf({
+            service_type: 'snmp-gateway',
+            unmanaged: false
+          })
+        ]
+      ],
+      snmp_v3_priv_password: [
+        null,
+        [
+          CdValidators.requiredIf({
+            service_type: 'snmp-gateway',
+            unmanaged: false
+          })
+        ]
       ]
     });
   }
@@ -314,6 +380,39 @@ export class ServiceFormComponent extends CdForm implements OnInit {
               this.serviceForm.get('ssl_key').setValue(response[0].spec?.ssl_key);
             }
             break;
+          case 'snmp-gateway':
+            const snmpCommonSpecKeys = ['snmp_version', 'snmp_destination'];
+            snmpCommonSpecKeys.forEach((key) => {
+              this.serviceForm.get(key).setValue(response[0].spec[key]);
+            });
+            if (this.serviceForm.getValue('snmp_version') === 'V3') {
+              const snmpV3SpecKeys = [
+                'engine_id',
+                'auth_protocol',
+                'privacy_protocol',
+                'snmp_v3_auth_username',
+                'snmp_v3_auth_password',
+                'snmp_v3_priv_password'
+              ];
+              snmpV3SpecKeys.forEach((key) => {
+                if (key !== null) {
+                  if (
+                    key === 'snmp_v3_auth_username' ||
+                    key === 'snmp_v3_auth_password' ||
+                    key === 'snmp_v3_priv_password'
+                  ) {
+                    this.serviceForm.get(key).setValue(response[0].spec['credentials'][key]);
+                  } else {
+                    this.serviceForm.get(key).setValue(response[0].spec[key]);
+                  }
+                }
+              });
+            } else {
+              this.serviceForm
+                .get('snmp_community')
+                .setValue(response[0].spec['credentials']['snmp_community']);
+            }
+            break;
         }
       });
     }
@@ -453,6 +552,23 @@ export class ServiceFormComponent extends CdForm implements OnInit {
           }
           serviceSpec['virtual_interface_networks'] = values['virtual_interface_networks'];
           break;
+        case 'snmp-gateway':
+          serviceSpec['credentials'] = {};
+          serviceSpec['snmp_version'] = values['snmp_version'];
+          serviceSpec['snmp_destination'] = values['snmp_destination'];
+          if (values['snmp_version'] === 'V3') {
+            serviceSpec['engine_id'] = values['engine_id'];
+            serviceSpec['auth_protocol'] = values['auth_protocol'];
+            serviceSpec['credentials']['snmp_v3_auth_username'] = values['snmp_v3_auth_username'];
+            serviceSpec['credentials']['snmp_v3_auth_password'] = values['snmp_v3_auth_password'];
+            if (values['privacy_protocol'] !== null) {
+              serviceSpec['privacy_protocol'] = values['privacy_protocol'];
+              serviceSpec['credentials']['snmp_v3_priv_password'] = values['snmp_v3_priv_password'];
+            }
+          } else {
+            serviceSpec['credentials']['snmp_community'] = values['snmp_community'];
+          }
+          break;
       }
     }
 
@@ -474,4 +590,21 @@ export class ServiceFormComponent extends CdForm implements OnInit {
         }
       });
   }
+
+  clearValidations() {
+    const snmpVersion = this.serviceForm.getValue('snmp_version');
+    const privacyProtocol = this.serviceForm.getValue('privacy_protocol');
+    if (snmpVersion === 'V3') {
+      this.serviceForm.get('snmp_community').clearValidators();
+    } else {
+      this.serviceForm.get('engine_id').clearValidators();
+      this.serviceForm.get('auth_protocol').clearValidators();
+      this.serviceForm.get('privacy_protocol').clearValidators();
+      this.serviceForm.get('snmp_v3_auth_username').clearValidators();
+      this.serviceForm.get('snmp_v3_auth_password').clearValidators();
+    }
+    if (privacyProtocol === null) {
+      this.serviceForm.get('snmp_v3_priv_password').clearValidators();
+    }
+  }
 }