Common cinder interface additional improvements

This is a follow up to 459fe314fa

Minor issues in the code and tests are fixed, the release note is added,
configuration options are described as part of not yet exposed feature.

Change-Id: Ib466ee3970dcc1e141ddac38a54544f6a011549e
Partial-Bug: #1559691
This commit is contained in:
Joanna Taryma 2017-04-12 12:47:13 -07:00
parent 28c48ea68f
commit 3b5aefa0b6
5 changed files with 178 additions and 180 deletions

View File

@ -383,13 +383,6 @@
# Note: This option can be changed without restarting. # Note: This option can be changed without restarting.
#debug = false #debug = false
# DEPRECATED: If set to false, the logging level will be set
# to WARNING instead of the default INFO level. (boolean
# value)
# This option is deprecated for removal.
# Its value may be silently ignored in the future.
#verbose = true
# The name of a logging configuration file. This file is # The name of a logging configuration file. This file is
# appended to any existing logging configuration files. For # appended to any existing logging configuration files. For
# details about logging configuration files, see the Python # details about logging configuration files, see the Python
@ -433,6 +426,13 @@
# ignored if log_config_append is set. (boolean value) # ignored if log_config_append is set. (boolean value)
#use_syslog = false #use_syslog = false
# Enable journald for logging. If running in a systemd
# environment you may wish to enable journal support. Doing so
# will use the journal native protocol which includes
# structured metadata in addition to log messages.This option
# is ignored if log_config_append is set. (boolean value)
#use_journal = false
# Syslog facility to receive log lines. This option is ignored # Syslog facility to receive log lines. This option is ignored
# if log_config_append is set. (string value) # if log_config_append is set. (string value)
#syslog_log_facility = LOG_USER #syslog_log_facility = LOG_USER
@ -500,7 +500,6 @@
# #
# Size of RPC connection pool. (integer value) # Size of RPC connection pool. (integer value)
# Deprecated group/name - [DEFAULT]/rpc_conn_pool_size
#rpc_conn_pool_size = 30 #rpc_conn_pool_size = 30
# The pool size limit for connections expiration policy # The pool size limit for connections expiration policy
@ -514,31 +513,25 @@
# ZeroMQ bind address. Should be a wildcard (*), an ethernet # ZeroMQ bind address. Should be a wildcard (*), an ethernet
# interface, or IP. The "host" option should point or resolve # interface, or IP. The "host" option should point or resolve
# to this address. (string value) # to this address. (string value)
# Deprecated group/name - [DEFAULT]/rpc_zmq_bind_address
#rpc_zmq_bind_address = * #rpc_zmq_bind_address = *
# MatchMaker driver. (string value) # MatchMaker driver. (string value)
# Allowed values: redis, sentinel, dummy # Allowed values: redis, sentinel, dummy
# Deprecated group/name - [DEFAULT]/rpc_zmq_matchmaker
#rpc_zmq_matchmaker = redis #rpc_zmq_matchmaker = redis
# Number of ZeroMQ contexts, defaults to 1. (integer value) # Number of ZeroMQ contexts, defaults to 1. (integer value)
# Deprecated group/name - [DEFAULT]/rpc_zmq_contexts
#rpc_zmq_contexts = 1 #rpc_zmq_contexts = 1
# Maximum number of ingress messages to locally buffer per # Maximum number of ingress messages to locally buffer per
# topic. Default is unlimited. (integer value) # topic. Default is unlimited. (integer value)
# Deprecated group/name - [DEFAULT]/rpc_zmq_topic_backlog
#rpc_zmq_topic_backlog = <None> #rpc_zmq_topic_backlog = <None>
# Directory for holding IPC sockets. (string value) # Directory for holding IPC sockets. (string value)
# Deprecated group/name - [DEFAULT]/rpc_zmq_ipc_dir
#rpc_zmq_ipc_dir = /var/run/openstack #rpc_zmq_ipc_dir = /var/run/openstack
# Name of this node. Must be a valid hostname, FQDN, or IP # Name of this node. Must be a valid hostname, FQDN, or IP
# address. Must match "host" option, if running Nova. (string # address. Must match "host" option, if running Nova. (string
# value) # value)
# Deprecated group/name - [DEFAULT]/rpc_zmq_host
#rpc_zmq_host = localhost #rpc_zmq_host = localhost
# Number of seconds to wait before all pending messages will # Number of seconds to wait before all pending messages will
@ -554,26 +547,21 @@
# The default number of seconds that poll should wait. Poll # The default number of seconds that poll should wait. Poll
# raises timeout exception when timeout expired. (integer # raises timeout exception when timeout expired. (integer
# value) # value)
# Deprecated group/name - [DEFAULT]/rpc_poll_timeout
#rpc_poll_timeout = 1 #rpc_poll_timeout = 1
# Expiration timeout in seconds of a name service record about # Expiration timeout in seconds of a name service record about
# existing target ( < 0 means no timeout). (integer value) # existing target ( < 0 means no timeout). (integer value)
# Deprecated group/name - [DEFAULT]/zmq_target_expire
#zmq_target_expire = 300 #zmq_target_expire = 300
# Update period in seconds of a name service record about # Update period in seconds of a name service record about
# existing target. (integer value) # existing target. (integer value)
# Deprecated group/name - [DEFAULT]/zmq_target_update
#zmq_target_update = 180 #zmq_target_update = 180
# Use PUB/SUB pattern for fanout methods. PUB/SUB always uses # Use PUB/SUB pattern for fanout methods. PUB/SUB always uses
# proxy. (boolean value) # proxy. (boolean value)
# Deprecated group/name - [DEFAULT]/use_pub_sub
#use_pub_sub = false #use_pub_sub = false
# Use ROUTER remote proxy. (boolean value) # Use ROUTER remote proxy. (boolean value)
# Deprecated group/name - [DEFAULT]/use_router_proxy
#use_router_proxy = false #use_router_proxy = false
# This option makes direct connections dynamic or static. It # This option makes direct connections dynamic or static. It
@ -590,25 +578,21 @@
# Minimal port number for random ports range. (port value) # Minimal port number for random ports range. (port value)
# Minimum value: 0 # Minimum value: 0
# Maximum value: 65535 # Maximum value: 65535
# Deprecated group/name - [DEFAULT]/rpc_zmq_min_port
#rpc_zmq_min_port = 49153 #rpc_zmq_min_port = 49153
# Maximal port number for random ports range. (integer value) # Maximal port number for random ports range. (integer value)
# Minimum value: 1 # Minimum value: 1
# Maximum value: 65536 # Maximum value: 65536
# Deprecated group/name - [DEFAULT]/rpc_zmq_max_port
#rpc_zmq_max_port = 65536 #rpc_zmq_max_port = 65536
# Number of retries to find free port number before fail with # Number of retries to find free port number before fail with
# ZMQBindError. (integer value) # ZMQBindError. (integer value)
# Deprecated group/name - [DEFAULT]/rpc_zmq_bind_port_retries
#rpc_zmq_bind_port_retries = 100 #rpc_zmq_bind_port_retries = 100
# Default serialization mechanism for # Default serialization mechanism for
# serializing/deserializing outgoing/incoming messages (string # serializing/deserializing outgoing/incoming messages (string
# value) # value)
# Allowed values: json, msgpack # Allowed values: json, msgpack
# Deprecated group/name - [DEFAULT]/rpc_zmq_serialization
#rpc_zmq_serialization = json #rpc_zmq_serialization = json
# This option configures round-robin mode in zmq socket. True # This option configures round-robin mode in zmq socket. True
@ -684,7 +668,8 @@
# taken from the matchmaker. (list value) # taken from the matchmaker. (list value)
#subscribe_on = #subscribe_on =
# Size of executor thread pool. (integer value) # Size of executor thread pool when executor is threading or
# eventlet. (integer value)
# Deprecated group/name - [DEFAULT]/rpc_thread_pool_size # Deprecated group/name - [DEFAULT]/rpc_thread_pool_size
#executor_thread_pool_size = 64 #executor_thread_pool_size = 64
@ -952,15 +937,16 @@
#project_domain_name = <None> #project_domain_name = <None>
# Project ID to scope to (string value) # Project ID to scope to (string value)
# Deprecated group/name - [cinder]/tenant-id # Deprecated group/name - [cinder]/tenant_id
#project_id = <None> #project_id = <None>
# Project name to scope to (string value) # Project name to scope to (string value)
# Deprecated group/name - [cinder]/tenant-name # Deprecated group/name - [cinder]/tenant_name
#project_name = <None> #project_name = <None>
# Client retries in the case of a failed request connection. # Client retries in the case of a failed request connection.
# (integer value) # This option is part of boot-from-volume work, which is not
# currently exposed to users. (integer value)
#retries = 3 #retries = 3
# Tenant ID (string value) # Tenant ID (string value)
@ -976,13 +962,11 @@
#trust_id = <None> #trust_id = <None>
# URL for connecting to cinder. If set, the value must start # URL for connecting to cinder. If set, the value must start
# with either http:// or https://. (string value) # with either http:// or https://. This option is part of
# boot-from-volume work, which is not currently exposed to
# users. (string value)
#url = <None> #url = <None>
# Timeout value for connecting to cinder in seconds. (integer
# value)
#url_timeout = 30
# User's domain id (string value) # User's domain id (string value)
#user_domain_id = <None> #user_domain_id = <None>
@ -993,7 +977,7 @@
#user_id = <None> #user_id = <None>
# Username (string value) # Username (string value)
# Deprecated group/name - [cinder]/user-name # Deprecated group/name - [cinder]/user_name
#username = <None> #username = <None>
@ -1251,16 +1235,7 @@
# From oslo.db # From oslo.db
# #
# DEPRECATED: The file name to use with SQLite. (string value)
# Deprecated group/name - [DEFAULT]/sqlite_db
# This option is deprecated for removal.
# Its value may be silently ignored in the future.
# Reason: Should use config option connection or
# slave_connection to connect the database.
#sqlite_db = oslo.sqlite
# If True, SQLite uses synchronous mode. (boolean value) # If True, SQLite uses synchronous mode. (boolean value)
# Deprecated group/name - [DEFAULT]/sqlite_synchronous
#sqlite_synchronous = true #sqlite_synchronous = true
# The back end to use for the database. (string value) # The back end to use for the database. (string value)
@ -1591,11 +1566,11 @@
#project_domain_name = <None> #project_domain_name = <None>
# Project ID to scope to (string value) # Project ID to scope to (string value)
# Deprecated group/name - [glance]/tenant-id # Deprecated group/name - [glance]/tenant_id
#project_id = <None> #project_id = <None>
# Project name to scope to (string value) # Project name to scope to (string value)
# Deprecated group/name - [glance]/tenant-name # Deprecated group/name - [glance]/tenant_name
#project_name = <None> #project_name = <None>
# The account that Glance uses to communicate with Swift. The # The account that Glance uses to communicate with Swift. The
@ -1698,7 +1673,7 @@
#user_id = <None> #user_id = <None>
# Username (string value) # Username (string value)
# Deprecated group/name - [glance]/user-name # Deprecated group/name - [glance]/user_name
#username = <None> #username = <None>
@ -1840,11 +1815,11 @@
#project_domain_name = <None> #project_domain_name = <None>
# Project ID to scope to (string value) # Project ID to scope to (string value)
# Deprecated group/name - [inspector]/tenant-id # Deprecated group/name - [inspector]/tenant_id
#project_id = <None> #project_id = <None>
# Project name to scope to (string value) # Project name to scope to (string value)
# Deprecated group/name - [inspector]/tenant-name # Deprecated group/name - [inspector]/tenant_name
#project_name = <None> #project_name = <None>
# ironic-inspector HTTP endpoint. If this is not set, the # ironic-inspector HTTP endpoint. If this is not set, the
@ -1877,7 +1852,7 @@
#user_id = <None> #user_id = <None>
# Username (string value) # Username (string value)
# Deprecated group/name - [inspector]/user-name # Deprecated group/name - [inspector]/user_name
#username = <None> #username = <None>
@ -2178,6 +2153,22 @@
# Reason: PKI token format is no longer supported. # Reason: PKI token format is no longer supported.
#hash_algorithms = md5 #hash_algorithms = md5
# A choice of roles that must be present in a service token.
# Service tokens are allowed to request that an expired token
# can be used and so this check should tightly control that
# only actual services should be sending this token. Roles
# here are applied as an ANY check so any role in this list
# must be present. For backwards compatibility reasons this
# currently only affects the allow_expired check. (list value)
#service_token_roles = service
# For backwards compatibility reasons we must let valid
# service tokens pass that don't pass the service_token_roles
# check as valid. Setting this true will become the default in
# a future release and should be enabled if possible. (boolean
# value)
#service_token_roles_required = false
# Authentication type to load (string value) # Authentication type to load (string value)
# Deprecated group/name - [keystone_authtoken]/auth_plugin # Deprecated group/name - [keystone_authtoken]/auth_plugin
#auth_type = <None> #auth_type = <None>
@ -2406,11 +2397,11 @@
#project_domain_name = <None> #project_domain_name = <None>
# Project ID to scope to (string value) # Project ID to scope to (string value)
# Deprecated group/name - [neutron]/tenant-id # Deprecated group/name - [neutron]/tenant_id
#project_id = <None> #project_id = <None>
# Project name to scope to (string value) # Project name to scope to (string value)
# Deprecated group/name - [neutron]/tenant-name # Deprecated group/name - [neutron]/tenant_name
#project_name = <None> #project_name = <None>
# Neutron network UUID or name for the ramdisk to be booted # Neutron network UUID or name for the ramdisk to be booted
@ -2463,7 +2454,7 @@
#user_id = <None> #user_id = <None>
# Username (string value) # Username (string value)
# Deprecated group/name - [neutron]/user-name # Deprecated group/name - [neutron]/user_name
#username = <None> #username = <None>
@ -2512,7 +2503,6 @@
# #
# Enables or disables inter-process locks. (boolean value) # Enables or disables inter-process locks. (boolean value)
# Deprecated group/name - [DEFAULT]/disable_process_locking
#disable_process_locking = false #disable_process_locking = false
# Directory to use for lock files. For security, the # Directory to use for lock files. For security, the
@ -2520,7 +2510,6 @@
# running the processes that need locking. Defaults to # running the processes that need locking. Defaults to
# environment variable OSLO_LOCK_PATH. If external locks are # environment variable OSLO_LOCK_PATH. If external locks are
# used, a lock path must be set. (string value) # used, a lock path must be set. (string value)
# Deprecated group/name - [DEFAULT]/lock_path
#lock_path = <None> #lock_path = <None>
@ -2532,41 +2521,38 @@
# Name for the AMQP container. must be globally unique. # Name for the AMQP container. must be globally unique.
# Defaults to a generated UUID (string value) # Defaults to a generated UUID (string value)
# Deprecated group/name - [amqp1]/container_name
#container_name = <None> #container_name = <None>
# Timeout for inactive connections (in seconds) (integer # Timeout for inactive connections (in seconds) (integer
# value) # value)
# Deprecated group/name - [amqp1]/idle_timeout
#idle_timeout = 0 #idle_timeout = 0
# Debug: dump AMQP frames to stdout (boolean value) # Debug: dump AMQP frames to stdout (boolean value)
# Deprecated group/name - [amqp1]/trace
#trace = false #trace = false
# Attempt to connect via SSL. If no other ssl-related
# parameters are given, it will use the system's CA-bundle to
# verify the server's certificate. (boolean value)
#ssl = false
# CA certificate PEM file used to verify the server's # CA certificate PEM file used to verify the server's
# certificate (string value) # certificate (string value)
# Deprecated group/name - [amqp1]/ssl_ca_file
#ssl_ca_file = #ssl_ca_file =
# Self-identifying certificate PEM file for client # Self-identifying certificate PEM file for client
# authentication (string value) # authentication (string value)
# Deprecated group/name - [amqp1]/ssl_cert_file
#ssl_cert_file = #ssl_cert_file =
# Private key PEM file used to sign ssl_cert_file certificate # Private key PEM file used to sign ssl_cert_file certificate
# (optional) (string value) # (optional) (string value)
# Deprecated group/name - [amqp1]/ssl_key_file
#ssl_key_file = #ssl_key_file =
# Password for decrypting ssl_key_file (if encrypted) (string # Password for decrypting ssl_key_file (if encrypted) (string
# value) # value)
# Deprecated group/name - [amqp1]/ssl_key_password
#ssl_key_password = <None> #ssl_key_password = <None>
# DEPRECATED: Accept clients using either SSL or plain TCP # DEPRECATED: Accept clients using either SSL or plain TCP
# (boolean value) # (boolean value)
# Deprecated group/name - [amqp1]/allow_insecure_clients
# This option is deprecated for removal. # This option is deprecated for removal.
# Its value may be silently ignored in the future. # Its value may be silently ignored in the future.
# Reason: Not applicable - not a SSL server # Reason: Not applicable - not a SSL server
@ -2574,25 +2560,20 @@
# Space separated list of acceptable SASL mechanisms (string # Space separated list of acceptable SASL mechanisms (string
# value) # value)
# Deprecated group/name - [amqp1]/sasl_mechanisms
#sasl_mechanisms = #sasl_mechanisms =
# Path to directory that contains the SASL configuration # Path to directory that contains the SASL configuration
# (string value) # (string value)
# Deprecated group/name - [amqp1]/sasl_config_dir
#sasl_config_dir = #sasl_config_dir =
# Name of configuration file (without .conf suffix) (string # Name of configuration file (without .conf suffix) (string
# value) # value)
# Deprecated group/name - [amqp1]/sasl_config_name
#sasl_config_name = #sasl_config_name =
# User name for message broker authentication (string value) # User name for message broker authentication (string value)
# Deprecated group/name - [amqp1]/username
#username = #username =
# Password for message broker authentication (string value) # Password for message broker authentication (string value)
# Deprecated group/name - [amqp1]/password
#password = #password =
# Seconds to pause before attempting to re-connect. (integer # Seconds to pause before attempting to re-connect. (integer
@ -2653,17 +2634,14 @@
# address prefix used when sending to a specific server # address prefix used when sending to a specific server
# (string value) # (string value)
# Deprecated group/name - [amqp1]/server_request_prefix
#server_request_prefix = exclusive #server_request_prefix = exclusive
# address prefix used when broadcasting to all servers (string # address prefix used when broadcasting to all servers (string
# value) # value)
# Deprecated group/name - [amqp1]/broadcast_prefix
#broadcast_prefix = broadcast #broadcast_prefix = broadcast
# address prefix when sending to any server in group (string # address prefix when sending to any server in group (string
# value) # value)
# Deprecated group/name - [amqp1]/group_request_prefix
#group_request_prefix = unicast #group_request_prefix = unicast
# Address prefix for all generated RPC addresses (string # Address prefix for all generated RPC addresses (string
@ -2820,7 +2798,6 @@
#amqp_durable_queues = false #amqp_durable_queues = false
# Auto-delete queues in AMQP. (boolean value) # Auto-delete queues in AMQP. (boolean value)
# Deprecated group/name - [DEFAULT]/amqp_auto_delete
#amqp_auto_delete = false #amqp_auto_delete = false
# Enable SSL (boolean value) # Enable SSL (boolean value)
@ -2847,7 +2824,6 @@
# How long to wait before reconnecting in response to an AMQP # How long to wait before reconnecting in response to an AMQP
# consumer cancel notification. (floating point value) # consumer cancel notification. (floating point value)
# Deprecated group/name - [DEFAULT]/kombu_reconnect_delay
#kombu_reconnect_delay = 1.0 #kombu_reconnect_delay = 1.0
# EXPERIMENTAL: Possible values are: gzip, bz2. If not set # EXPERIMENTAL: Possible values are: gzip, bz2. If not set
@ -2870,7 +2846,6 @@
# DEPRECATED: The RabbitMQ broker address where a single node # DEPRECATED: The RabbitMQ broker address where a single node
# is used. (string value) # is used. (string value)
# Deprecated group/name - [DEFAULT]/rabbit_host
# This option is deprecated for removal. # This option is deprecated for removal.
# Its value may be silently ignored in the future. # Its value may be silently ignored in the future.
# Reason: Replaced by [DEFAULT]/transport_url # Reason: Replaced by [DEFAULT]/transport_url
@ -2880,7 +2855,6 @@
# used. (port value) # used. (port value)
# Minimum value: 0 # Minimum value: 0
# Maximum value: 65535 # Maximum value: 65535
# Deprecated group/name - [DEFAULT]/rabbit_port
# This option is deprecated for removal. # This option is deprecated for removal.
# Its value may be silently ignored in the future. # Its value may be silently ignored in the future.
# Reason: Replaced by [DEFAULT]/transport_url # Reason: Replaced by [DEFAULT]/transport_url
@ -2888,21 +2862,18 @@
# DEPRECATED: RabbitMQ HA cluster host:port pairs. (list # DEPRECATED: RabbitMQ HA cluster host:port pairs. (list
# value) # value)
# Deprecated group/name - [DEFAULT]/rabbit_hosts
# This option is deprecated for removal. # This option is deprecated for removal.
# Its value may be silently ignored in the future. # Its value may be silently ignored in the future.
# Reason: Replaced by [DEFAULT]/transport_url # Reason: Replaced by [DEFAULT]/transport_url
#rabbit_hosts = $rabbit_host:$rabbit_port #rabbit_hosts = $rabbit_host:$rabbit_port
# DEPRECATED: The RabbitMQ userid. (string value) # DEPRECATED: The RabbitMQ userid. (string value)
# Deprecated group/name - [DEFAULT]/rabbit_userid
# This option is deprecated for removal. # This option is deprecated for removal.
# Its value may be silently ignored in the future. # Its value may be silently ignored in the future.
# Reason: Replaced by [DEFAULT]/transport_url # Reason: Replaced by [DEFAULT]/transport_url
#rabbit_userid = guest #rabbit_userid = guest
# DEPRECATED: The RabbitMQ password. (string value) # DEPRECATED: The RabbitMQ password. (string value)
# Deprecated group/name - [DEFAULT]/rabbit_password
# This option is deprecated for removal. # This option is deprecated for removal.
# Its value may be silently ignored in the future. # Its value may be silently ignored in the future.
# Reason: Replaced by [DEFAULT]/transport_url # Reason: Replaced by [DEFAULT]/transport_url
@ -2910,11 +2881,9 @@
# The RabbitMQ login method. (string value) # The RabbitMQ login method. (string value)
# Allowed values: PLAIN, AMQPLAIN, RABBIT-CR-DEMO # Allowed values: PLAIN, AMQPLAIN, RABBIT-CR-DEMO
# Deprecated group/name - [DEFAULT]/rabbit_login_method
#rabbit_login_method = AMQPLAIN #rabbit_login_method = AMQPLAIN
# DEPRECATED: The RabbitMQ virtual host. (string value) # DEPRECATED: The RabbitMQ virtual host. (string value)
# Deprecated group/name - [DEFAULT]/rabbit_virtual_host
# This option is deprecated for removal. # This option is deprecated for removal.
# Its value may be silently ignored in the future. # Its value may be silently ignored in the future.
# Reason: Replaced by [DEFAULT]/transport_url # Reason: Replaced by [DEFAULT]/transport_url
@ -2926,7 +2895,6 @@
# How long to backoff for between retries when connecting to # How long to backoff for between retries when connecting to
# RabbitMQ. (integer value) # RabbitMQ. (integer value)
# Deprecated group/name - [DEFAULT]/rabbit_retry_backoff
#rabbit_retry_backoff = 2 #rabbit_retry_backoff = 2
# Maximum interval of RabbitMQ connection retries. Default is # Maximum interval of RabbitMQ connection retries. Default is
@ -2935,7 +2903,6 @@
# DEPRECATED: Maximum number of RabbitMQ connection retries. # DEPRECATED: Maximum number of RabbitMQ connection retries.
# Default is 0 (infinite retry count). (integer value) # Default is 0 (infinite retry count). (integer value)
# Deprecated group/name - [DEFAULT]/rabbit_max_retries
# This option is deprecated for removal. # This option is deprecated for removal.
# Its value may be silently ignored in the future. # Its value may be silently ignored in the future.
#rabbit_max_retries = 0 #rabbit_max_retries = 0
@ -2948,7 +2915,6 @@
# generated names) are mirrored across all nodes, run: # generated names) are mirrored across all nodes, run:
# "rabbitmqctl set_policy HA '^(?!amq\.).*' '{"ha-mode": # "rabbitmqctl set_policy HA '^(?!amq\.).*' '{"ha-mode":
# "all"}' " (boolean value) # "all"}' " (boolean value)
# Deprecated group/name - [DEFAULT]/rabbit_ha_queues
#rabbit_ha_queues = false #rabbit_ha_queues = false
# Positive integer representing duration in seconds for queue # Positive integer representing duration in seconds for queue
@ -2973,7 +2939,6 @@
# Deprecated, use rpc_backend=kombu+memory or rpc_backend=fake # Deprecated, use rpc_backend=kombu+memory or rpc_backend=fake
# (boolean value) # (boolean value)
# Deprecated group/name - [DEFAULT]/fake_rabbit
#fake_rabbit = false #fake_rabbit = false
# Maximum number of channels to allow (integer value) # Maximum number of channels to allow (integer value)
@ -3099,31 +3064,25 @@
# ZeroMQ bind address. Should be a wildcard (*), an ethernet # ZeroMQ bind address. Should be a wildcard (*), an ethernet
# interface, or IP. The "host" option should point or resolve # interface, or IP. The "host" option should point or resolve
# to this address. (string value) # to this address. (string value)
# Deprecated group/name - [DEFAULT]/rpc_zmq_bind_address
#rpc_zmq_bind_address = * #rpc_zmq_bind_address = *
# MatchMaker driver. (string value) # MatchMaker driver. (string value)
# Allowed values: redis, sentinel, dummy # Allowed values: redis, sentinel, dummy
# Deprecated group/name - [DEFAULT]/rpc_zmq_matchmaker
#rpc_zmq_matchmaker = redis #rpc_zmq_matchmaker = redis
# Number of ZeroMQ contexts, defaults to 1. (integer value) # Number of ZeroMQ contexts, defaults to 1. (integer value)
# Deprecated group/name - [DEFAULT]/rpc_zmq_contexts
#rpc_zmq_contexts = 1 #rpc_zmq_contexts = 1
# Maximum number of ingress messages to locally buffer per # Maximum number of ingress messages to locally buffer per
# topic. Default is unlimited. (integer value) # topic. Default is unlimited. (integer value)
# Deprecated group/name - [DEFAULT]/rpc_zmq_topic_backlog
#rpc_zmq_topic_backlog = <None> #rpc_zmq_topic_backlog = <None>
# Directory for holding IPC sockets. (string value) # Directory for holding IPC sockets. (string value)
# Deprecated group/name - [DEFAULT]/rpc_zmq_ipc_dir
#rpc_zmq_ipc_dir = /var/run/openstack #rpc_zmq_ipc_dir = /var/run/openstack
# Name of this node. Must be a valid hostname, FQDN, or IP # Name of this node. Must be a valid hostname, FQDN, or IP
# address. Must match "host" option, if running Nova. (string # address. Must match "host" option, if running Nova. (string
# value) # value)
# Deprecated group/name - [DEFAULT]/rpc_zmq_host
#rpc_zmq_host = localhost #rpc_zmq_host = localhost
# Number of seconds to wait before all pending messages will # Number of seconds to wait before all pending messages will
@ -3139,26 +3098,21 @@
# The default number of seconds that poll should wait. Poll # The default number of seconds that poll should wait. Poll
# raises timeout exception when timeout expired. (integer # raises timeout exception when timeout expired. (integer
# value) # value)
# Deprecated group/name - [DEFAULT]/rpc_poll_timeout
#rpc_poll_timeout = 1 #rpc_poll_timeout = 1
# Expiration timeout in seconds of a name service record about # Expiration timeout in seconds of a name service record about
# existing target ( < 0 means no timeout). (integer value) # existing target ( < 0 means no timeout). (integer value)
# Deprecated group/name - [DEFAULT]/zmq_target_expire
#zmq_target_expire = 300 #zmq_target_expire = 300
# Update period in seconds of a name service record about # Update period in seconds of a name service record about
# existing target. (integer value) # existing target. (integer value)
# Deprecated group/name - [DEFAULT]/zmq_target_update
#zmq_target_update = 180 #zmq_target_update = 180
# Use PUB/SUB pattern for fanout methods. PUB/SUB always uses # Use PUB/SUB pattern for fanout methods. PUB/SUB always uses
# proxy. (boolean value) # proxy. (boolean value)
# Deprecated group/name - [DEFAULT]/use_pub_sub
#use_pub_sub = false #use_pub_sub = false
# Use ROUTER remote proxy. (boolean value) # Use ROUTER remote proxy. (boolean value)
# Deprecated group/name - [DEFAULT]/use_router_proxy
#use_router_proxy = false #use_router_proxy = false
# This option makes direct connections dynamic or static. It # This option makes direct connections dynamic or static. It
@ -3175,25 +3129,21 @@
# Minimal port number for random ports range. (port value) # Minimal port number for random ports range. (port value)
# Minimum value: 0 # Minimum value: 0
# Maximum value: 65535 # Maximum value: 65535
# Deprecated group/name - [DEFAULT]/rpc_zmq_min_port
#rpc_zmq_min_port = 49153 #rpc_zmq_min_port = 49153
# Maximal port number for random ports range. (integer value) # Maximal port number for random ports range. (integer value)
# Minimum value: 1 # Minimum value: 1
# Maximum value: 65536 # Maximum value: 65536
# Deprecated group/name - [DEFAULT]/rpc_zmq_max_port
#rpc_zmq_max_port = 65536 #rpc_zmq_max_port = 65536
# Number of retries to find free port number before fail with # Number of retries to find free port number before fail with
# ZMQBindError. (integer value) # ZMQBindError. (integer value)
# Deprecated group/name - [DEFAULT]/rpc_zmq_bind_port_retries
#rpc_zmq_bind_port_retries = 100 #rpc_zmq_bind_port_retries = 100
# Default serialization mechanism for # Default serialization mechanism for
# serializing/deserializing outgoing/incoming messages (string # serializing/deserializing outgoing/incoming messages (string
# value) # value)
# Allowed values: json, msgpack # Allowed values: json, msgpack
# Deprecated group/name - [DEFAULT]/rpc_zmq_serialization
#rpc_zmq_serialization = json #rpc_zmq_serialization = json
# This option configures round-robin mode in zmq socket. True # This option configures round-robin mode in zmq socket. True
@ -3277,12 +3227,10 @@
# #
# The file that defines policies. (string value) # The file that defines policies. (string value)
# Deprecated group/name - [DEFAULT]/policy_file
#policy_file = policy.json #policy_file = policy.json
# Default rule. Enforced when a requested rule is not found. # Default rule. Enforced when a requested rule is not found.
# (string value) # (string value)
# Deprecated group/name - [DEFAULT]/policy_default_rule
#policy_default_rule = default #policy_default_rule = default
# Directories where policy configuration files are stored. # Directories where policy configuration files are stored.
@ -3291,7 +3239,6 @@
# file defined by policy_file must exist for these directories # file defined by policy_file must exist for these directories
# to be searched. Missing or empty directories are ignored. # to be searched. Missing or empty directories are ignored.
# (multi valued) # (multi valued)
# Deprecated group/name - [DEFAULT]/policy_dirs
#policy_dirs = policy.d #policy_dirs = policy.d
@ -3438,11 +3385,11 @@
#project_domain_name = <None> #project_domain_name = <None>
# Project ID to scope to (string value) # Project ID to scope to (string value)
# Deprecated group/name - [service_catalog]/tenant-id # Deprecated group/name - [service_catalog]/tenant_id
#project_id = <None> #project_id = <None>
# Project name to scope to (string value) # Project name to scope to (string value)
# Deprecated group/name - [service_catalog]/tenant-name # Deprecated group/name - [service_catalog]/tenant_name
#project_name = <None> #project_name = <None>
# Tenant ID (string value) # Tenant ID (string value)
@ -3467,7 +3414,7 @@
#user_id = <None> #user_id = <None>
# Username (string value) # Username (string value)
# Deprecated group/name - [service_catalog]/user-name # Deprecated group/name - [service_catalog]/user_name
#username = <None> #username = <None>
@ -3589,11 +3536,11 @@
#project_domain_name = <None> #project_domain_name = <None>
# Project ID to scope to (string value) # Project ID to scope to (string value)
# Deprecated group/name - [swift]/tenant-id # Deprecated group/name - [swift]/tenant_id
#project_id = <None> #project_id = <None>
# Project name to scope to (string value) # Project name to scope to (string value)
# Deprecated group/name - [swift]/tenant-name # Deprecated group/name - [swift]/tenant_name
#project_name = <None> #project_name = <None>
# Maximum number of times to retry a Swift request, before # Maximum number of times to retry a Swift request, before
@ -3622,5 +3569,5 @@
#user_id = <None> #user_id = <None>
# Username (string value) # Username (string value)
# Deprecated group/name - [swift]/user-name # Deprecated group/name - [swift]/user_name
#username = <None> #username = <None>

View File

@ -104,14 +104,15 @@ def _get_attachment_id(node, volume):
# attachment for each node that represents all possible attachment # attachment for each node that represents all possible attachment
# information as multiple types can be submitted in a single request. # information as multiple types can be submitted in a single request.
attachments = volume.attachments attachments = volume.attachments
if attachments is not None: if attachments is None:
return
for attachment in attachments: for attachment in attachments:
if attachment.get('server_id') in (node.instance_uuid, node.uuid): if attachment.get('server_id') in (node.instance_uuid, node.uuid):
return attachment.get('attachment_id') return attachment.get('attachment_id')
def _create_metadata_dictionary(node, action): def _create_metadata_dictionary(node, action):
"""Create a volume metadata dictionary utilizing the node UUID. """Create a volume metadata dictionary.
:param node: Object representing a node. :param node: Object representing a node.
:param action: String value representing the last action. :param action: String value representing the last action.
@ -121,12 +122,12 @@ def _create_metadata_dictionary(node, action):
label = "ironic_node_%s" % node.uuid label = "ironic_node_%s" % node.uuid
return { return {
label: { label: {
'instance_uuid': node.instance_uuid, 'instance_uuid': node.instance_uuid or node.uuid,
'last_seen': datetime.datetime.utcnow().isoformat(), 'last_seen': datetime.datetime.utcnow().isoformat(),
'last_action': action}} 'last_action': action}}
def _init_client_for_operations(task): def _init_client(task):
"""Obtain cinder client and return it for use. """Obtain cinder client and return it for use.
:param task: TaskManager instance representing the operation. :param task: TaskManager instance representing the operation.
@ -138,8 +139,8 @@ def _init_client_for_operations(task):
try: try:
return get_client() return get_client()
except Exception as e: except Exception as e:
msg = (_('Failed to initialize cinder client for node %(uuid)s: %(' msg = (_('Failed to initialize cinder client for operations on node '
'err)s') % {'uuid': node.uuid, 'err': e}) '%(uuid)s: %(err)s') % {'uuid': node.uuid, 'err': e})
LOG.error(msg) LOG.error(msg)
raise exception.StorageError(msg) raise exception.StorageError(msg)
@ -181,7 +182,6 @@ def attach_volumes(task, volume_list, connector):
} }
:raises: StorageError If storage subsystem exception is raised. :raises: StorageError If storage subsystem exception is raised.
:raises: TypeError If the supplied volume_list is not a list.
:returns: List of connected volumes, including volumes that were :returns: List of connected volumes, including volumes that were
already connected to desired nodes. The returned list already connected to desired nodes. The returned list
can be relatively consistent depending on the end storage can be relatively consistent depending on the end storage
@ -232,7 +232,7 @@ def attach_volumes(task, volume_list, connector):
}] }]
""" """
node = task.node node = task.node
client = _init_client_for_operations(task) client = _init_client(task)
connected = [] connected = []
for volume_id in volume_list: for volume_id in volume_list:
@ -271,10 +271,6 @@ def attach_volumes(task, volume_list, connector):
# Provide connector information to cinder # Provide connector information to cinder
connection = client.volumes.initialize_connection(volume_id, connection = client.volumes.initialize_connection(volume_id,
connector) connector)
if 'volume_id' not in connection['data']:
connection['data']['volume_id'] = volume_id
connection['data']['ironic_volume_uuid'] = volume.uuid
connected.append(connection)
except cinder_exceptions.ClientException as e: except cinder_exceptions.ClientException as e:
msg = (_('Failed to initialize connection for volume ' msg = (_('Failed to initialize connection for volume '
'%(vol_id)s to node %(node)s: %(err)s') % '%(vol_id)s to node %(node)s: %(err)s') %
@ -282,6 +278,11 @@ def attach_volumes(task, volume_list, connector):
LOG.error(msg) LOG.error(msg)
raise exception.StorageError(msg) raise exception.StorageError(msg)
if 'volume_id' not in connection['data']:
connection['data']['volume_id'] = volume_id
connection['data']['ironic_volume_uuid'] = volume.uuid
connected.append(connection)
LOG.info('Successfully initialized volume %(vol_id)s for ' LOG.info('Successfully initialized volume %(vol_id)s for '
'node %(node)s.', {'vol_id': volume_id, 'node': node.uuid}) 'node %(node)s.', {'vol_id': volume_id, 'node': node.uuid})
@ -351,7 +352,6 @@ def detach_volumes(task, volume_list, connector, allow_errors=False):
:param allow_errors: Boolean value governing if errors that are returned :param allow_errors: Boolean value governing if errors that are returned
are treated as warnings instead of exceptions. are treated as warnings instead of exceptions.
Default False. Default False.
:raises: TypeError If the supplied volume_list is not a sequence.
:raises: StorageError :raises: StorageError
""" """
def _handle_errors(msg): def _handle_errors(msg):
@ -361,7 +361,7 @@ def detach_volumes(task, volume_list, connector, allow_errors=False):
LOG.error(msg) LOG.error(msg)
raise exception.StorageError(msg) raise exception.StorageError(msg)
client = _init_client_for_operations(task) client = _init_client(task)
node = task.node node = task.node
for volume_id in volume_list: for volume_id in volume_list:

View File

@ -20,11 +20,14 @@ opts = [
cfg.StrOpt('url', cfg.StrOpt('url',
regex='^http(s?):\/\/.+', regex='^http(s?):\/\/.+',
help=_('URL for connecting to cinder. If set, the value must ' help=_('URL for connecting to cinder. If set, the value must '
'start with either http:// or https://.')), 'start with either http:// or https://. This option is '
'part of boot-from-volume work, which is not currently '
'exposed to users.')),
cfg.IntOpt('retries', cfg.IntOpt('retries',
default=3, default=3,
help=_('Client retries in the case of a failed request ' help=_('Client retries in the case of a failed request '
'connection.')), 'connection. This option is part of boot-from-volume '
'work, which is not currently exposed to users.')),
] ]

View File

@ -11,12 +11,11 @@
# 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 mock
from cinderclient import exceptions as cinder_exceptions from cinderclient import exceptions as cinder_exceptions
import cinderclient.v3 as cinderclient import cinderclient.v3 as cinderclient
import mock
from oslo_utils import uuidutils from oslo_utils import uuidutils
from six.moves import http_client from six.moves import http_client
from ironic.common import cinder from ironic.common import cinder
@ -108,10 +107,6 @@ class TestCinderUtils(db_base.DbTestCase):
self.context, self.context,
instance_uuid=uuidutils.generate_uuid()) instance_uuid=uuidutils.generate_uuid())
def test_cinder_states(self):
self.assertEqual('available', cinder.AVAILABLE)
self.assertEqual('in-use', cinder.IN_USE)
def test_is_volume_available(self): def test_is_volume_available(self):
available_volumes = [ available_volumes = [
mock.Mock(status=cinder.AVAILABLE, multiattach=False), mock.Mock(status=cinder.AVAILABLE, multiattach=False),
@ -122,13 +117,13 @@ class TestCinderUtils(db_base.DbTestCase):
for vol in available_volumes: for vol in available_volumes:
result = cinder.is_volume_available(vol) result = cinder.is_volume_available(vol)
self.assertEqual(True, result, self.assertTrue(result,
message="Failed for status '%s'." % vol.status) msg="Failed for status '%s'." % vol.status)
for vol in unavailable_volumes: for vol in unavailable_volumes:
result = cinder.is_volume_available(vol) result = cinder.is_volume_available(vol)
self.assertEqual(False, result, self.assertFalse(result,
message="Failed for status '%s'." % vol.status) msg="Failed for status '%s'." % vol.status)
def test_is_volume_attached(self): def test_is_volume_attached(self):
attached_vol = mock.Mock(id='foo', attachments=[ attached_vol = mock.Mock(id='foo', attachments=[
@ -168,12 +163,9 @@ class TestCinderUtils(db_base.DbTestCase):
} }
result = cinder._create_metadata_dictionary(self.node, 'meow') result = cinder._create_metadata_dictionary(self.node, 'meow')
self.maxDiff = None
# Since datetime is an internal, we can't exactly mock it.
# We can however verify it's presence, and replace it.
self.assertIsInstance(result[expected_key]['last_seen'], str) self.assertIsInstance(result[expected_key]['last_seen'], str)
result[expected_key]['last_seen'] = 'faked-time' result[expected_key]['last_seen'] = 'faked-time'
self.assertDictEqual(expected, result) self.assertEqual(expected, result)
@mock.patch.object(cinder, '_get_cinder_session', autospec=True) @mock.patch.object(cinder, '_get_cinder_session', autospec=True)
@ -229,7 +221,7 @@ class TestCinderActions(db_base.DbTestCase):
with task_manager.acquire(self.context, self.node.uuid) as task: with task_manager.acquire(self.context, self.node.uuid) as task:
attachments = cinder.attach_volumes(task, volumes, connector) attachments = cinder.attach_volumes(task, volumes, connector)
self.assertDictEqual(expected[0], attachments[0]) self.assertEqual(expected, attachments)
mock_reserve.assert_called_once_with(mock.ANY, volume_id) mock_reserve.assert_called_once_with(mock.ANY, volume_id)
mock_init.assert_called_once_with(mock.ANY, volume_id, connector) mock_init.assert_called_once_with(mock.ANY, volume_id, connector)
mock_attach.assert_called_once_with(mock.ANY, volume_id, mock_attach.assert_called_once_with(mock.ANY, volume_id,
@ -292,12 +284,13 @@ class TestCinderActions(db_base.DbTestCase):
mock_set_meta.assert_called_once_with(mock.ANY, volume_id, mock_set_meta.assert_called_once_with(mock.ANY, volume_id,
{'bar': 'baz'}) {'bar': 'baz'})
@mock.patch.object(cinderclient.Client, '__init__') @mock.patch.object(cinderclient.Client, '__init__', autospec=True)
def test_attach_volumes_client_init_failure( def test_attach_volumes_client_init_failure(
self, mock_client, mock_get, mock_set_meta, mock_session): self, mock_client, mock_get, mock_set_meta, mock_session):
connector = {'foo': 'bar'} connector = {'foo': 'bar'}
volumes = ['111111111-0000-0000-0000-000000000003'] volumes = ['111111111-0000-0000-0000-000000000003']
mock_client.side_effect = cinder_exceptions.BadRequest(400) mock_client.side_effect = cinder_exceptions.BadRequest(
http_client.BAD_REQUEST)
with task_manager.acquire(self.context, self.node.uuid) as task: with task_manager.acquire(self.context, self.node.uuid) as task:
self.assertRaises(exception.StorageError, self.assertRaises(exception.StorageError,
@ -318,9 +311,10 @@ class TestCinderActions(db_base.DbTestCase):
mock_get, mock_set_meta, mock_session): mock_get, mock_set_meta, mock_session):
"""Raise an error if the volume lookup fails""" """Raise an error if the volume lookup fails"""
def __mock_get_side_effect(*args, **kwargs): def __mock_get_side_effect(client, volume_id):
if args[1] == 'not_found': if volume_id == 'not_found':
raise cinder_exceptions.NotFound(404, message='error') raise cinder_exceptions.NotFound(
http_client.NOT_FOUND, message='error')
else: else:
return mock.Mock(attachments=[], uuid='000-000') return mock.Mock(attachments=[], uuid='000-000')
@ -362,7 +356,8 @@ class TestCinderActions(db_base.DbTestCase):
volume = mock.Mock(attachments=[]) volume = mock.Mock(attachments=[])
mock_get.return_value = volume mock_get.return_value = volume
mock_is_attached.return_value = False mock_is_attached.return_value = False
mock_reserve.side_effect = cinder_exceptions.NotAcceptable(406) mock_reserve.side_effect = cinder_exceptions.NotAcceptable(
http_client.NOT_ACCEPTABLE)
with task_manager.acquire(self.context, self.node.uuid) as task: with task_manager.acquire(self.context, self.node.uuid) as task:
self.assertRaises(exception.StorageError, self.assertRaises(exception.StorageError,
@ -389,7 +384,8 @@ class TestCinderActions(db_base.DbTestCase):
mock_create_meta.return_value = {'bar': 'baz'} mock_create_meta.return_value = {'bar': 'baz'}
mock_is_attached.return_value = False mock_is_attached.return_value = False
mock_get.return_value = mock.Mock(attachments=[]) mock_get.return_value = mock.Mock(attachments=[])
mock_init.side_effect = cinder_exceptions.NotAcceptable(406) mock_init.side_effect = cinder_exceptions.NotAcceptable(
http_client.NOT_ACCEPTABLE)
with task_manager.acquire(self.context, self.node.uuid) as task: with task_manager.acquire(self.context, self.node.uuid) as task:
self.assertRaises(exception.StorageError, self.assertRaises(exception.StorageError,
@ -426,8 +422,8 @@ class TestCinderActions(db_base.DbTestCase):
'target_iqn': 'iqn.2010-10.org.openstack:volume-00000002', 'target_iqn': 'iqn.2010-10.org.openstack:volume-00000002',
'target_portal': '127.0.0.0.1:3260', 'target_portal': '127.0.0.0.1:3260',
'target_lun': 2}} 'target_lun': 2}}
mock_attach.side_effect = cinder_exceptions.ClientException(406, mock_attach.side_effect = cinder_exceptions.ClientException(
'error') http_client.NOT_ACCEPTABLE, 'error')
with task_manager.acquire(self.context, self.node.uuid) as task: with task_manager.acquire(self.context, self.node.uuid) as task:
self.assertRaises(exception.StorageError, cinder.attach_volumes, self.assertRaises(exception.StorageError, cinder.attach_volumes,
@ -476,12 +472,13 @@ class TestCinderActions(db_base.DbTestCase):
'target_iqn': 'iqn.2010-10.org.openstack:volume-00000002', 'target_iqn': 'iqn.2010-10.org.openstack:volume-00000002',
'target_portal': '127.0.0.0.1:3260', 'target_portal': '127.0.0.0.1:3260',
'target_lun': 2}} 'target_lun': 2}}
mock_set_meta.side_effect = cinder_exceptions.NotAcceptable(406) mock_set_meta.side_effect = cinder_exceptions.NotAcceptable(
http_client.NOT_ACCEPTABLE)
with task_manager.acquire(self.context, self.node.uuid) as task: with task_manager.acquire(self.context, self.node.uuid) as task:
attachments = cinder.attach_volumes(task, volumes, connector) attachments = cinder.attach_volumes(task, volumes, connector)
self.assertDictEqual(expected[0], attachments[0]) self.assertEqual(expected, attachments)
mock_reserve.assert_called_once_with(mock.ANY, volume_id) mock_reserve.assert_called_once_with(mock.ANY, volume_id)
mock_init.assert_called_once_with(mock.ANY, volume_id, connector) mock_init.assert_called_once_with(mock.ANY, volume_id, connector)
mock_attach.assert_called_once_with(mock.ANY, volume_id, mock_attach.assert_called_once_with(mock.ANY, volume_id,
@ -556,22 +553,28 @@ class TestCinderActions(db_base.DbTestCase):
{'bar': 'baz'}) {'bar': 'baz'})
@mock.patch.object(cinderclient.Client, '__init__', autospec=True) @mock.patch.object(cinderclient.Client, '__init__', autospec=True)
def test_detach_volumes_client_init_failure( def test_detach_volumes_client_init_failure_bad_request(
self, mock_client, mock_get, mock_set_meta, mock_session): self, mock_client, mock_get, mock_set_meta, mock_session):
connector = {'foo': 'bar'} connector = {'foo': 'bar'}
volumes = ['111111111-0000-0000-0000-000000000003'] volumes = ['111111111-0000-0000-0000-000000000003']
with task_manager.acquire(self.context, self.node.uuid) as task: with task_manager.acquire(self.context, self.node.uuid) as task:
mock_client.side_effect = cinder_exceptions.BadRequest(400) mock_client.side_effect = cinder_exceptions.BadRequest(
http_client.BAD_REQUEST)
self.assertRaises(exception.StorageError, self.assertRaises(exception.StorageError,
cinder.detach_volumes, cinder.detach_volumes,
task, task,
volumes, volumes,
connector) connector)
# While we would be permitting failures, this is an
# exception that must be raised since the client @mock.patch.object(cinderclient.Client, '__init__', autospec=True)
# cannot be initialized. def test_detach_volumes_client_init_failure_invalid_parameter_value(
self, mock_client, mock_get, mock_set_meta, mock_session):
connector = {'foo': 'bar'}
volumes = ['111111111-0000-0000-0000-000000000003']
with task_manager.acquire(self.context, self.node.uuid) as task:
# While we would be permitting failures, this is an exception that
# must be raised since the client cannot be initialized.
mock_client.side_effect = exception.InvalidParameterValue('error') mock_client.side_effect = exception.InvalidParameterValue('error')
self.assertRaises(exception.StorageError, self.assertRaises(exception.StorageError,
cinder.detach_volumes, task, volumes, cinder.detach_volumes, task, volumes,
@ -583,7 +586,7 @@ class TestCinderActions(db_base.DbTestCase):
volumes = ['vol1'] volumes = ['vol1']
connector = {'foo': 'bar'} connector = {'foo': 'bar'}
mock_get.side_effect = cinder_exceptions.NotFound( mock_get.side_effect = cinder_exceptions.NotFound(
404, message='error') http_client.NOT_FOUND, message='error')
with task_manager.acquire(self.context, self.node.uuid) as task: with task_manager.acquire(self.context, self.node.uuid) as task:
self.assertRaises(exception.StorageError, self.assertRaises(exception.StorageError,
@ -616,7 +619,8 @@ class TestCinderActions(db_base.DbTestCase):
mock_get.return_value = volume mock_get.return_value = volume
mock_create_meta.return_value = {'bar': 'baz'} mock_create_meta.return_value = {'bar': 'baz'}
mock_is_attached.return_value = True mock_is_attached.return_value = True
mock_begin.side_effect = cinder_exceptions.NotAcceptable(406) mock_begin.side_effect = cinder_exceptions.NotAcceptable(
http_client.NOT_ACCEPTABLE)
with task_manager.acquire(self.context, self.node.uuid) as task: with task_manager.acquire(self.context, self.node.uuid) as task:
self.assertRaises(exception.StorageError, self.assertRaises(exception.StorageError,
@ -648,7 +652,8 @@ class TestCinderActions(db_base.DbTestCase):
mock_create_meta.return_value = {'bar': 'baz'} mock_create_meta.return_value = {'bar': 'baz'}
mock_is_attached.return_value = True mock_is_attached.return_value = True
mock_get.return_value = {'id': volume_id, 'attachments': []} mock_get.return_value = {'id': volume_id, 'attachments': []}
mock_term.side_effect = cinder_exceptions.NotAcceptable(406) mock_term.side_effect = cinder_exceptions.NotAcceptable(
http_client.NOT_ACCEPTABLE)
with task_manager.acquire(self.context, self.node.uuid) as task: with task_manager.acquire(self.context, self.node.uuid) as task:
self.assertRaises(exception.StorageError, self.assertRaises(exception.StorageError,
@ -669,38 +674,21 @@ class TestCinderActions(db_base.DbTestCase):
autospec=True) autospec=True)
@mock.patch.object(cinder, 'is_volume_attached', autospec=True) @mock.patch.object(cinder, 'is_volume_attached', autospec=True)
@mock.patch.object(cinder, '_create_metadata_dictionary', autospec=True) @mock.patch.object(cinder, '_create_metadata_dictionary', autospec=True)
def test_detach_volumes_detach_meta_failure( def test_detach_volumes_detach_failure_errors_not_allowed(
self, mock_create_meta, mock_is_attached, mock_begin, mock_term, self, mock_create_meta, mock_is_attached, mock_begin, mock_term,
mock_detach, mock_get, mock_set_meta, mock_session): mock_detach, mock_get, mock_set_meta, mock_session):
volume_id = '111111111-0000-0000-0000-000000000003' volume_id = '111111111-0000-0000-0000-000000000003'
volumes = [volume_id] volumes = [volume_id]
connector = {'foo': 'bar'} connector = {'foo': 'bar'}
mock_create_meta.return_value = {'bar': 'baz'} mock_create_meta.return_value = {'bar': 'baz'}
mock_is_attached.return_value = True mock_is_attached.return_value = True
mock_get.return_value = mock.Mock(attachments=[ mock_get.return_value = mock.Mock(attachments=[
{'server_id': self.node.uuid, 'attachment_id': 'qux'}]) {'server_id': self.node.uuid, 'attachment_id': 'qux'}])
with task_manager.acquire(self.context, self.node.uuid) as task:
mock_detach.side_effect = cinder_exceptions.NotAcceptable( mock_detach.side_effect = cinder_exceptions.NotAcceptable(
http_client.NOT_ACCEPTABLE) http_client.NOT_ACCEPTABLE)
cinder.detach_volumes(task, volumes, connector, allow_errors=True)
mock_detach.assert_called_once_with(mock.ANY, volume_id, 'qux')
mock_set_meta.assert_called_once_with(mock.ANY, volume_id,
{'bar': 'baz'})
mock_detach.reset_mock()
mock_set_meta.reset_mock()
mock_set_meta.side_effect = cinder_exceptions.NotAcceptable(
http_client.NOT_ACCEPTABLE)
cinder.detach_volumes(task, volumes, connector, allow_errors=True)
mock_detach.assert_called_once_with(mock.ANY, volume_id, 'qux')
mock_set_meta.assert_called_once_with(mock.ANY, volume_id,
{'bar': 'baz'})
mock_detach.reset_mock()
mock_set_meta.reset_mock()
with task_manager.acquire(self.context, self.node.uuid) as task:
self.assertRaises(exception.StorageError, self.assertRaises(exception.StorageError,
cinder.detach_volumes, cinder.detach_volumes,
task, task,
@ -709,3 +697,59 @@ class TestCinderActions(db_base.DbTestCase):
allow_errors=False) allow_errors=False)
mock_detach.assert_called_once_with(mock.ANY, volume_id, 'qux') mock_detach.assert_called_once_with(mock.ANY, volume_id, 'qux')
self.assertFalse(mock_set_meta.called) self.assertFalse(mock_set_meta.called)
@mock.patch.object(cinderclient.volumes.VolumeManager, 'detach',
autospec=True)
@mock.patch.object(cinderclient.volumes.VolumeManager,
'terminate_connection', autospec=True)
@mock.patch.object(cinderclient.volumes.VolumeManager, 'begin_detaching',
autospec=True)
@mock.patch.object(cinder, 'is_volume_attached', autospec=True)
@mock.patch.object(cinder, '_create_metadata_dictionary', autospec=True)
def test_detach_volumes_detach_failure_errors_allowed(
self, mock_create_meta, mock_is_attached, mock_begin, mock_term,
mock_detach, mock_get, mock_set_meta, mock_session):
volume_id = '111111111-0000-0000-0000-000000000003'
volumes = [volume_id]
connector = {'foo': 'bar'}
mock_create_meta.return_value = {'bar': 'baz'}
mock_is_attached.return_value = True
mock_get.return_value = mock.Mock(attachments=[
{'server_id': self.node.uuid, 'attachment_id': 'qux'}])
mock_set_meta.side_effect = cinder_exceptions.NotAcceptable(
http_client.NOT_ACCEPTABLE)
with task_manager.acquire(self.context, self.node.uuid) as task:
cinder.detach_volumes(task, volumes, connector, allow_errors=True)
mock_detach.assert_called_once_with(mock.ANY, volume_id, 'qux')
mock_set_meta.assert_called_once_with(mock.ANY, volume_id,
{'bar': 'baz'})
@mock.patch.object(cinderclient.volumes.VolumeManager, 'detach',
autospec=True)
@mock.patch.object(cinderclient.volumes.VolumeManager,
'terminate_connection', autospec=True)
@mock.patch.object(cinderclient.volumes.VolumeManager, 'begin_detaching',
autospec=True)
@mock.patch.object(cinder, 'is_volume_attached', autospec=True)
@mock.patch.object(cinder, '_create_metadata_dictionary', autospec=True)
def test_detach_volumes_detach_meta_failure_errors_not_allowed(
self, mock_create_meta, mock_is_attached, mock_begin, mock_term,
mock_detach, mock_get, mock_set_meta, mock_session):
volume_id = '111111111-0000-0000-0000-000000000003'
volumes = [volume_id]
connector = {'foo': 'bar'}
mock_create_meta.return_value = {'bar': 'baz'}
mock_is_attached.return_value = True
mock_get.return_value = mock.Mock(attachments=[
{'server_id': self.node.uuid, 'attachment_id': 'qux'}])
mock_set_meta.side_effect = cinder_exceptions.NotAcceptable(
http_client.NOT_ACCEPTABLE)
with task_manager.acquire(self.context, self.node.uuid) as task:
cinder.detach_volumes(task, volumes, connector, allow_errors=False)
mock_detach.assert_called_once_with(mock.ANY, volume_id, 'qux')
mock_set_meta.assert_called_once_with(mock.ANY, volume_id,
{'bar': 'baz'})

View File

@ -0,0 +1,4 @@
---
other:
- Adds a configuration section ``cinder`` and a requirement of
cinder client (python-cinderclient).