Adds audit support for VIM, VNFD and VNF
implements blueprint: audit-support Co-Authored-By: Vishwanath Jayaraman <vishwanathj@hotmail.com> Change-Id: I8e6c4d6d47130c447c9a77e654d2dfad5d23ae7e
This commit is contained in:
parent
492796465f
commit
8ca9c9cfea
@ -0,0 +1,37 @@
|
|||||||
|
# Copyright 2016 OpenStack Foundation
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
"""audit support
|
||||||
|
|
||||||
|
Revision ID: 2ff0a0e360f1
|
||||||
|
Revises: 22f5385a3d50
|
||||||
|
Create Date: 2016-06-02 15:14:31.888078
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '2ff0a0e360f1'
|
||||||
|
down_revision = '22f5385a3d50'
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade(active_plugins=None, options=None):
|
||||||
|
for table in ['vims', 'vnf', 'vnfd']:
|
||||||
|
op.add_column(table,
|
||||||
|
sa.Column('created_at', sa.DateTime(), nullable=True))
|
||||||
|
op.add_column(table,
|
||||||
|
sa.Column('updated_at', sa.DateTime(), nullable=True))
|
@ -1 +1,2 @@
|
|||||||
22f5385a3d50
|
2ff0a0e360f1
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from oslo_utils import timeutils
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
@ -31,3 +32,11 @@ class HasId(object):
|
|||||||
id = sa.Column(types.Uuid,
|
id = sa.Column(types.Uuid,
|
||||||
primary_key=True,
|
primary_key=True,
|
||||||
default=uuidutils.generate_uuid)
|
default=uuidutils.generate_uuid)
|
||||||
|
|
||||||
|
|
||||||
|
class Audit(object):
|
||||||
|
"""Helps to add time stamp for create, update and delete actions. """
|
||||||
|
|
||||||
|
created_at = sa.Column(sa.DateTime,
|
||||||
|
default=lambda: timeutils.utcnow())
|
||||||
|
updated_at = sa.Column(sa.DateTime)
|
||||||
|
@ -18,6 +18,7 @@ import uuid
|
|||||||
|
|
||||||
from oslo_db import exception
|
from oslo_db import exception
|
||||||
from oslo_utils import strutils
|
from oslo_utils import strutils
|
||||||
|
from oslo_utils import timeutils
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
from sqlalchemy import orm
|
from sqlalchemy import orm
|
||||||
from sqlalchemy.orm import exc as orm_exc
|
from sqlalchemy.orm import exc as orm_exc
|
||||||
@ -33,11 +34,16 @@ from tacker import manager
|
|||||||
|
|
||||||
|
|
||||||
VIM_ATTRIBUTES = ('id', 'type', 'tenant_id', 'name', 'description',
|
VIM_ATTRIBUTES = ('id', 'type', 'tenant_id', 'name', 'description',
|
||||||
'placement_attr', 'shared', 'is_default', 'status')
|
'placement_attr', 'shared', 'is_default',
|
||||||
|
'created_at', 'updated_at', 'status')
|
||||||
|
|
||||||
VIM_AUTH_ATTRIBUTES = ('auth_url', 'vim_project', 'password', 'auth_cred')
|
VIM_AUTH_ATTRIBUTES = ('auth_url', 'vim_project', 'password', 'auth_cred')
|
||||||
|
|
||||||
|
|
||||||
class Vim(model_base.BASE, models_v1.HasId, models_v1.HasTenant):
|
class Vim(model_base.BASE,
|
||||||
|
models_v1.HasId,
|
||||||
|
models_v1.HasTenant,
|
||||||
|
models_v1.Audit):
|
||||||
type = sa.Column(sa.String(64), nullable=False)
|
type = sa.Column(sa.String(64), nullable=False)
|
||||||
name = sa.Column(sa.String(255), nullable=False)
|
name = sa.Column(sa.String(255), nullable=False)
|
||||||
description = sa.Column(sa.Text, nullable=True)
|
description = sa.Column(sa.Text, nullable=True)
|
||||||
@ -151,9 +157,9 @@ class NfvoPluginDb(nfvo.NFVOPluginBase, db_base.CommonDbMixin):
|
|||||||
vim_cred = vim['auth_cred']
|
vim_cred = vim['auth_cred']
|
||||||
vim_project = vim['vim_project']
|
vim_project = vim['vim_project']
|
||||||
is_default = vim.get('is_default')
|
is_default = vim.get('is_default')
|
||||||
|
vim_db = self._get_resource(context, Vim, vim_id)
|
||||||
try:
|
try:
|
||||||
if is_default:
|
if is_default:
|
||||||
vim_db = self._get_resource(context, Vim, vim_id)
|
|
||||||
vim_db.update({'is_default': is_default})
|
vim_db.update({'is_default': is_default})
|
||||||
vim_auth_db = (self._model_query(context, VimAuth).filter(
|
vim_auth_db = (self._model_query(context, VimAuth).filter(
|
||||||
VimAuth.vim_id == vim_id).with_lockmode('update').one())
|
VimAuth.vim_id == vim_id).with_lockmode('update').one())
|
||||||
@ -162,6 +168,8 @@ class NfvoPluginDb(nfvo.NFVOPluginBase, db_base.CommonDbMixin):
|
|||||||
vim_auth_db.update({'auth_cred': vim_cred, 'password':
|
vim_auth_db.update({'auth_cred': vim_cred, 'password':
|
||||||
vim_cred.pop('password'), 'vim_project':
|
vim_cred.pop('password'), 'vim_project':
|
||||||
vim_project})
|
vim_project})
|
||||||
|
vim_db.update({'updated_at': timeutils.utcnow()})
|
||||||
|
|
||||||
return self.get_vim(context, vim_id)
|
return self.get_vim(context, vim_id)
|
||||||
|
|
||||||
def update_vim_status(self, context, vim_id, status):
|
def update_vim_status(self, context, vim_id, status):
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
from oslo_utils import timeutils
|
||||||
|
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
from sqlalchemy import orm
|
from sqlalchemy import orm
|
||||||
from sqlalchemy.orm import exc as orm_exc
|
from sqlalchemy.orm import exc as orm_exc
|
||||||
@ -42,7 +44,8 @@ CREATE_STATES = (constants.PENDING_CREATE, constants.DEAD)
|
|||||||
###########################################################################
|
###########################################################################
|
||||||
# db tables
|
# db tables
|
||||||
|
|
||||||
class VNFD(model_base.BASE, models_v1.HasId, models_v1.HasTenant):
|
class VNFD(model_base.BASE, models_v1.HasId, models_v1.HasTenant,
|
||||||
|
models_v1.Audit):
|
||||||
"""Represents VNFD to create VNF."""
|
"""Represents VNFD to create VNF."""
|
||||||
|
|
||||||
__tablename__ = 'vnfd'
|
__tablename__ = 'vnfd'
|
||||||
@ -92,7 +95,8 @@ class VNFDAttribute(model_base.BASE, models_v1.HasId):
|
|||||||
value = sa.Column(sa.TEXT(65535), nullable=True)
|
value = sa.Column(sa.TEXT(65535), nullable=True)
|
||||||
|
|
||||||
|
|
||||||
class VNF(model_base.BASE, models_v1.HasId, models_v1.HasTenant):
|
class VNF(model_base.BASE, models_v1.HasId, models_v1.HasTenant,
|
||||||
|
models_v1.Audit):
|
||||||
"""Represents devices that hosts services.
|
"""Represents devices that hosts services.
|
||||||
|
|
||||||
Here the term, 'VM', is intentionally avoided because it can be
|
Here the term, 'VM', is intentionally avoided because it can be
|
||||||
@ -181,7 +185,8 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin):
|
|||||||
template.service_types)
|
template.service_types)
|
||||||
}
|
}
|
||||||
key_list = ('id', 'tenant_id', 'name', 'description',
|
key_list = ('id', 'tenant_id', 'name', 'description',
|
||||||
'infra_driver', 'mgmt_driver')
|
'infra_driver', 'mgmt_driver',
|
||||||
|
'created_at', 'updated_at')
|
||||||
res.update((key, template[key]) for key in key_list)
|
res.update((key, template[key]) for key in key_list)
|
||||||
return self._fields(res, fields)
|
return self._fields(res, fields)
|
||||||
|
|
||||||
@ -198,7 +203,7 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin):
|
|||||||
}
|
}
|
||||||
key_list = ('id', 'tenant_id', 'name', 'description', 'instance_id',
|
key_list = ('id', 'tenant_id', 'name', 'description', 'instance_id',
|
||||||
'vim_id', 'placement_attr', 'vnfd_id', 'status',
|
'vim_id', 'placement_attr', 'vnfd_id', 'status',
|
||||||
'mgmt_url', 'error_reason')
|
'mgmt_url', 'error_reason', 'created_at', 'updated_at')
|
||||||
res.update((key, device_db[key]) for key in key_list)
|
res.update((key, device_db[key]) for key in key_list)
|
||||||
return self._fields(res, fields)
|
return self._fields(res, fields)
|
||||||
|
|
||||||
@ -269,6 +274,7 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin):
|
|||||||
template_db = self._get_resource(context, VNFD,
|
template_db = self._get_resource(context, VNFD,
|
||||||
device_template_id)
|
device_template_id)
|
||||||
template_db.update(device_template['device_template'])
|
template_db.update(device_template['device_template'])
|
||||||
|
template_db.update({'updated_at': timeutils.utcnow()})
|
||||||
return self._make_template_dict(template_db)
|
return self._make_template_dict(template_db)
|
||||||
|
|
||||||
def delete_device_template(self, context, device_template_id):
|
def delete_device_template(self, context, device_template_id):
|
||||||
@ -435,6 +441,11 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin):
|
|||||||
filter(VNF.id == device_id).
|
filter(VNF.id == device_id).
|
||||||
filter(VNF.status == constants.PENDING_UPDATE).
|
filter(VNF.status == constants.PENDING_UPDATE).
|
||||||
update({'status': new_status}))
|
update({'status': new_status}))
|
||||||
|
(self._model_query(context, VNF).
|
||||||
|
filter(VNF.id == device_id).
|
||||||
|
filter(VNF.status == constants.PENDING_UPDATE).
|
||||||
|
update({'status': new_status,
|
||||||
|
'updated_at': timeutils.utcnow()}))
|
||||||
|
|
||||||
dev_attrs = new_device_dict.get('attributes', {})
|
dev_attrs = new_device_dict.get('attributes', {})
|
||||||
(context.session.query(VNFAttribute).
|
(context.session.query(VNFAttribute).
|
||||||
|
@ -160,6 +160,16 @@ RESOURCE_ATTRIBUTE_MAP = {
|
|||||||
'is_visible': True,
|
'is_visible': True,
|
||||||
'default': False
|
'default': False
|
||||||
},
|
},
|
||||||
|
'created_at': {
|
||||||
|
'allow_post': False,
|
||||||
|
'allow_put': False,
|
||||||
|
'is_visible': True,
|
||||||
|
},
|
||||||
|
'updated_at': {
|
||||||
|
'allow_post': False,
|
||||||
|
'allow_put': False,
|
||||||
|
'is_visible': True,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,6 +224,16 @@ RESOURCE_ATTRIBUTE_MAP = {
|
|||||||
'is_visible': True,
|
'is_visible': True,
|
||||||
'default': None,
|
'default': None,
|
||||||
},
|
},
|
||||||
|
'created_at': {
|
||||||
|
'allow_post': False,
|
||||||
|
'allow_put': False,
|
||||||
|
'is_visible': True,
|
||||||
|
},
|
||||||
|
'updated_at': {
|
||||||
|
'allow_post': False,
|
||||||
|
'allow_put': False,
|
||||||
|
'is_visible': True,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
'vnfs': {
|
'vnfs': {
|
||||||
@ -303,6 +313,16 @@ RESOURCE_ATTRIBUTE_MAP = {
|
|||||||
'allow_put': False,
|
'allow_put': False,
|
||||||
'is_visible': True,
|
'is_visible': True,
|
||||||
},
|
},
|
||||||
|
'created_at': {
|
||||||
|
'allow_post': False,
|
||||||
|
'allow_put': False,
|
||||||
|
'is_visible': True,
|
||||||
|
},
|
||||||
|
'updated_at': {
|
||||||
|
'allow_post': False,
|
||||||
|
'allow_put': False,
|
||||||
|
'is_visible': True,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,6 +88,8 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
|||||||
self.assertEqual(SECRET_PASSWORD, res['auth_cred']['password'])
|
self.assertEqual(SECRET_PASSWORD, res['auth_cred']['password'])
|
||||||
self.assertIn('id', res)
|
self.assertIn('id', res)
|
||||||
self.assertIn('placement_attr', res)
|
self.assertIn('placement_attr', res)
|
||||||
|
self.assertIn('created_at', res)
|
||||||
|
self.assertIn('updated_at', res)
|
||||||
|
|
||||||
def test_delete_vim(self):
|
def test_delete_vim(self):
|
||||||
self._insert_dummy_vim()
|
self._insert_dummy_vim()
|
||||||
@ -118,3 +120,4 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
|||||||
self.assertEqual(vim_project, res['vim_project'])
|
self.assertEqual(vim_project, res['vim_project'])
|
||||||
self.assertEqual(vim_auth_username, res['auth_cred']['username'])
|
self.assertEqual(vim_auth_username, res['auth_cred']['username'])
|
||||||
self.assertEqual(SECRET_PASSWORD, res['auth_cred']['password'])
|
self.assertEqual(SECRET_PASSWORD, res['auth_cred']['password'])
|
||||||
|
self.assertIn('updated_at', res)
|
||||||
|
@ -152,6 +152,8 @@ class TestVNFMPlugin(db_base.SqlTestCase):
|
|||||||
self.assertIn('id', result)
|
self.assertIn('id', result)
|
||||||
self.assertIn('service_types', result)
|
self.assertIn('service_types', result)
|
||||||
self.assertIn('attributes', result)
|
self.assertIn('attributes', result)
|
||||||
|
self.assertIn('created_at', result)
|
||||||
|
self.assertIn('updated_at', result)
|
||||||
self._device_manager.invoke.assert_called_once_with(
|
self._device_manager.invoke.assert_called_once_with(
|
||||||
mock.ANY,
|
mock.ANY,
|
||||||
mock.ANY,
|
mock.ANY,
|
||||||
@ -183,6 +185,8 @@ class TestVNFMPlugin(db_base.SqlTestCase):
|
|||||||
self.assertIn('status', result)
|
self.assertIn('status', result)
|
||||||
self.assertIn('attributes', result)
|
self.assertIn('attributes', result)
|
||||||
self.assertIn('mgmt_url', result)
|
self.assertIn('mgmt_url', result)
|
||||||
|
self.assertIn('created_at', result)
|
||||||
|
self.assertIn('updated_at', result)
|
||||||
self._device_manager.invoke.assert_called_with(mock.ANY, mock.ANY,
|
self._device_manager.invoke.assert_called_with(mock.ANY, mock.ANY,
|
||||||
plugin=mock.ANY,
|
plugin=mock.ANY,
|
||||||
context=mock.ANY,
|
context=mock.ANY,
|
||||||
@ -217,5 +221,6 @@ class TestVNFMPlugin(db_base.SqlTestCase):
|
|||||||
self.assertIn('status', result)
|
self.assertIn('status', result)
|
||||||
self.assertIn('attributes', result)
|
self.assertIn('attributes', result)
|
||||||
self.assertIn('mgmt_url', result)
|
self.assertIn('mgmt_url', result)
|
||||||
|
self.assertIn('updated_at', result)
|
||||||
self._pool.spawn_n.assert_called_once_with(mock.ANY, mock.ANY,
|
self._pool.spawn_n.assert_called_once_with(mock.ANY, mock.ANY,
|
||||||
mock.ANY, mock.ANY)
|
mock.ANY, mock.ANY)
|
||||||
|
Loading…
Reference in New Issue
Block a user