Add manager.py to redirect to respective podmanager

This commit is add new module manager.py to redirect the controller
requests to respective podmanager based on 'driver' field.

This commit takes reference of multi-podm patch proposed here:
https://review.openstack.org/#/c/445360/10 and extends the same.

Partially-Implements blueprint add-vendor-extensible-framework

Change-Id: I92efd4c18c75613a6365c750b09390cbe1fedc2e
This commit is contained in:
Anusha Ramineni 2017-08-09 16:52:25 +05:30
parent 78de3b7ba7
commit 570086d34a
8 changed files with 163 additions and 2 deletions

View File

@ -65,3 +65,6 @@ oslo.config.opts =
valence.provision.driver =
ironic = valence.provision.ironic.driver:IronicDriver
valence.podmanager.driver =
redfishv1 = valence.podmanagers.podm_base:PodManagerBase

View File

@ -120,6 +120,10 @@ class NotFound(ValenceError):
_msg_fmt = "Resource could not be found"
class DriverNotFound(NotFound):
_msg_fmt = "Unsupported Driver Specified"
class BadRequest(ValenceError):
status = http_client.BAD_REQUEST
_msg_fmt = "Bad Request"

View File

@ -17,12 +17,13 @@
"""
import logging
import flask
from oslo_utils import uuidutils
from valence.common import constants
LOG = logging.getLogger(__name__)
@ -111,3 +112,16 @@ def make_response(status_code, content="", headers=None):
def generate_uuid():
"""Generate uniform format uuid"""
return uuidutils.generate_uuid()
def get_basic_auth_credentials(authentication):
"""parse out the basic auth from podm's authentication array properties
:param authentication: podm's authentication
:return: username, password to connect to the podm
"""
for auth_property in authentication:
if auth_property['type'] == constants.PODM_AUTH_BASIC_TYPE:
username = auth_property['auth_items']['username']
password = auth_property['auth_items']['password']
return username, password

View File

@ -0,0 +1,57 @@
import logging
import stevedore
from valence.common import exception
from valence.common import utils
from valence.db import api as db_api
LOG = logging.getLogger(__name__)
# cache podmanager connections, one connection per podmanager
podm_connections = {}
# cache podmanager modules, to be loaded only once per driver
# If same driver used by 2 podmanagers (eg:redfishv1), podm_base module will be
# loaded only once, but 2 instances of class would be created.
podm_modules = {}
def get_podm_connection(podm_id):
podm_connection = podm_connections.get(podm_id, None)
if podm_connection:
return podm_connection
podm_db = db_api.Connection.get_podmanager_by_uuid(podm_id).as_dict()
username, password = utils.get_basic_auth_credentials(
podm_db['authentication'])
podm_connection = Manager(podm_db['url'], username, password,
podm_db['driver'])
podm_connections[podm_id] = podm_connection
return podm_connection
class Manager(object):
def __init__(self, url, username, password, driver='redfishv1'):
self.podm = self._get_podm_instance(driver, url, username, password)
def _get_podm_instance(self, driver, url, username, password):
podm = self.load_podm(driver)
return podm(username, password, url)
@classmethod
def load_podm(cls, driver):
# get module if already loaded
podm = podm_modules.get(driver, None)
if not podm:
try:
podm = stevedore.driver.DriverManager(
'valence.podmanager.driver',
driver, invoke_on_load=False).driver
except RuntimeError:
msg = "podmanager could not be loaded with specified driver %s"
LOG.exception(msg % driver)
raise exception.DriverNotFound(msg % driver)
podm_modules[driver] = podm
return podm

View File

@ -16,7 +16,7 @@
import sushy
from sushy import exceptions
from resources import chassis
from valence.redfish.sushy.resources import chassis
class RedfishInstance(sushy.Sushy):

View File

@ -0,0 +1,34 @@
# 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 valence.db import models
def fake_podmanager():
return {
"name": "fake-podm",
"podm_id": "fake-id",
"url": "https://10.240.212.123",
"driver": "redfishv1",
"authentication": [
{
"type": "basic",
"auth_items": {
"username": "fake-user",
"password": "fake-pass"
}
}]
}
def fake_podm_object():
return models.PodManager(**fake_podmanager())

View File

@ -0,0 +1,49 @@
# Copyright 2017 NEC, Corp.
#
# 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 mock
from oslotest import base
from valence.common import exception
from valence.podmanagers import manager
from valence.podmanagers import podm_base
from valence.tests.unit.fakes import podmanager_fakes
class TestManager(base.BaseTestCase):
def setUp(self):
super(TestManager, self).setUp()
def test_load_podm_failure(self):
self.assertRaises(exception.DriverNotFound, manager.Manager.load_podm,
'UnknownDriver')
def test_load_podm(self):
podm = manager.Manager.load_podm('redfishv1')
self.assertEqual(manager.podm_modules['redfishv1'], podm)
@mock.patch("valence.redfish.sushy.sushy_instance.RedfishInstance")
def test_get_podm_instance(self, mock_redfish):
mng = manager.Manager('http://fake-url', 'fake-user', 'fake-pass')
self.assertTrue(isinstance(mng.podm, podm_base.PodManagerBase))
@mock.patch("valence.db.api.Connection.get_podmanager_by_uuid")
@mock.patch("valence.redfish.sushy.sushy_instance.RedfishInstance")
def test_get_podm_connection(self, redfish_mock, get_podm_mock):
get_podm_mock.return_value = podmanager_fakes.fake_podm_object()
inst = manager.get_podm_connection("fake-id")
self.assertTrue(isinstance(inst, manager.Manager))
self.assertTrue(isinstance(inst.podm, podm_base.PodManagerBase))
self.assertTrue(manager.podm_connections['fake-id'])