Fix execute db_manager init failed

Previously, `db_manager init` command failed because pbr generated
script will not pass sys.argv as argument to main function. So fix
it.

And improve etcd_db.init_etcd_db to make it check whether each
directory already exists in etcd at first. If it exist and it's not
directory, delete and re-create it.

Change-Id: I7d9980e0a1b38d988fe8144d0cbd618ac12f5498
Closes-Bug: #1654638
This commit is contained in:
Lin Yang 2017-01-06 15:55:50 -08:00
parent 6e77f11e4c
commit 6e49e5a1fb
4 changed files with 101 additions and 7 deletions

View File

@ -55,7 +55,12 @@ Valence installation
6. Initialize etcd database 6. Initialize etcd database
``$ sudo db_manager init`` ``$ db_manager init``
Note: The TypeError exception "TypeError: NoneType object is not callable"
is caused by known python-etcd bug, which will not impact this db init
functionality.
https://github.com/jplana/python-etcd/issues/190
7. Start valence service 7. Start valence service

10
valence/cmd/db_manager.py Normal file → Executable file
View File

@ -16,24 +16,24 @@
import logging import logging
import sys import sys
from valence.db.etcd_db import init_etcd_db from valence.db import etcd_db
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
def init(): def init():
init_etcd_db() etcd_db.init_etcd_db()
def migrate(): def migrate():
pass pass
def main(argv): def main():
if argv[1] == 'init': if sys.argv[1] == 'init':
LOG.info("initialize database") LOG.info("initialize database")
init() init()
if __name__ == '__main__': if __name__ == '__main__':
main(sys.argv) sys.exit(main())

View File

@ -12,7 +12,6 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import etcd import etcd
from valence import config from valence import config
@ -29,4 +28,16 @@ etcd_client = etcd.Client(config.etcd_host, config.etcd_port)
def init_etcd_db(): def init_etcd_db():
"""initialize etcd database""" """initialize etcd database"""
for directory in etcd_directories: for directory in etcd_directories:
try:
if not etcd_client.read(directory).dir:
# This directory name already exists, but is regular file, not
# directory, so delete it.
etcd_client.delete(directory)
else:
# This directory already exists, so skip
continue
except etcd.EtcdKeyNotFound:
# This directory name don't exist
pass
etcd_client.write(directory, None, dir=True, append=True) etcd_client.write(directory, None, dir=True, append=True)

View File

@ -0,0 +1,78 @@
# copyright (c) 2016 Intel, Inc.
#
# 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
import unittest
import etcd
from valence.db import etcd_db
class TestDBInit(unittest.TestCase):
def setUp(self):
self.backup_directories = etcd_db.etcd_directories
etcd_db.etcd_directories = ['/test']
def tearDown(self):
etcd_db.etcd_directories = self.backup_directories
@mock.patch('etcd.Client.delete')
@mock.patch('etcd.Client.write')
@mock.patch('etcd.Client.read')
def test_init_db(self, mock_etcd_read, mock_etcd_write, mock_etcd_delete):
"""Test init DB when no corresponding dir exists"""
# Directory don't exist in etcd db
mock_etcd_read.side_effect = etcd.EtcdKeyNotFound
etcd_db.init_etcd_db()
mock_etcd_read.assert_called_with('/test')
mock_etcd_write.assert_called_with(
'/test', None, dir=True, append=True)
mock_etcd_delete.assert_not_called()
@mock.patch('etcd.Client.delete')
@mock.patch('etcd.Client.write')
@mock.patch('etcd.Client.read')
def test_init_db_with_existing_key(self, mock_etcd_read, mock_etcd_write,
mock_etcd_delete):
"""Test init DB when a regular key with same name already exists"""
# A regular key with same name already exists
mock_etcd_read.return_value = mock.Mock(dir=False)
etcd_db.init_etcd_db()
mock_etcd_read.assert_called_with('/test')
mock_etcd_write.assert_called_with(
'/test', None, dir=True, append=True)
mock_etcd_delete.assert_called_with('/test')
@mock.patch('etcd.Client.delete')
@mock.patch('etcd.Client.write')
@mock.patch('etcd.Client.read')
def test_init_db_with_existing_dir(self, mock_etcd_read, mock_etcd_write,
mock_etcd_delete):
"""Test init DB when a dir with same name already exists"""
# A dir with same name already exists
mock_etcd_read.return_value = mock.Mock(dir=True)
etcd_db.init_etcd_db()
mock_etcd_read.assert_called_with('/test')
mock_etcd_write.assert_not_called()
mock_etcd_delete.assert_not_called()