From 4ad40cc88c3091046cb08cc8de8ef4ae25226416 Mon Sep 17 00:00:00 2001 From: rajdeep11 Date: Fri, 13 Dec 2024 18:27:37 +0530 Subject: [PATCH] adding featuregroup controller and making the featuregroup name unique Change-Id: I3218f65ee3e27ba1432dc6aa8b711615ddf3cf85 Signed-off-by: rajdeep11 --- trainingmgr/controller/__init__.py | 7 +- trainingmgr/controller/featuregroup_controller.py | 127 ++++++++++++++++++++++ trainingmgr/models/featuregroup.py | 5 + trainingmgr/trainingmgr_main.py | 95 +--------------- 4 files changed, 140 insertions(+), 94 deletions(-) create mode 100644 trainingmgr/controller/featuregroup_controller.py diff --git a/trainingmgr/controller/__init__.py b/trainingmgr/controller/__init__.py index 677395c..51acd28 100644 --- a/trainingmgr/controller/__init__.py +++ b/trainingmgr/controller/__init__.py @@ -14,4 +14,9 @@ # See the License for the specific language governing permissions and # limitations under the License. # -# ================================================================================== \ No newline at end of file +# ================================================================================== + +from .trainingjob_controller import training_job_controller +from .featuregroup_controller import featuregroup_controller + +__all__ = ['training_job_controller', 'featuregroup_controller'] \ No newline at end of file diff --git a/trainingmgr/controller/featuregroup_controller.py b/trainingmgr/controller/featuregroup_controller.py new file mode 100644 index 0000000..af4ace4 --- /dev/null +++ b/trainingmgr/controller/featuregroup_controller.py @@ -0,0 +1,127 @@ +# ================================================================================== +# +# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ================================================================================== +import json +from flask_api import status +from flask import Blueprint, jsonify, request +from marshmallow import ValidationError +from trainingmgr.common.exceptions_utls import DBException +from trainingmgr.common.trainingmgr_operations import create_dme_filtered_data_job +from trainingmgr.common.trainingmgr_util import check_trainingjob_name_or_featuregroup_name +from trainingmgr.db.featuregroup_db import add_featuregroup, delete_feature_group_by_name +from trainingmgr.common.trainingmgr_config import TrainingMgrConfig +from trainingmgr.schemas import FeatureGroupSchema + + + +featuregroup_controller = Blueprint('featuregroup_controller', __name__) +TRAININGMGR_CONFIG_OBJ = TrainingMgrConfig() +LOGGER = TRAININGMGR_CONFIG_OBJ.logger +MIMETYPE_JSON = "application/json" + +@featuregroup_controller.route('/featureGroup', methods=['POST']) +def create_feature_group(): + """ + Rest endpoint to create feature group + + Args in function: + NONE + + Args in json: + json with below fields are given: + featureGroupName: str + description + feature_list: str + feature names + datalake: str + name of datalake + bucket: str + bucket name + host: str + db host + port: str + db port + token: str + token for the bucket + db org: str + db org name + measurement: str + measurement of the influxdb + enable_Dme: boolean + whether to enable dme + source_name: str + name of source + DmePort: str + DME port + measured_obj_class: str + obj class for dme. + datalake_source: str + string indicating datalake source + + Returns: + 1. For post request + json: + result : str + result message + status code: + HTTP status code 201 + 2. For put request + json: + result : str + result message + status code: + HTTP status code 200 + + Exceptions: + All exception are provided with exception message and HTTP status code.""" + + api_response = {} + response_code = status.HTTP_500_INTERNAL_SERVER_ERROR + LOGGER.debug('feature Group Create request, ' + json.dumps(request.json)) + + try: + featuregroup = FeatureGroupSchema().load(request.get_json()) + feature_group_name = featuregroup.featuregroup_name + # check the data conformance + # LOGGER.debug("the db info is : ", get_feature_group_by_name_db(PS_DB_OBJ, feature_group_name)) + if (not check_trainingjob_name_or_featuregroup_name(feature_group_name) or + len(feature_group_name) < 3 or len(feature_group_name) > 63): + api_response = {"Exception": "Failed to create the feature group since feature group not valid"} + response_code = status.HTTP_400_BAD_REQUEST + else: + # the features are stored in string format in the db, and has to be passed as list of feature to the dme. Hence the conversion. + add_featuregroup(featuregroup) + api_response = FeatureGroupSchema().dump(featuregroup) + response_code =status.HTTP_200_OK + if featuregroup.enable_dme == True : + response= create_dme_filtered_data_job(TRAININGMGR_CONFIG_OBJ, featuregroup) + if response.status_code != 201: + api_response={"Exception": "Cannot create dme job"} + delete_feature_group_by_name(featuregroup) + response_code=status.HTTP_400_BAD_REQUEST + except ValidationError as err: + LOGGER.error(f"Failed to create the feature Group {str(err)}") + return {"Exception": str(err)}, 400 + except DBException as err: + LOGGER.error(f"Failed to create the feature Group {str(err)}") + return {"Exception": str(err)}, 400 + except Exception as e: + api_response = {"Exception":str(e)} + LOGGER.error(f"Failed to create the feature Group {str(err)}") + jsonify(json.dumps(api_response)), 500 + + return jsonify(api_response), 201 \ No newline at end of file diff --git a/trainingmgr/models/featuregroup.py b/trainingmgr/models/featuregroup.py index 2c59b6f..ec9d2ff 100644 --- a/trainingmgr/models/featuregroup.py +++ b/trainingmgr/models/featuregroup.py @@ -16,6 +16,7 @@ # # ================================================================================== from . import db +from sqlalchemy import UniqueConstraint class FeatureGroup(db.Model): __tablename__ = "featuregroup_info_table" @@ -34,5 +35,9 @@ class FeatureGroup(db.Model): dme_port = db.Column(db.String(128), nullable=True) source_name = db.Column(db.String(20000), nullable=True) + __table_args__ = ( + UniqueConstraint("featuregroup_name", name="unique featuregroup"), + ) + def __repr__(self): return f'' \ No newline at end of file diff --git a/trainingmgr/trainingmgr_main.py b/trainingmgr/trainingmgr_main.py index c0f41ef..3483a34 100644 --- a/trainingmgr/trainingmgr_main.py +++ b/trainingmgr/trainingmgr_main.py @@ -54,7 +54,7 @@ from trainingmgr.models import db, TrainingJob, FeatureGroup from trainingmgr.schemas import ma, TrainingJobSchema , FeatureGroupSchema from trainingmgr.db.featuregroup_db import add_featuregroup, edit_featuregroup, get_feature_groups_db, \ get_feature_group_by_name_db, delete_feature_group_by_name -from trainingmgr.controller.trainingjob_controller import training_job_controller +from trainingmgr.controller import featuregroup_controller, training_job_controller from trainingmgr.controller.pipeline_controller import pipeline_controller from trainingmgr.common.trainingConfig_parser import validateTrainingConfig, getField from trainingmgr.handler.async_handler import start_async_handler @@ -65,6 +65,7 @@ APP = Flask(__name__) TRAININGMGR_CONFIG_OBJ = TrainingMgrConfig() from middleware.loggingMiddleware import LoggingMiddleware APP.wsgi_app = LoggingMiddleware(APP.wsgi_app) +APP.register_blueprint(featuregroup_controller) APP.register_blueprint(training_job_controller) APP.register_blueprint(pipeline_controller) @@ -649,98 +650,6 @@ def feature_group_by_name(featuregroup_name): status= response_code, mimetype=MIMETYPE_JSON) -@APP.route('/featureGroup', methods=['POST']) -def create_feature_group(): - """ - Rest endpoint to create feature group - - Args in function: - NONE - - Args in json: - json with below fields are given: - featureGroupName: str - description - feature_list: str - feature names - datalake: str - name of datalake - bucket: str - bucket name - host: str - db host - port: str - db port - token: str - token for the bucket - db org: str - db org name - measurement: str - measurement of the influxdb - enable_Dme: boolean - whether to enable dme - source_name: str - name of source - DmePort: str - DME port - measured_obj_class: str - obj class for dme. - datalake_source: str - string indicating datalake source - - Returns: - 1. For post request - json: - result : str - result message - status code: - HTTP status code 201 - 2. For put request - json: - result : str - result message - status code: - HTTP status code 200 - - Exceptions: - All exception are provided with exception message and HTTP status code.""" - - api_response = {} - response_code = status.HTTP_500_INTERNAL_SERVER_ERROR - LOGGER.debug('feature Group Create request, ' + json.dumps(request.json)) - - try: - featuregroup = FeatureGroupSchema().load(request.get_json()) - feature_group_name = featuregroup.featuregroup_name - # check the data conformance - # LOGGER.debug("the db info is : ", get_feature_group_by_name_db(PS_DB_OBJ, feature_group_name)) - if (not check_trainingjob_name_or_featuregroup_name(feature_group_name) or - len(feature_group_name) < 3 or len(feature_group_name) > 63): - api_response = {"Exception": "Failed to create the feature group since feature group not valid"} - response_code = status.HTTP_400_BAD_REQUEST - else: - # the features are stored in string format in the db, and has to be passed as list of feature to the dme. Hence the conversion. - add_featuregroup(featuregroup) - api_response = FeatureGroupSchema().dump(featuregroup) - response_code =status.HTTP_200_OK - if featuregroup.enable_dme == True : - response= create_dme_filtered_data_job(TRAININGMGR_CONFIG_OBJ, featuregroup) - if response.status_code != 201: - api_response={"Exception": "Cannot create dme job"} - delete_feature_group_by_name(featuregroup) - response_code=status.HTTP_400_BAD_REQUEST - except ValidationError as err: - return {"Exception": str(err)}, 400 - except DBException as err: - return {"Exception": str(err)}, 400 - except Exception as e: - err_msg = "Failed to create the feature Group " - api_response = {"Exception":str(e)} - LOGGER.error(str(e)) - - return APP.response_class(response=json.dumps(api_response), - status=response_code, - mimetype=MIMETYPE_JSON) @APP.route('/featureGroup', methods=['GET']) def get_feature_group(): -- 2.16.6