Change the gate to OpenStack infrastrucure

Change the gate to OpenStack infrastrcuture and update the README.md
to reflect the work on the stateless design proposal and branch.

BP: https://blueprints.launchpad.net/tricircle/+spec/new-design

Change-Id: I51accdf33d8d9e50774c16d7649975ca91c2f5ec
Signed-off-by: Chaoyi Huang <joehuang@huawei.com>
This commit is contained in:
Chaoyi Huang 2015-12-11 15:29:10 +08:00
parent 57f0ddbf91
commit bfc6a83048
13 changed files with 379 additions and 63 deletions

88
.gitignore vendored
View File

@ -1,45 +1,53 @@
*.DS_Store *.py[cod]
*.egg*
*.log # C extensions
*.mo *.so
*.pyc
*.swo # Packages
*.swp *.egg
*.sqlite *.egg-info
*.iml dist
*~ build
.autogenerated eggs
parts
var
sdist
develop-eggs
.installed.cfg
lib
lib64
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage .coverage
.nova-venv .tox
nosetests.xml
.testrepository
.venv
# Translations
*.mo
# Mr Developer
.mr.developer.cfg
.project .project
.pydevproject .pydevproject
.ropeproject
.testrepository/ # Complexity
.tox output/*.html
.idea output/*/index.html
.venv
# Sphinx
doc/build
# pbr generates these
AUTHORS AUTHORS
Authors
build-stamp
build/*
CA/
ChangeLog ChangeLog
coverage.xml
cover/* # Editors
covhtml *~
dist/* .*.swp
doc/source/api/* .*sw?
doc/build/*
etc/nova/nova.conf.sample
instances
keeper
keys
local_settings.py
MANIFEST
nosetests.xml
nova/tests/cover/*
nova/vcsversion.py
tools/conf/nova.conf*
tools/lintstack.head.py
tools/pylint_exceptions
etc/nova/nova.conf.sample

7
.testr.conf Normal file
View File

@ -0,0 +1,7 @@
[DEFAULT]
test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \
OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \
${PYTHON:-python} -m subunit.run discover -t ./ . $LISTOPT $IDOPTION
test_id_option=--load-list $IDFILE
test_list_option=--list

View File

@ -1,6 +1,8 @@
# Tricircle # Tricircle
(For PoC source code, please switch to ["poc"](https://github.com/openstack/tricircle/tree/poc) tag, or ["stable/fortest"](https://github.com/openstack/tricircle/tree/stable/fortest) branch) (Attention Please, Stateless Design Proposal is being worked on the ["experiment"](https://github.com/openstack/tricircle/tree/experiment) branch).
(The origningal PoC source code, please switch to ["poc"](https://github.com/openstack/tricircle/tree/poc) tag, or ["stable/fortest"](https://github.com/openstack/tricircle/tree/stable/fortest) branch)
Tricircle is a openstack project that aims to deal with OpenStack deployment across multiple sites. It provides users a single management view by having only one OpenStack instance on behalf of all the involved ones. It essentially serves as a communication bus between the central OpenStack instance and the other OpenStack instances that are called upon. Tricircle is a openstack project that aims to deal with OpenStack deployment across multiple sites. It provides users a single management view by having only one OpenStack instance on behalf of all the involved ones. It essentially serves as a communication bus between the central OpenStack instance and the other OpenStack instances that are called upon.

75
doc/source/conf.py Executable file
View File

@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-
# 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 os
import sys
sys.path.insert(0, os.path.abspath('../..'))
# -- General configuration ----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = [
'sphinx.ext.autodoc',
# 'sphinx.ext.intersphinx',
'oslosphinx'
]
# autodoc generation is a bit aggressive and a nuisance when doing heavy
# text edit cycles.
# execute "export SPHINX_DEBUG=1" in your terminal to disable
# The suffix of source filenames.
source_suffix = '.rst'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'tricircle'
copyright = u'2015, OpenStack Foundation'
# If true, '()' will be appended to :func: etc. cross-reference text.
add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
add_module_names = True
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# -- Options for HTML output --------------------------------------------------
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
# html_theme_path = ["."]
# html_theme = '_theme'
# html_static_path = ['static']
# Output file base name for HTML help builder.
htmlhelp_basename = '%sdoc' % project
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass
# [howto/manual]).
latex_documents = [
('index',
'%s.tex' % project,
u'%s Documentation' % project,
u'OpenStack Foundation', 'manual'),
]
# Example configuration for intersphinx: refer to the Python standard library.
# intersphinx_mapping = {'http://docs.python.org/': None}

21
doc/source/index.rst Normal file
View File

@ -0,0 +1,21 @@
.. tricircle documentation master file, created by
sphinx-quickstart on Wed Dec 2 17:00:36 2015.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to tricircle's documentation!
========================================================
Contents:
.. toctree::
:maxdepth: 2
api_v1
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View File

@ -1,7 +1,8 @@
# The order of packages is significant, because pip processes them in the order # The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration # of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later. # process, which may cause wedges in the gate later.
pbr<2.0,>=1.3 pbr>=1.6
Babel>=1.3
Paste Paste
PasteDeploy>=1.5.0 PasteDeploy>=1.5.0
@ -9,30 +10,37 @@ Routes!=2.0,!=2.1,>=1.12.3;python_version=='2.7'
Routes!=2.0,>=1.12.3;python_version!='2.7' Routes!=2.0,>=1.12.3;python_version!='2.7'
debtcollector>=0.3.0 # Apache-2.0 debtcollector>=0.3.0 # Apache-2.0
eventlet>=0.17.4 eventlet>=0.17.4
pecan>=0.9.0 pecan>=1.0.0
greenlet>=0.3.2 greenlet>=0.3.2
httplib2>=0.7.5 httplib2>=0.7.5
requests>=2.5.2 requests>=2.8.1
Jinja2>=2.6 # BSD License (3 clause) Jinja2>=2.8 # BSD License (3 clause)
keystonemiddleware>=2.0.0 keystonemiddleware>=4.0.0
netaddr>=0.7.12 netaddr!=0.7.16,>=0.7.12
netifaces>=0.10.4
retrying!=1.3.0,>=1.2.3 # Apache-2.0 retrying!=1.3.0,>=1.2.3 # Apache-2.0
SQLAlchemy<1.1.0,>=0.9.7 SQLAlchemy<1.1.0,>=0.9.9
WebOb>=1.2.3 WebOb>=1.2.3
python-keystoneclient>=1.6.0 python-cinderclient>=1.3.1
alembic>=0.7.2 python-glanceclient>=0.18.0
python-keystoneclient!=1.8.0,>=1.6.0
python-neutronclient>=2.6.0
python-novaclient>=2.29.0,!=2.33.0
alembic>=0.8.0
six>=1.9.0 six>=1.9.0
stevedore>=1.5.0 # Apache-2.0 stevedore>=1.5.0 # Apache-2.0
oslo.concurrency>=2.1.0 # Apache-2.0 oslo.concurrency>=2.3.0 # Apache-2.0
oslo.config>=1.11.0 # Apache-2.0 oslo.config>=2.7.0 # Apache-2.0
oslo.context>=0.2.0 # Apache-2.0 oslo.context>=0.2.0 # Apache-2.0
oslo.db>=1.12.0 # Apache-2.0 oslo.db>=4.1.0 # Apache-2.0
oslo.i18n>=1.5.0 # Apache-2.0 oslo.i18n>=1.5.0 # Apache-2.0
oslo.log>=1.6.0 # Apache-2.0 oslo.log>=1.12.0 # Apache-2.0
oslo.messaging>=1.16.0 # Apache-2.0 oslo.messaging!=2.8.0,!=3.1.0,>2.6.1 # Apache-2.0
oslo.middleware>=2.4.0 # Apache-2.0 oslo.middleware>=3.0.0 # Apache-2.0
oslo.policy>=0.5.0 # Apache-2.0 oslo.policy>=0.5.0 # Apache-2.0
oslo.rootwrap>=2.0.0 # Apache-2.0 oslo.rootwrap>=2.0.0 # Apache-2.0
oslo.serialization>=1.4.0 # Apache-2.0 oslo.serialization>=1.10.0 # Apache-2.0
oslo.service>=0.1.0 # Apache-2.0 oslo.service>=1.0.0 # Apache-2.0
oslo.utils>=1.9.0 # Apache-2.0 oslo.utils!=3.1.0,>=2.8.0 # Apache-2.0
oslo.versionedobjects>=0.13.0
sqlalchemy-migrate>=0.9.6

48
setup.cfg Normal file
View File

@ -0,0 +1,48 @@
[metadata]
name = tricircle
summary = Tricircle is an OpenStack project that aims to deal with OpenStack deployment across multiple sites.
description-file =
README.md
author = OpenStack
author-email = openstack-dev@lists.openstack.org
home-page = http://www.openstack.org/
classifier =
Environment :: OpenStack
Intended Audience :: Information Technology
Intended Audience :: System Administrators
License :: OSI Approved :: Apache Software License
Operating System :: POSIX :: Linux
Programming Language :: Python
Programming Language :: Python :: 2
Programming Language :: Python :: 2.7
Programming Language :: Python :: 3
Programming Language :: Python :: 3.3
Programming Language :: Python :: 3.4
[files]
packages =
tricircle
[build_sphinx]
source-dir = doc/source
build-dir = doc/build
all_files = 1
[upload_sphinx]
upload-dir = doc/build/html
[compile_catalog]
directory = tricircle/locale
domain = tricircle
[update_catalog]
domain = tricircle
output_dir = tricircle/locale
input_file = tricircle/locale/tricircle.pot
[extract_messages]
keywords = _ gettext ngettext l_ lazy_gettext
mapping_file = babel.cfg
output_file = tricircle/locale/tricircle.pot
[entry_points]

29
setup.py Normal file
View File

@ -0,0 +1,29 @@
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
#
# 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.
# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
import setuptools
# In python < 2.7.4, a lazy loading of package `pbr` will break
# setuptools if some other modules registered functions in `atexit`.
# solution from: http://bugs.python.org/issue15881#msg170215
try:
import multiprocessing # noqa
except ImportError:
pass
setuptools.setup(
setup_requires=['pbr'],
pbr=True)

23
test-requirements.txt Normal file
View File

@ -0,0 +1,23 @@
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
hacking<0.11,>=0.10.2
cliff>=1.15.0 # Apache-2.0
coverage>=3.6
fixtures>=1.3.1
mock>=1.2
python-subunit>=0.0.18
requests-mock>=0.7.0 # Apache-2.0
sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2
oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0
testrepository>=0.0.18
testtools>=1.4.0
testresources>=0.2.4
testscenarios>=0.4
WebTest>=2.0
oslotest>=1.10.0 # Apache-2.0
os-testr>=0.4.1
tempest-lib>=0.11.0
ddt>=1.0.1
pylint==1.4.5 # GNU GPL v2

43
tox.ini Normal file
View File

@ -0,0 +1,43 @@
[tox]
minversion = 1.6
envlist = py34,py27,pypy,pep8
skipsdist = True
[testenv]
sitepackages = True
usedevelop = True
install_command =
pip install -U --force-reinstall {opts} {packages}
setenv =
VIRTUAL_ENV={envdir}
deps =
-egit+https://git.openstack.org/openstack/neutron@master#egg=neutron
-r{toxinidir}/test-requirements.txt
commands = python setup.py testr --slowest --testr-args='{posargs}'
whitelist_externals = rm
[testenv:common-constraints]
install_command = {toxinidir}/tools/tox_install.sh constrained -c{env:UPPER_CONTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages}
[testenv:pep8]
commands = flake8
[testenv:venv]
commands = {posargs}
[testenv:cover]
commands = python setup.py testr --coverage --testr-args='{posargs}'
[testenv:docs]
commands = python setup.py build_sphinx
[testenv:debug]
commands = oslo_debug_helper {posargs}
[flake8]
# E123, E125 skipped as they are invalid PEP-8.
show-source = True
ignore = E123,E125
builtins = _
exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build

View File

@ -20,12 +20,24 @@ import unittest
import pecan import pecan
import tricircle.api.controllers.root as root_controller import tricircle.api.controllers.root as root_controller
from tricircle.common import cascading_site_api
from tricircle.common import context from tricircle.common import context
from tricircle.common import rpc
from tricircle.db import client from tricircle.db import client
from tricircle.db import core from tricircle.db import core
from tricircle.db import models from tricircle.db import models
def fake_create_client(target):
return None
def fake_cast_message(self, context, method, payload):
return None
class ControllerTest(unittest.TestCase): class ControllerTest(unittest.TestCase):
def setUp(self): def setUp(self):
core.initialize() core.initialize()
@ -49,6 +61,9 @@ class SitesControllerTest(ControllerTest):
super(SitesControllerTest, self).setUp() super(SitesControllerTest, self).setUp()
self.controller = root_controller.SitesController() self.controller = root_controller.SitesController()
@patch.object(rpc, 'create_client', new=fake_create_client)
@patch.object(cascading_site_api.CascadingSiteNotifyAPI,
'_cast_message', new=fake_cast_message)
def test_post_top_site(self): def test_post_top_site(self):
kw = {'name': 'TopSite', 'top': True} kw = {'name': 'TopSite', 'top': True}
site_id = self.controller.post(**kw)['site']['site_id'] site_id = self.controller.post(**kw)['site']['site_id']
@ -56,6 +71,9 @@ class SitesControllerTest(ControllerTest):
self.assertEqual(site['site_name'], 'TopSite') self.assertEqual(site['site_name'], 'TopSite')
self.assertEqual(site['az_id'], '') self.assertEqual(site['az_id'], '')
@patch.object(rpc, 'create_client', new=fake_create_client)
@patch.object(cascading_site_api.CascadingSiteNotifyAPI,
'_cast_message', new=fake_cast_message)
@patch.object(client.Client, 'create_resources') @patch.object(client.Client, 'create_resources')
def test_post_bottom_site(self, mock_method): def test_post_bottom_site(self, mock_method):
kw = {'name': 'BottomSite'} kw = {'name': 'BottomSite'}
@ -66,11 +84,17 @@ class SitesControllerTest(ControllerTest):
mock_method.assert_called_once_with('aggregate', self.context, mock_method.assert_called_once_with('aggregate', self.context,
'ag_BottomSite', 'az_BottomSite') 'ag_BottomSite', 'az_BottomSite')
@patch.object(rpc, 'create_client', new=fake_create_client)
@patch.object(cascading_site_api.CascadingSiteNotifyAPI,
'_cast_message', new=fake_cast_message)
def test_post_site_name_missing(self): def test_post_site_name_missing(self):
kw = {'top': True} kw = {'top': True}
self.controller.post(**kw) self.controller.post(**kw)
pecan.abort.assert_called_once_with(400, 'Name of site required') pecan.abort.assert_called_once_with(400, 'Name of site required')
@patch.object(rpc, 'create_client', new=fake_create_client)
@patch.object(cascading_site_api.CascadingSiteNotifyAPI,
'_cast_message', new=fake_cast_message)
def test_post_conflict(self): def test_post_conflict(self):
kw = {'name': 'TopSite', 'top': True} kw = {'name': 'TopSite', 'top': True}
self.controller.post(**kw) self.controller.post(**kw)
@ -78,6 +102,9 @@ class SitesControllerTest(ControllerTest):
pecan.abort.assert_called_once_with(409, pecan.abort.assert_called_once_with(409,
'Site with name TopSite exists') 'Site with name TopSite exists')
@patch.object(rpc, 'create_client', new=fake_create_client)
@patch.object(cascading_site_api.CascadingSiteNotifyAPI,
'_cast_message', new=fake_cast_message)
def test_post_not_admin(self): def test_post_not_admin(self):
self.context.is_admin = False self.context.is_admin = False
kw = {'name': 'TopSite', 'top': True} kw = {'name': 'TopSite', 'top': True}
@ -85,6 +112,9 @@ class SitesControllerTest(ControllerTest):
pecan.abort.assert_called_once_with( pecan.abort.assert_called_once_with(
400, 'Admin role required to create sites') 400, 'Admin role required to create sites')
@patch.object(rpc, 'create_client', new=fake_create_client)
@patch.object(cascading_site_api.CascadingSiteNotifyAPI,
'_cast_message', new=fake_cast_message)
@patch.object(client.Client, 'create_resources') @patch.object(client.Client, 'create_resources')
def test_post_decide_top(self, mock_method): def test_post_decide_top(self, mock_method):
# 'top' default to False # 'top' default to False
@ -100,6 +130,9 @@ class SitesControllerTest(ControllerTest):
'az_Site%d' % i) for i in xrange(2, 4)] 'az_Site%d' % i) for i in xrange(2, 4)]
mock_method.assert_has_calls(calls) mock_method.assert_has_calls(calls)
@patch.object(rpc, 'create_client', new=fake_create_client)
@patch.object(cascading_site_api.CascadingSiteNotifyAPI,
'_cast_message', new=fake_cast_message)
@patch.object(models, 'create_site') @patch.object(models, 'create_site')
def test_post_create_site_exception(self, mock_method): def test_post_create_site_exception(self, mock_method):
mock_method.side_effect = Exception mock_method.side_effect = Exception
@ -121,6 +154,9 @@ class SitesControllerTest(ControllerTest):
sites = models.list_sites(self.context, site_filter) sites = models.list_sites(self.context, site_filter)
self.assertEqual(len(sites), 0) self.assertEqual(len(sites), 0)
@patch.object(rpc, 'create_client', new=fake_create_client)
@patch.object(cascading_site_api.CascadingSiteNotifyAPI,
'_cast_message', new=fake_cast_message)
def test_get_one(self): def test_get_one(self):
kw = {'name': 'TopSite', 'top': True} kw = {'name': 'TopSite', 'top': True}
site_id = self.controller.post(**kw)['site']['site_id'] site_id = self.controller.post(**kw)['site']['site_id']
@ -129,11 +165,17 @@ class SitesControllerTest(ControllerTest):
'site_name': 'TopSite', 'site_name': 'TopSite',
'az_id': ''}) 'az_id': ''})
@patch.object(rpc, 'create_client', new=fake_create_client)
@patch.object(cascading_site_api.CascadingSiteNotifyAPI,
'_cast_message', new=fake_cast_message)
def test_get_one_not_found(self): def test_get_one_not_found(self):
self.controller.get_one('fake_id') self.controller.get_one('fake_id')
pecan.abort.assert_called_once_with(404, pecan.abort.assert_called_once_with(404,
'Site with id fake_id not found') 'Site with id fake_id not found')
@patch.object(rpc, 'create_client', new=fake_create_client)
@patch.object(cascading_site_api.CascadingSiteNotifyAPI,
'_cast_message', new=fake_cast_message)
@patch.object(client.Client, 'create_resources', new=mock.Mock) @patch.object(client.Client, 'create_resources', new=mock.Mock)
def test_get_all(self): def test_get_all(self):
kw1 = {'name': 'TopSite', 'top': True} kw1 = {'name': 'TopSite', 'top': True}

View File

@ -45,6 +45,11 @@ def fake_update_port(instance, context, port_id, port):
return FAKE_PORT return FAKE_PORT
class FakePlugin(TricirclePlugin):
def __init__(self):
pass
class TricirclePluginTest(unittest.TestCase): class TricirclePluginTest(unittest.TestCase):
def setUp(self): def setUp(self):
FAKE_PORT['status'] = neutron_const.PORT_STATUS_DOWN FAKE_PORT['status'] = neutron_const.PORT_STATUS_DOWN
@ -55,7 +60,7 @@ class TricirclePluginTest(unittest.TestCase):
@patch.object(db_base_plugin_v2.NeutronDbPluginV2, @patch.object(db_base_plugin_v2.NeutronDbPluginV2,
'get_port', new=fake_get_port) 'get_port', new=fake_get_port)
def test_update_port_status(self): def test_update_port_status(self):
plugin = TricirclePlugin() plugin = FakePlugin()
# this method requires a neutron context, but for test we just pass # this method requires a neutron context, but for test we just pass
# a tricircle context # a tricircle context
port = plugin.update_port_status(context.Context(), FAKE_PORT_ID, port = plugin.update_port_status(context.Context(), FAKE_PORT_ID,
@ -69,7 +74,7 @@ class TricirclePluginTest(unittest.TestCase):
@patch.object(db_base_plugin_v2.NeutronDbPluginV2, @patch.object(db_base_plugin_v2.NeutronDbPluginV2,
'get_port', new=fake_get_port) 'get_port', new=fake_get_port)
def test_update_port_status_port_not_found(self): def test_update_port_status_port_not_found(self):
plugin = TricirclePlugin() plugin = FakePlugin()
port = plugin.update_port_status(context.Context(), 'no_such_port', port = plugin.update_port_status(context.Context(), 'no_such_port',
neutron_const.PORT_STATUS_ACTIVE) neutron_const.PORT_STATUS_ACTIVE)
self.assertEqual(FAKE_PORT['status'], neutron_const.PORT_STATUS_DOWN) self.assertEqual(FAKE_PORT['status'], neutron_const.PORT_STATUS_DOWN)

View File

@ -29,6 +29,11 @@ FAKE_PORT_ID = 'fake_port_uuid'
FAKE_CONTEXT = object() FAKE_CONTEXT = object()
class FakePlugin(plugin.TricirclePlugin):
def __init__(self):
pass
class RpcCallbacksTest(unittest.TestCase): class RpcCallbacksTest(unittest.TestCase):
def setUp(self): def setUp(self):
self.callbacks = rpc.RpcCallbacks() self.callbacks = rpc.RpcCallbacks()
@ -39,7 +44,7 @@ class RpcCallbacksTest(unittest.TestCase):
'get_plugin') as get_plugin_method: 'get_plugin') as get_plugin_method:
with patch.object(plugin.TricirclePlugin, with patch.object(plugin.TricirclePlugin,
'update_port_status') as update_method: 'update_port_status') as update_method:
get_plugin_method.return_value = plugin.TricirclePlugin() get_plugin_method.return_value = FakePlugin()
self.callbacks.update_port_up(FAKE_CONTEXT, self.callbacks.update_port_up(FAKE_CONTEXT,
port_id=FAKE_PORT_ID) port_id=FAKE_PORT_ID)
update_method.assert_called_once_with( update_method.assert_called_once_with(
@ -52,7 +57,7 @@ class RpcCallbacksTest(unittest.TestCase):
'get_plugin') as get_plugin_method: 'get_plugin') as get_plugin_method:
with patch.object(plugin.TricirclePlugin, with patch.object(plugin.TricirclePlugin,
'update_port_status') as update_method: 'update_port_status') as update_method:
get_plugin_method.return_value = plugin.TricirclePlugin() get_plugin_method.return_value = FakePlugin()
self.callbacks.update_port_down(FAKE_CONTEXT, self.callbacks.update_port_down(FAKE_CONTEXT,
port_id=FAKE_PORT_ID) port_id=FAKE_PORT_ID)
update_method.assert_called_once_with( update_method.assert_called_once_with(