Skip to content

Commit

Permalink
Merge branch 'master' into api-update
Browse files Browse the repository at this point in the history
  • Loading branch information
NajmudheenCT authored Dec 18, 2020
2 parents 0bef95b + b04b66c commit 0b7e9f6
Show file tree
Hide file tree
Showing 18 changed files with 558 additions and 1 deletion.
54 changes: 54 additions & 0 deletions delfin/api/v1/controllers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Copyright 2020 The SODA Authors.
#
# 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.

from delfin import db
from delfin.api import api_utils
from delfin.api.common import wsgi
from delfin.api.views import controllers as controller_view


class ControllerController(wsgi.Controller):

def __init__(self):
super(ControllerController, self).__init__()
self.search_options = ['name', 'status', 'id', 'storage_id',
'native_controller_id']

def _get_controllers_search_options(self):
"""Return controllers search options allowed ."""
return self.search_options

def index(self, req):
ctxt = req.environ['delfin.context']
query_params = {}
query_params.update(req.GET)
# update options other than filters
sort_keys, sort_dirs = api_utils.get_sort_params(query_params)
marker, limit, offset = api_utils.get_pagination_params(query_params)
# strip out options except supported search options
api_utils.remove_invalid_options(
ctxt, query_params, self._get_controllers_search_options())

controllers = db.controller_get_all(ctxt, marker, limit, sort_keys,
sort_dirs, query_params, offset)
return controller_view.build_controllers(controllers)

def show(self, req, id):
ctxt = req.environ['delfin.context']
controller = db.controller_get(ctxt, id)
return controller_view.build_controller(controller)


def create_resource():
return wsgi.Resource(ControllerController())
5 changes: 5 additions & 0 deletions delfin/api/v1/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from delfin.api.v1 import access_info
from delfin.api.v1 import alert_source
from delfin.api.v1 import alerts
from delfin.api.v1 import controllers
from delfin.api.v1 import storage_pools
from delfin.api.v1 import storages
from delfin.api.v1 import volumes
Expand Down Expand Up @@ -94,3 +95,7 @@ def _setup_routes(self, mapper):
self.resources['volumes'] = volumes.create_resource()
mapper.resource("volume", "volumes",
controller=self.resources['volumes'])

self.resources['controllers'] = controllers.create_resource()
mapper.resource("controller", "controllers",
controller=self.resources['controllers'])
26 changes: 26 additions & 0 deletions delfin/api/views/controllers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright 2020 The SODA Authors.
#
# 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 copy


def build_controllers(controllers):
# Build list of controllers
views = [build_controller(controller)
for controller in controllers]
return dict(controllers=views)


def build_controller(controller):
view = copy.deepcopy(controller)
return dict(view)
8 changes: 8 additions & 0 deletions delfin/common/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ class VolumeStatus(object):
ALL = (AVAILABLE, ERROR)


class ControllerStatus(object):
NORMAL = 'normal'
OFFLINE = 'offline'
UNKNOWN = 'unknown'

ALL = (NORMAL, OFFLINE, UNKNOWN)


class StorageType(object):
BLOCK = 'block'
FILE = 'file'
Expand Down
58 changes: 58 additions & 0 deletions delfin/db/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,64 @@ def storage_pool_delete_by_storage(context, storage_id):
return IMPL.storage_pool_delete_by_storage(context, storage_id)


def controllers_create(context, values):
"""Create multiple controllers."""
return IMPL.controllers_create(context, values)


def controllers_update(context, values):
"""Update multiple controllers."""
return IMPL.controllers_update(context, values)


def controllers_delete(context, values):
"""Delete multiple controllers."""
return IMPL.controllers_delete(context, values)


def controller_create(context, values):
"""Create a controller from the values dictionary."""
return IMPL.controller_create(context, values)


def controller_update(context, controller_id, values):
"""Update a controller with the values dictionary."""
return IMPL.controller_update(context, controller_id, values)


def controller_get(context, controller_id):
"""Get a controller or raise an exception if it does not exist."""
return IMPL.controller_get(context, controller_id)


def controller_delete_by_storage(context, storage_id):
"""Delete a controller or raise an exception if it does not exist."""
return IMPL.controller_delete_by_storage(context, storage_id)


def controller_get_all(context, marker=None, limit=None, sort_keys=None,
sort_dirs=None, filters=None, offset=None):
"""Retrieves all controllers.
If no sort parameters are specified then the returned volumes are sorted
first by the 'created_at' key and then by the 'id' key in descending
order.
:param context: context of this request, it's helpful to trace the request
:param marker: the last item of the previous page, used to determine the
next page of results to return
:param limit: maximum number of items to return
:param sort_keys: list of attributes by which results should be sorted,
paired with corresponding item in sort_dirs
:param sort_dirs: list of directions in which results should be sorted,
paired with corresponding item in sort_keys, for example
'desc' for descending order
:param filters: dictionary of filters
:param offset: number of items to skip
:returns: list of controllers
"""
return IMPL.controller_get_all(context, marker, limit, sort_keys,
sort_dirs, filters, offset)


def disk_create(context, values):
"""Create a disk from the values dictionary."""
return IMPL.disk_create(context, values)
Expand Down
146 changes: 146 additions & 0 deletions delfin/db/sqlalchemy/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,149 @@ def _process_storage_pool_info_filters(query, filters):
return query


def controllers_create(context, controllers):
"""Create multiple controllers."""
session = get_session()
controllers_refs = []
with session.begin():

for controller in controllers:
LOG.debug('adding new controller for native_controller_id {0}:'
.format(controller.get('native_controller_id')))
if not controller.get('id'):
controller['id'] = uuidutils.generate_uuid()

controller_ref = models.Controller()
controller_ref.update(controller)
controllers_refs.append(controller_ref)

session.add_all(controllers_refs)

return controllers_refs


def controllers_update(context, controllers):
"""Update multiple controllers."""
session = get_session()

with session.begin():
controller_refs = []

for controller in controllers:
LOG.debug('updating controller {0}:'.format(
controller.get('id')))
query = _controller_get_query(context, session)
result = query.filter_by(id=controller.get('id')
).update(controller)

if not result:
LOG.error(exception.ControllerNotFound(controller.get(
'id')))
else:
controller_refs.append(result)

return controller_refs


def controllers_delete(context, controllers_id_list):
"""Delete multiple controllers."""
session = get_session()
with session.begin():
for controller_id in controllers_id_list:
LOG.debug('deleting controller {0}:'.format(controller_id))
query = _controller_get_query(context, session)
result = query.filter_by(id=controller_id).delete()

if not result:
LOG.error(exception.ControllerNotFound(controller_id))

return


def _controller_get_query(context, session=None):
return model_query(context, models.Controller, session=session)


def _controller_get(context, controller_id, session=None):
result = (_controller_get_query(context, session=session)
.filter_by(id=controller_id)
.first())

if not result:
raise exception.ControllerNotFound(controller_id)

return result


def controller_create(context, values):
"""Create a controller from the values dictionary."""
if not values.get('id'):
values['id'] = uuidutils.generate_uuid()

controller_ref = models.Controller()
controller_ref.update(values)

session = get_session()
with session.begin():
session.add(controller_ref)

return _controller_get(context,
controller_ref['id'],
session=session)


def controller_update(context, controller_id, values):
"""Update a controller with the values dictionary."""
session = get_session()

with session.begin():
query = _controller_get_query(context, session)
result = query.filter_by(id=controller_id).update(values)

if not result:
raise exception.ControllerNotFound(controller_id)

return result


def controller_get(context, controller_id):
"""Get a controller or raise an exception if it does not exist."""
return _controller_get(context, controller_id)


def controller_delete_by_storage(context, storage_id):
"""Delete a controller or raise an exception if it does not exist."""
_controller_get_query(context).filter_by(storage_id=storage_id).delete()


def controller_get_all(context, marker=None, limit=None, sort_keys=None,
sort_dirs=None, filters=None, offset=None):
"""Retrieves all controllers."""

session = get_session()
with session.begin():
# Generate the query
query = _generate_paginate_query(context, session, models.Controller,
marker, limit, sort_keys, sort_dirs,
filters, offset,
)
# No Controller would match, return empty list
if query is None:
return []
return query.all()


@apply_like_filters(model=models.Controller)
def _process_controller_info_filters(query, filters):
"""Common filter processing for controllers queries."""
if filters:
if not is_valid_model_filters(models.Controller, filters):
return
query = query.filter_by(**filters)

return query


def disk_create(context, values):
"""Create a disk from the values dictionary."""
return NotImplemented
Expand Down Expand Up @@ -714,6 +857,9 @@ def alert_source_get_all(context, marker=None, limit=None, sort_keys=None,
_alert_source_get),
models.Volume: (_volume_get_query, _process_volume_info_filters,
_volume_get),
models.Controller: (_controller_get_query,
_process_controller_info_filters,
_controller_get),
}


Expand Down
14 changes: 14 additions & 0 deletions delfin/db/sqlalchemy/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,20 @@ class Disk(BASE, DelfinBase):
capacity = Column(BigInteger)


class Controller(BASE, DelfinBase):
"""Represents a controller object."""
__tablename__ = 'controllers'
id = Column(String(36), primary_key=True)
native_controller_id = Column(String(255))
name = Column(String(255))
status = Column(String(255))
location = Column(String(255))
soft_version = Column(String(255))
cpu_info = Column(String(255))
memory_size = Column(BigInteger)
storage_id = Column(String(36))


class AlertSource(BASE, DelfinBase):
"""Represents an alert source configuration."""
__tablename__ = 'alert_source'
Expand Down
6 changes: 6 additions & 0 deletions delfin/drivers/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ def list_volumes(self, context, storage_id):
driver = self.driver_manager.get_driver(context, storage_id=storage_id)
return driver.list_volumes(context)

def list_controllers(self, context, storage_id):
"""List all storage controllers from storage system."""

driver = self.driver_manager.get_driver(context, storage_id=storage_id)
return driver.list_controllers(context)

def add_trap_config(self, context, storage_id, trap_config):
"""Config the trap receiver in storage system."""
pass
Expand Down
3 changes: 3 additions & 0 deletions delfin/drivers/dell_emc/vmax/vmax.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ def list_storage_pools(self, context):
def list_volumes(self, context):
return self.client.list_volumes(self.storage_id)

def list_controllers(self, context):
pass

def add_trap_config(self, context, trap_config):
pass

Expand Down
5 changes: 5 additions & 0 deletions delfin/drivers/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ def list_volumes(self, context):
"""List all storage volumes from storage system."""
pass

@abc.abstractmethod
def list_controllers(self, context):
"""List all storage controllers from storage system."""
pass

@abc.abstractmethod
def add_trap_config(self, context, trap_config):
"""Config the trap receiver in storage system."""
Expand Down
Loading

0 comments on commit 0b7e9f6

Please sign in to comment.