Upload the latest networking-zvm

Upload the latest networking-zvm, with configuration files

Change-Id: Iadc04202c3530cdd0c24fc74c4960f8dab56b3a9
changes/24/179724/1
Huang Rui 8 years ago
parent 36283042a8
commit a3b7f66b43
  1. 19
      .gitignore
  2. 4
      .gitreview
  3. 9
      .testr.conf
  4. 1
      README.rst
  5. 25
      bin/neutron-zvm-agent
  6. 284
      doc/source/conf.py
  7. 20
      doc/source/index.rst
  8. 110
      etc/neutron/plugins/zvm/neutron_zvm_plugin.ini.sample
  9. 97
      etc/rc.d/init.d/neutron-zvm-agent
  10. 0
      neutron/plugins/ml2/drivers/zvm/__init__.py
  11. 54
      neutron/plugins/ml2/drivers/zvm/mech_zvm.py
  12. 0
      neutron/plugins/zvm/__init__.py
  13. 0
      neutron/plugins/zvm/agent/__init__.py
  14. 19
      neutron/plugins/zvm/agent/zvm_network.py
  15. 80
      neutron/plugins/zvm/agent/zvm_neutron_agent.py
  16. 0
      neutron/plugins/zvm/common/__init__.py
  17. 12
      neutron/plugins/zvm/common/config.py
  18. 2
      neutron/plugins/zvm/common/constants.py
  19. 8
      neutron/plugins/zvm/common/exception.py
  20. 177
      neutron/plugins/zvm/common/utils.py
  21. 40
      neutron/plugins/zvm/common/xcatutils.py
  22. 0
      neutron/tests/unit/plugins/__init__.py
  23. 0
      neutron/tests/unit/plugins/ml2/__init__.py
  24. 0
      neutron/tests/unit/plugins/ml2/zvm/__init__.py
  25. 77
      neutron/tests/unit/plugins/ml2/zvm/test_mech_zvm.py
  26. 0
      neutron/tests/unit/plugins/zvm/__init__.py
  27. 11
      neutron/tests/unit/plugins/zvm/test_zvm_network.py
  28. 44
      neutron/tests/unit/plugins/zvm/test_zvm_neutron_agent.py
  29. 304
      neutron/tests/unit/plugins/zvm/test_zvm_utils.py
  30. 4
      neutron/tests/unit/plugins/zvm/test_zvm_xcatutils.py
  31. 4
      requirements.txt
  32. 58
      setup.cfg
  33. 9
      setup.py
  34. 13
      test-requirements.txt
  35. 21
      tools/build_rpm.sh
  36. 6
      tools/post_install
  37. 3
      tools/post_uninstall
  38. 4
      tools/pre_uninstall
  39. 44
      tox.ini

19
.gitignore vendored

@ -0,0 +1,19 @@
*.log
*.pyc
.autogenerated
.coverage
.project
.pydevproject
.settings
.testrepository
.tox
.venv
AUTHORS
build/
ChangeLog
coverage.xml
cover/*
covhtml
dist/
doc/build/
neutron_zvm_plugin.egg-info/

@ -0,0 +1,4 @@
[gerrit]
host=review.openstack.org
port=29418
project=stackforge/networking-zvm.git

@ -0,0 +1,9 @@
[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 ./neutron/tests/unit/plugins/ ./neutron/tests/unit/plugins \
$LISTOPT $IDOPTION
test_id_option=--load-list $IDFILE
test_list_option=--list

@ -0,0 +1 @@
TODO (rui): Add readme

@ -0,0 +1,25 @@
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2013 IBM 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 os
import sys
sys.path.insert(0, os.getcwd())
from neutron.plugins.zvm.agent.zvm_neutron_agent import main
main()

@ -0,0 +1,284 @@
# -*- coding: utf-8 -*-
#
# networking-zvm documentation build configuration file, created by
# sphinx-quickstart on Tue Apr 14 15:27:57 2015.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys
import os
import shlex
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ['oslosphinx']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['.templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'networking-zvm'
copyright = u'2015, IBM'
author = u'IBM'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '2015.1'
# The full version, including alpha/beta/rc tags.
release = '2015.1'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = []
# The reST default role (used for this markup: `text`) to use for all
# documents.
#default_role = None
# 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
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'alabaster'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['.static']
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#html_extra_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Language to be used for generating the HTML full-text search index.
# Sphinx supports the following languages:
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
#html_search_language = 'en'
# A dictionary with options for the search language support, empty by default.
# Now only 'ja' uses this config value
#html_search_options = {'type': 'default'}
# The name of a javascript file (relative to the configuration directory) that
# implements a search results scorer. If empty, the default will be used.
#html_search_scorer = 'scorer.js'
# Output file base name for HTML help builder.
htmlhelp_basename = 'networking-zvm-doc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
# Latex figure (float) alignment
#'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'networking-zvm.tex', u'networking-zvm Documentation',
u'IBM', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'networking-zvm', u'networking-zvm Documentation',
[author], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'networking-zvm', u'networking-zvm Documentation',
author, 'networking-zvm', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False

@ -0,0 +1,20 @@
Welcome to networking-zvm's documentation!
==============================================
This project implements Neutron ML2 zvm mechnism driver and zvm network
agent.
Contents:
.. toctree::
:maxdepth: 2
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

@ -0,0 +1,110 @@
[AGENT]
# (StrOpt) xCat REST API username, default value is admin.
# zvm_xcat_username = admin
# Example: zvm_xcat_username = guest
# (StrOpt) Password of the xCat REST API user, default value is admin
# zvm_xcat_password = admin
# Example: zvm_xcat_password = passw0rd
# (StrOpt) xCat MN server address, IP address or host name
# zvm_xcat_server = YourxCATMNServerAddress
# Example: zvm_xcat_server = 10.0.0.1
# (StrOpt) xCat zHCP nodename in xCAT, default value is zhcp
# xcat_zhcp_nodename = zhcp
# Example: xcat_zhcp_nodename = myzhcp1
# (StrOpt) The compute node name neutron-zvm-agent work on, same as 'host'in nova.conf
# This property is optional. If it is not specified, 'host' in neutron.conf will be
# used. Moreover, 'host' in neutron.conf is recommended and this property is deprecated.
# zvm_host = opnstk1
# Example: zvm_host = opnstk1
# (IntOpt) Agent's polling interval in seconds, default value is 2 seconds
# polling_interval = 2
# Example: polling_interval = 5
# (IntOpt) The number of seconds the agent will wait for
# xCAT MN response, default value is 300 seconds
# zvm_xcat_timeout = 300
# Example: zvm_xcat_timeout = 600
# (StrOpt ) xcat management NIC IP.
# xcat_mgt_ip = 10.1.0.1
# Example: xcat_mgt_ip=10.1.0.1
# (StrOpt ) xcat management NIC mask.
# xcat_mgt_mask=255.255.0.0
# Example: xcat_mgt_mask=255.255.0.0
# (StrOpt ) rdev_list for each vswitch's uplink real device(s), seperated by ','.
# If a vswitch does not connect an OSA, which means it does not connect to
# external network, rdev_list can be ignored.
# A new section is required for each vswitch which has a uplink port.
# rdev_list = 6000
# Example:
# [ xcatvsw3 ]
# rdev_list = 6000,6003,6005
#-----------------------------------------------------------------------------
# Sample Configurations.
#-----------------------------------------------------------------------------
# 1. Single FLAT Mode
# Physical network names should be identical to z/VM vswitch names. In
# this sample, xcatvsw2 is used for xCAT Management Network, it should be a
# Layer 2, VLAN UNAWARE vswitch in z/VM. When create neutron network, set
# xcatvsw2 provider network_type to flat
# Neutron server:
#
# [database]
# connection = mysql://root:nova@127.0.0.1:3306/ovs_neutron
# [ovs]
# tenant_network_type = vlan
# network_vlan_ranges = xcatvsw2
#
# Neutron z/VM Agent:
#
# [AGENT]
# zvm_xcat_username = admin
# zvm_xcat_password = admin
# zvm_xcat_server = 10.0.0.1
# xcat_zhcp_nodename = zhcp
# polling_interval = 2
# zvm_xcat_timeout = 300
# xcat_mgt_ip = 10.1.0.1
# xcat_mgt_mask=255.255.0.0
# 2. FLAT, VLAN mixed Mode
# Physical network names should be identical to z/VM vswitch names. In
# this sample, xcatvsw2 is used for xCAT Management Network, it should be a
# Layer 2, VLAN UNAWARE vswitch in z/VM, xcatvsw3 is used for OpenStack
# Compute/Data Network, it is a Layer 2, VLAN AWARE vswitch in z/VM. xCAT
# Management Network MUST be the first created network. This configuration
# also can used for single FLAT network mode if you only create only one
# FLAT network with xcatvsw2
# Neutron server:
#
# [database]
# connection = mysql://root:nova@127.0.0.1:3306/ovs_neutron
# [ovs]
# tenant_network_type = vlan
# network_vlan_ranges = xcatvsw2,xcatvsw3:2:3999
#
# Neutron z/VM Agent:
#
# [AGENT]
# zvm_xcat_username = admin
# zvm_xcat_password = admin
# zvm_xcat_server = 10.0.0.1
# xcat_zhcp_nodename = zhcp
# polling_interval = 2
# zvm_xcat_timeout = 300
# xcat_mgt_ip = 10.1.0.1
# xcat_mgt_mask=255.255.0.0
#
# [xcatvsw3]
# rdev_list=6243

@ -0,0 +1,97 @@
#!/bin/sh
#
# neutron-zvm-agent OpenStack z/VM plugin
#
# chkconfig: - 98 02
# description: Support z/VM vswitch network
### END INIT INFO
. /etc/rc.d/init.d/functions
proj=neutron
plugin=zvm-agent
prog=$proj-$plugin
exec="/usr/bin/$prog"
config="/etc/$proj/plugins/zvm/neutron_zvm_plugin.ini"
plugin_config="/etc/$proj/plugins/ml2/ml2_conf.ini"
pidfile="/var/run/$proj/$prog.pid"
logfile="/var/log/$proj/$plugin.log"
[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog
lockfile=/var/lock/subsys/$prog
start() {
[ -x $exec ] || exit 5
[ -f $config ] || exit 6
[ -f $plugin_config ] || exit 6
echo -n $"Starting $prog: "
daemon --user neutron --pidfile $pidfile "$exec --config-file /etc/$proj/$proj.conf --config-file $plugin_config --config-file $config --log-file $logfile &>/dev/null & echo \$! > $pidfile"
retval=$?
echo
[ $retval -eq 0 ] && touch $lockfile
return $retval
}
stop() {
echo -n $"Stopping $prog: "
killproc -p $pidfile $prog
retval=$?
echo
[ $retval -eq 0 ] && rm -f $lockfile
return $retval
}
restart() {
stop
start
}
reload() {
restart
}
force_reload() {
restart
}
rh_status() {
status -p $pidfile $prog
}
rh_status_q() {
rh_status >/dev/null 2>&1
}
case "$1" in
start)
rh_status_q && exit 0
$1
;;
stop)
rh_status_q || exit 0
$1
;;
restart)
$1
;;
reload)
rh_status_q || exit 7
$1
;;
force-reload)
force_reload
;;
status)
rh_status
;;
condrestart|try-restart)
rh_status_q || exit 0
restart
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
exit 2
esac
exit $?

@ -0,0 +1,54 @@
# =================================================================
# Licensed Materials - Property of IBM
#
# (c) Copyright IBM Corp. 2014, 2015 All Rights Reserved
#
# US Government Users Restricted Rights - Use, duplication or
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
# =================================================================
# All Rights Reserved.
#
# 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 oslo_log import log
from neutron.common import constants
from neutron.extensions import portbindings
from neutron.plugins.common import constants as p_constants
from neutron.plugins.ml2.drivers import mech_agent
LOG = log.getLogger(__name__)
class ZvmMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase):
"""Attach to networks using zvm vswitch agent.
The ZvmMechanismDriver integrates the ml2 plugin with the
z/VM L2 agent. Port binding with this driver requires the
z/VM vswitch agent to be running on the port's host, and that agent
to have connectivity to at least one segment of the port's network.
"""
def __init__(self):
super(ZvmMechanismDriver, self).__init__(
constants.AGENT_TYPE_ZVM,
portbindings.VIF_TYPE_ZVM,
{portbindings.CAP_PORT_FILTER: False})
def get_allowed_network_types(self, agent=None):
return [p_constants.TYPE_LOCAL, p_constants.TYPE_FLAT,
p_constants.TYPE_VLAN]
def get_mappings(self, agent):
return agent['configurations'].get('vswitch_mappings', {})

@ -1,5 +1,3 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2014 IBM Corp.
#
# All Rights Reserved.
@ -16,8 +14,9 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslo.config import cfg
from neutron.openstack.common import log as logging
from oslo_config import cfg
from oslo_log import log as logging
from neutron.plugins.common import utils as plugin_utils
from neutron.plugins.zvm.common import utils
@ -44,19 +43,25 @@ class zvmVswitch(object):
class zvmNetwork(object):
def __init__(self):
self._utils = utils.zvmUtils()
self._zhcp = CONF.AGENT.xcat_zhcp_nodename
self._vsws = []
self._maps = {}
self._creat_networks()
def _creat_networks(self):
admin_vsw = self._utils.get_admin_created_vsw(self._zhcp)
self._maps = plugin_utils.parse_network_vlan_ranges(
CONF.ml2_type_vlan.network_vlan_ranges
+ CONF.ml2_type_flat.flat_networks)
CONF.ml2_type_vlan.network_vlan_ranges +
CONF.ml2_type_flat.flat_networks)
self._vsws = []
for vsw in self._maps.keys():
CONF.register_opts(vswitch_opts, vsw)
self._vsws.append(zvmVswitch(self._zhcp, vsw, self._maps[vsw]))
if vsw.upper() in admin_vsw:
LOG.info(_('Vswitch %s is pre-created by admin or system, '
'neutron-zvm-agent will not handle it') % vsw)
else:
self._vsws.append(zvmVswitch(self._zhcp, vsw, self._maps[vsw]))
def get_network_maps(self):
return self._maps

@ -1,5 +1,3 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2014 IBM Corp.
#
# All Rights Reserved.
@ -19,20 +17,19 @@
import eventlet
import sys
import time
import zvm_network
from oslo.config import cfg
from oslo_config import cfg
from oslo_log import log as logging
from neutron import context
from neutron.agent import rpc as agent_rpc
from neutron.common import config as common_config
from neutron.common import constants as q_const
from neutron.common import rpc as n_rpc
from neutron.common import topics
from neutron.plugins.common import constants as p_const
from neutron.openstack.common import log as logging
from neutron import context
from neutron.openstack.common import loopingcall
from neutron.openstack.common.gettextutils import _
from neutron.plugins.common import constants as p_const
from neutron.i18n import _, _LE, _LI
from neutron.plugins.zvm.agent import zvm_network
from neutron.plugins.zvm.common import exception
from neutron.plugins.zvm.common import utils
@ -47,7 +44,7 @@ def restart_wrapper(func):
return wrapper
class zvmNeutronAgent(n_rpc.RpcCallback):
class zvmNeutronAgent(object):
RPC_API_VERSION = '1.1'
def __init__(self):
@ -55,7 +52,7 @@ class zvmNeutronAgent(n_rpc.RpcCallback):
self._utils = utils.zvmUtils()
self._polling_interval = cfg.CONF.AGENT.polling_interval
self._zhcp_node = cfg.CONF.AGENT.xcat_zhcp_nodename
self._host = cfg.CONF.AGENT.zvm_host
self._host = cfg.CONF.AGENT.zvm_host or cfg.CONF.host
zvm_net = zvm_network.zvmNetwork()
self.agent_state = {
@ -98,11 +95,11 @@ class zvmNeutronAgent(n_rpc.RpcCallback):
LOG.exception(_("Failed reporting state!"))
def network_delete(self, context, network_id=None):
LOG.debug(_("Network delete received. UUID: %s"), network_id)
LOG.debug("Network delete received. UUID: %s", network_id)
def port_update(self, context, **kwargs):
port = kwargs.get('port')
LOG.debug(_("Port update received. UUID: %s"), port)
LOG.debug("Port update received. UUID: %s", port)
if not port['id'] in self._port_map.keys():
# update a port which is not coupled to any NIC, nothing
@ -126,7 +123,7 @@ class zvmNeutronAgent(n_rpc.RpcCallback):
def port_bound(self, port_id, net_uuid,
network_type, physical_network, segmentation_id, userid):
LOG.debug(_("Binding port %s"), port_id)
LOG.debug("Binding port %s", port_id)
self._utils.grant_user(self._zhcp_node, physical_network, userid)
vdev = self._utils.couple_nic_to_vswitch(physical_network, port_id,
@ -143,7 +140,7 @@ class zvmNeutronAgent(n_rpc.RpcCallback):
LOG.info(_('Bind %s mode done'), network_type)
def port_unbound(self, port_id):
LOG.debug(_("Unbinding port %s"), port_id)
LOG.debug("Unbinding port %s", port_id)
# uncouple is not necessary, because revoke user will uncouple it
# automatically.
self._utils.revoke_user(self._zhcp_node,
@ -188,14 +185,14 @@ class zvmNeutronAgent(n_rpc.RpcCallback):
device,
self.agent_id)
except Exception:
LOG.debug(_("Unable to get port details for %s:"), device)
LOG.info(_LI("Unable to get port details for %s:"), device)
continue
try:
if 'port_id' in details:
LOG.info(_("Port %(device)s updated."
" Details: %(details)s"),
{'device': device, 'details': details})
LOG.info(_("Port %(device)s updated. "
"Details: %(details)s"),
{'device': device, 'details': details})
(node, userid) = self._treat_vif_port(
details['port_id'],
details['network_id'],
@ -217,39 +214,39 @@ class zvmNeutronAgent(n_rpc.RpcCallback):
details['physical_network'],
details['segmentation_id'])
if details.get('admin_state_up'):
LOG.debug(_("Setting status for %s to UP"), device)
LOG.debug("Setting status for %s to UP", device)
self.plugin_rpc.update_device_up(
self.context, device, self.agent_id, cfg.CONF.host)
self.context, device, self.agent_id, self._host)
else:
LOG.debug(_("Setting status for %s to DOWN"), device)
LOG.debug("Setting status for %s to DOWN", device)
self.plugin_rpc.update_device_down(
self.context, device, self.agent_id, cfg.CONF.host)
self.context, device, self.agent_id, self._host)
else:
LOG.debug(_("Device %s not defined on Neutron server"),
device)
LOG.debug("Device %s not defined on Neutron server",
device)
continue
except Exception as e:
LOG.exception(_("Can not add device %(device)s: %(msg)s"),
{'device': device, 'msg': e})
{'device': device, 'msg': e})
continue
def _treat_devices_removed(self, devices):
for device in devices:
LOG.info(_("Removing port %s"), device)
try:
if not device in self._port_map:
if device not in self._port_map:
LOG.warn(_("Can't find port %s in zvm agent"), device)
continue
self.port_unbound(device)
self.plugin_rpc.update_device_down(self.context,
device,
self.agent_id)
device,
self.agent_id)
del self._port_map[device]
except Exception as e:
LOG.exception(_("Removing port failed %(device)s: %(msg)s"),
{'device': device, 'msg': e})
{'device': device, 'msg': e})
continue
def _process_network_ports(self, port_info):
@ -278,23 +275,23 @@ class zvmNeutronAgent(n_rpc.RpcCallback):
connect = True
if port_info:
LOG.debug(_("Devices change!"))
LOG.debug("Devices change, info: %s" % port_info)
self._process_network_ports(port_info)
ports = port_info['current']
except exception.zVMxCatRequestFailed as e:
LOG.error(_("Lost connection to xCAT. %s"), e)
LOG.error(_LE("Lost connection to xCAT. %s"), e)
connect = False
except Exception as e:
LOG.exception(_("error in xCAT DB query loop: %s"), e)
LOG.exception(_LE("error in xCAT DB query loop: %s"), e)
# sleep till end of polling interval
elapsed = (time.time() - start_time)
if (elapsed < self._polling_interval):
sleep_time = self._polling_interval - elapsed
LOG.debug(_("Sleep %s"), sleep_time)
LOG.debug("Sleep %s", sleep_time)
time.sleep(sleep_time)
else:
LOG.debug(_("Looping iteration exceeded interval"))
LOG.debug("Looping iteration exceeded interval")
def _init_xcat_mgt(self):
'''xCAT Management Node(MN) use the first flat network to manage all
@ -305,8 +302,13 @@ class zvmNeutronAgent(n_rpc.RpcCallback):
by default neutron_zvm_plugin.ini.
'''
if (cfg.CONF.AGENT.xcat_mgt_ip is None or
cfg.CONF.AGENT.xcat_mgt_mask is None):
LOG.info(_("User does not configure management IP. Don't need to"
" initialize xCAT management network."))
return
if not len(cfg.CONF.ml2_type_flat.flat_networks):
raise exception.zvmException(
raise exception.zVMConfigException(
msg=_('Can not find xCAT management network,'
'a flat network is required by xCAT.'))
self._utils.create_xcat_mgt_network(self._zhcp_node,
@ -330,8 +332,10 @@ class zvmNeutronAgent(n_rpc.RpcCallback):
self._port_map = self._utils.re_grant_user(self._zhcp_node)
zvm_uptime = tmp_new_time
yield
except exception.zVMConfigException:
raise
except Exception:
LOG.error(_("Failed to handle restart,"
LOG.error(_LE("Failed to handle restart,"
"try again in 5 seconds"))
time.sleep(5)
@ -345,6 +349,6 @@ def main():
agent = zvmNeutronAgent()
# Start to query xCAT DB
agent.xcatdb_daemon_loop()
LOG.info(_("z/VM agent initialized, now running... "))
agent.xcatdb_daemon_loop()
sys.exit(0)

@ -1,5 +1,3 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2014 IBM Corp.
#
# All Rights Reserved.
@ -16,9 +14,11 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslo.config import cfg
from oslo_config import cfg
from neutron.agent.common import config
from neutron.openstack.common.gettextutils import _
from neutron.i18n import _
agent_opts = [
cfg.StrOpt(
@ -27,7 +27,9 @@ agent_opts = [
help=_('xCat zHCP nodename in xCAT ')),
cfg.StrOpt(
'zvm_host',
help=_('z/VM host that managed by zHCP.')),
help=_("DEPRECATED, use 'host' in neutron.conf instead."
"If it is not specified, 'host' in neutron.conf"
"will take effect")),
cfg.StrOpt(
'zvm_xcat_username',
default='admin',

@ -1,5 +1,3 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2014 IBM Corp.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may

@ -1,5 +1,3 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2014 IBM Corp.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -16,13 +14,17 @@
from neutron.common import exceptions as exception
from neutron.openstack.common.gettextutils import _
from neutron.i18n import _
class zvmException(exception.NeutronException):
message = _('zvmException: %(msg)s')
class zVMConfigException(exception.NeutronException):
message = _('zVMConfig Error: %(msg)s')
class zVMxCatConnectionFailed(exception.NeutronException):
message = _('Failed to connect xCAT server: %(xcatserver)s')

@ -1,5 +1,3 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2014 IBM Corp.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -14,12 +12,15 @@
# License for the specific language governing permissions and limitations
# under the License.
import xcatutils
import re
from oslo_config import cfg
from oslo_log import log as logging
from oslo.config import cfg
from neutron.openstack.common import log as logging
from neutron.openstack.common.gettextutils import _
from neutron.i18n import _, _LE, _LW
from neutron.plugins.zvm.common import exception
from neutron.plugins.zvm.common import xcatutils
CONF = cfg.CONF
LOG = logging.getLogger(__name__)
@ -40,20 +41,21 @@ class zvmUtils(object):
def get_nic_ids(self):
addp = ''
url = self._xcat_url.tabdump("/switch", addp)
nic_settings = xcatutils.xcat_request("GET", url)
with xcatutils.expect_invalid_xcat_resp_data():
nic_settings = xcatutils.xcat_request("GET", url)['data'][0]
# remove table header
nic_settings['data'][0].pop(0)
nic_settings.pop(0)
# it's possible to return empty array
return nic_settings['data'][0]
return nic_settings
def _get_nic_settings(self, port_id, field=None, get_node=False):
"""Get NIC information from xCat switch table."""
LOG.debug(_("Get nic information for port: %s"), port_id)
LOG.debug("Get nic information for port: %s", port_id)
addp = '&col=port&value=%s' % port_id + '&attribute=%s' % (
field and field or 'node')
url = self._xcat_url.gettab("/switch", addp)
nic_settings = xcatutils.xcat_request("GET", url)
ret_value = nic_settings['data'][0][0]
with xcatutils.expect_invalid_xcat_resp_data():
ret_value = xcatutils.xcat_request("GET", url)['data'][0][0]
if field is None and not get_node:
ret_value = self.get_userid_from_node(ret_value)
return ret_value
@ -61,13 +63,13 @@ class zvmUtils(object):
def get_userid_from_node(self, node):
addp = '&col=node&value=%s&attribute=userid' % node
url = self._xcat_url.gettab("/zvm", addp)
user_info = xcatutils.xcat_request("GET", url)
return user_info['data'][0][0]
with xcatutils.expect_invalid_xcat_resp_data():
return xcatutils.xcat_request("GET", url)['data'][0][0]
def couple_nic_to_vswitch(self, vswitch_name, switch_port_name,
zhcp, userid, dm=True, immdt=True):
zhcp, userid, dm=True, immdt=True):
"""Couple nic to vswitch."""
LOG.debug(_("Connect nic to switch: %s"), vswitch_name)
LOG.debug("Connect nic to switch: %s", vswitch_name)
vdev = self._get_nic_settings(switch_port_name, "interface")
if vdev:
self._couple_nic(zhcp, vswitch_name, userid, vdev, dm, immdt)
@ -78,9 +80,9 @@ class zvmUtils(object):
return vdev
def uncouple_nic_from_vswitch(self, vswitch_name, switch_port_name,
zhcp, userid, dm=True, immdt=True):
zhcp, userid, dm=True, immdt=True):
"""Uncouple nic from vswitch."""
LOG.debug(_("Disconnect nic from switch: %s"), vswitch_name)
LOG.debug("Disconnect nic from switch: %s", vswitch_name)
vdev = self._get_nic_settings(switch_port_name, "interface")
self._uncouple_nic(zhcp, userid, vdev, dm, immdt)
@ -175,6 +177,32 @@ class zvmUtils(object):
self._zhcp_userid = self.get_userid_from_node(zhcp)
return self._zhcp_userid
@xcatutils.wrap_invalid_xcat_resp_data_error
def get_admin_created_vsw(self, zhcp):
'''Check whether the vswitch is preinstalled in env,
these vswitchs should not be handled by neutron-zvm-agent.
'''
url = self._xcat_url.xdsh('/%s' % self._xcat_node_name)
commands = 'command=vmcp q v nic'
body = [commands]
result = xcatutils.xcat_request("PUT", url, body)
if (result['errorcode'][0][0] != '0'):
raise exception.zvmException(
msg=("Query xcat nic info failed, %s") % result['data'][0][0])
output = result['data'][0][0].split('\n')
vswitch = []
index = 0
for i in output:
if ('0600' in i) or ('0700' in i):
vsw_start = output[index + 1].rfind(' ') + 1
vswitch.append(output[index + 1][vsw_start:])
index += 1
LOG.debug("admin config vswitch is %s" % vswitch)
return vswitch
@xcatutils.wrap_invalid_xcat_resp_data_error
def add_vswitch(self, zhcp, name, rdev,
controller='*',
connection=1, queue_mem=8, router=0, network_type=2, vid=0,
@ -189,9 +217,26 @@ class zvmUtils(object):
configuration file
gvrp:0-unspecified 1-gvrp 2-nogvrp
'''
if (self._does_vswitch_exist(zhcp, name)):
LOG.info(_('Vswitch %s already exists.'), name)
return
vswitch_info = self._check_vswitch_status(zhcp, name)
if vswitch_info is not None:
LOG.info(_('Vswitch %s already exists,check rdev info.'), name)
if rdev is None:
LOG.debug('vswitch %s is not changed', name)
return
else:
# as currently zvm-agent can only set one rdev for vswitch
# so as long one of rdev in vswitch env are same as rdevs
# list in config file, we think the vswitch does not change.
rdev_list = rdev.split(',')
for i in vswitch_info:
for j in rdev_list:
if i.strip() == j.strip():
LOG.debug('vswitch %s is not changed', name)
return
LOG.info(_('start changing vswitch %s '), name)
self._set_vswitch_rdev(zhcp, name, rdev)
return
# if vid = 0, port_type, gvrp and native_vlanid are not
# allowed to specified
@ -210,7 +255,7 @@ class zvmUtils(object):
commands += ' -n %s' % name
if rdev:
commands += " -r %s" % rdev.replace(',', ' ')
#commands += " -a %s" % osa_name
# commands += " -a %s" % osa_name
if controller != '*':
commands += " -i %s" % controller
commands += " -c %s" % connection
@ -226,14 +271,22 @@ class zvmUtils(object):
body = [xdsh_commands]
result = xcatutils.xcat_request("PUT", url, body)
if (result['errorcode'][0][0] != '0') or \
(not self._does_vswitch_exist(zhcp, name)):
if ((result['errorcode'][0][0] != '0') or
(self._check_vswitch_status(zhcp, name) is None)):
raise exception.zvmException(
msg=("switch: %s add failed, %s") %
(name, result['data'][0][0]))
(name, result['data'][0][0]))
LOG.info(_('Created vswitch %s done.'), name)
def _does_vswitch_exist(self, zhcp, vsw):
@xcatutils.wrap_invalid_xcat_resp_data_error
def _check_vswitch_status(self, zhcp, vsw):
'''
check the vswitch exists or not,return rdev info
return value:
None: vswitch does not exist
[]: vswitch exists but does not connect to a rdev
['xxxx','xxxx']:vswitch exists and 'xxxx' is rdev value
'''
userid = self.get_zhcp_userid(zhcp)
url = self._xcat_url.xdsh("/%s" % zhcp)
commands = '/opt/zhcp/bin/smcli Virtual_Network_Vswitch_Query'
@ -242,11 +295,34 @@ class zvmUtils(object):
xdsh_commands = 'command=%s' % commands
body = [xdsh_commands]
result = xcatutils.xcat_request("PUT", url, body)
if (result['errorcode'][0][0] != '0' or not
result['data'] or not result['data'][0]):
return None
else:
output = re.findall('Real device: (.*)\n', result['data'][0][0])
return output
return (result['errorcode'][0][0] == '0')
@xcatutils.wrap_invalid_xcat_resp_data_error
def _set_vswitch_rdev(self, zhcp, vsw, rdev):
"""Set vswitch's rdev."""
userid = self.get_zhcp_userid(zhcp)
url = self._xcat_url.xdsh("/%s" % zhcp)
commands = '/opt/zhcp/bin/smcli Virtual_Network_Vswitch_Set_Extended'
commands += ' -T %s' % userid
commands += ' -k switch_name=%s' % vsw
if rdev:
commands += ' -k real_device_address=%s' % rdev.replace(',', ' ')
xdsh_commands = 'command=%s' % commands
body = [xdsh_commands]
result = xcatutils.xcat_request("PUT", url, body)
if (result['errorcode'][0][0] != '0'):
raise exception.zvmException(
msg=("switch: %s changes failed, %s") %
(vsw, result['data'][0][0]))
LOG.info(_('change vswitch %s done.'), vsw)
def re_grant_user(self, zhcp):
"""Grant user again after z/VM is re-IPLed"""
"""Grant user again after z/VM is re-IPLed."""
ports_info = self._get_userid_vswitch_vlan_id_mapping(zhcp)
records_num = 0
cmd = ''
@ -277,7 +353,7 @@ class zvmUtils(object):
# just in case there are bad records of vlan info which
# could be a string
LOG.warn(_("Unknown vlan '%(vlan)s' for user %(user)s."),
{'vlan': port['vlan_id'], 'user': port['userid']})
{'vlan': port['vlan_id'], 'user': port['userid']})
cmd += '\n'
continue
records_num += 1
@ -315,6 +391,7 @@ class zvmUtils(object):
'userid': None,
'vlan_id': port_vid}
@xcatutils.wrap_invalid_xcat_resp_data_error
def get_all_userid():
users = {}
addp = ''
@ -350,10 +427,12 @@ class zvmUtils(object):
body = [commands]
xcatutils.xcat_request("PUT", url, body)
@xcatutils.wrap_invalid_xcat_resp_data_error
def create_xcat_mgt_network(self, zhcp, mgt_ip, mgt_mask, mgt_vswitch):
url = self._xcat_url.xdsh("/%s" % zhcp)
xdsh_commands = ('command=smcli Virtual_Network_Adapter_Query'
' -T %s -v 0800') % self._xcat_node_name
' -T %s -v 0800') % self.get_userid_from_node(
self._xcat_node_name)
body = [xdsh_commands]
result = xcatutils.xcat_request("PUT", url, body)['data'][0][0]
code = result.split("\n")
@ -365,11 +444,29 @@ class zvmUtils(object):
elif len(code) == 7:
status = code[4].split(': ')[2]
if status == 'Coupled and active':
# we just assign the IP/mask,
# no matter if it is assigned or not
LOG.info(_("Assign IP for NIC 800."))
# Only support one management network.
url = self._xcat_url.xdsh("/%s") % self._xcat_node_name
xdsh_commands = "command=ifconfig eth2|grep 'inet addr:'"
body = [xdsh_commands]
result = xcatutils.xcat_request("PUT", url, body)
if result['errorcode'][0][0] == '0' and result['data']:
cur_ip = re.findall('inet addr:(.*) Bcast:',
result['data'][0][0])
cur_mask = result['data'][0][0].split("Mask:")[1]
if mgt_ip != cur_ip[0]:
raise exception.zVMConfigException(
msg=("Only support one Management network,"
"it has been assigned by other agent!"
"Please use current management network"
"(%s/%s) to deploy." % (cur_ip[0], cur_mask)))
else:
LOG.debug("IP address has been assigned for NIC 800.")
return
else:
LOG.warning(_LW("Nic 800 has been created, but IP address "
"doesn't exist, will config it again"))
else:
LOG.error(_("NIC 800 staus is unknown."))
LOG.error(_LE("NIC 800 staus is unknown."))
return
else:
raise exception.zvmException(
@ -386,13 +483,15 @@ class zvmUtils(object):
def _get_xcat_node_ip(self):
addp = '&col=key&value=master&attribute=value'
url = self._xcat_url.gettab("/site", addp)
return xcatutils.xcat_request("GET", url)['data'][0][0]
with xcatutils.expect_invalid_xcat_resp_data():
return xcatutils.xcat_request("GET", url)['data'][0][0]
def _get_xcat_node_name(self):
xcat_ip = self._get_xcat_node_ip()
addp = '&col=ip&value=%s&attribute=node' % (xcat_ip)
url = self._xcat_url.gettab("/hosts", addp)
return (xcatutils.xcat_request("GET", url)['data'][0][0])
with xcatutils.expect_invalid_xcat_resp_data():
return (xcatutils.xcat_request("GET", url)['data'][0][0])
def query_xcat_uptime(self, zhcp):
url = self._xcat_url.xdsh("/%s" % zhcp)
@ -403,7 +502,8 @@ class zvmUtils(object):
cmd += " -f %s" % "4"
xdsh_commands = 'command=%s' % cmd
body = [xdsh_commands]
ret_str = xcatutils.xcat_request("PUT", url, body)['data'][0][0]
with xcatutils.expect_invalid_xcat_resp_data():
ret_str = xcatutils.xcat_request("PUT", url, body)['data'][0][0]
return ret_str.split('on ')[1]
def query_zvm_uptime(self, zhcp):
@ -411,5 +511,6 @@ class zvmUtils(object):
cmd = '/opt/zhcp/bin/smcli System_Info_Query'
xdsh_commands = 'command=%s' % cmd
body = [xdsh_commands]
ret_str = xcatutils.xcat_request("PUT", url, body)['data'][0][0]
with xcatutils.expect_invalid_xcat_resp_data():
ret_str = xcatutils.xcat_request("PUT", url, body)['data'][0][0]
return ret_str.split('\n')[4].split(': ', 3)[2]

<
@ -1,5 +1,3 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2014 IBM Corp.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -14,13 +12,15 @@
# License for the specific language governing permissions and limitations
# under the License.
import contextlib
import functools
import httplib
from neutron.openstack.common import jsonutils
from neutron.openstack.common.gettextutils import _
from neutron.openstack.common import log as logging
from oslo_log import log as logging
from oslo_serialization import jsonutils
from neutron.i18n import _
from neutron.i18n import _LE
from neutron.plugins.zvm.common import config
from neutron.plugins.zvm.common import constants
from neutron.plugins.zvm.common import exception
@ -35,9 +35,9 @@ class xCatURL(object):
def __init__(self):
"""Set constant that used to form xCat url."""
self.PREFIX = '/xcatws'
self.SUFFIX = '?userName=' + CONF.AGENT.zvm_xcat_username + \
'&password=' + CONF.AGENT.zvm_xcat_password + \
'&format=json'