Example #1
0
 def test_dict_of_dicts(self):
     self.type_instance = types.Dict(
         types.Dict(types.String(), bounds=True)
     )
     self.assertConvertedValue('k1:{k1:v1,k2:v2},k2:{k3:v3}',
                               {'k1': {'k1': 'v1', 'k2': 'v2'},
                                'k2': {'k3': 'v3'}})
Example #2
0
    def _get_pdu_opts(cls):
        return [
            cfg.Opt(
                name="pdu_servers",
                type=types.Dict(
                    value_type=types.String(),
                ),
                help="A mapping between PDU names and their endpoint "
                     "(IP/FQDN)",
                sample_default=(
                    "[my_data_puller]\n"
                    "#pdu_servers=PDU_1:127.0.0.1,PDU_2:192.168.1.1")
            ),
            cfg.MultiOpt(
                name="mapping",
                item_type=types.Dict(
                    value_type=types.List(
                        bounds=True,
                        item_type=types.Dict(
                            value_type=types.Integer()
                        ),
                    ),
                ),
                help="Each entry specified here should be an entry mapping a "
                     "PDU name to a list of servers. Each server is a pair "
                     "between its endpoint and its related outlet ID.",
                sample_default=(
                    "[my_data_puller]\n"
                    "#mapping = PDU_1:[serv1.hostname:1,serv2.hostname:2]\n"
                    "#mapping = PDU_2:[serv3.hostname:1,serv4.hostname:2]"
                ),

            ),
        ]
Example #3
0
 def get_config_opts(cls):
     return [
         cfg.Opt('weights',
                 type=types.Dict(value_type=types.Integer()),
                 help="These weights are used to schedule the actions",
                 default=cls.weights_dict),
     ]
Example #4
0
def _register_sensor_container_opts(ignore_errors=False):
    logging_opts = [
        cfg.StrOpt('logging',
                   default='conf/logging.sensorcontainer.conf',
                   help='location of the logging.conf file')
    ]

    st2cfg.do_register_opts(logging_opts,
                            group='sensorcontainer',
                            ignore_errors=ignore_errors)

    # Partitioning options
    partition_opts = [
        cfg.StrOpt('sensor_node_name',
                   default='sensornode1',
                   help='name of the sensor node.'),
        cfg.Opt('partition_provider',
                type=types.Dict(value_type=types.String()),
                default={'name': DEFAULT_PARTITION_LOADER},
                help='Provider of sensor node partition config.')
    ]

    st2cfg.do_register_opts(partition_opts,
                            group='sensorcontainer',
                            ignore_errors=ignore_errors)

    # Other options
    other_opts = [
        cfg.BoolOpt(
            'single_sensor_mode',
            default=False,
            help=
            'Run in a single sensor mode where parent process exits when a sensor crashes / '
            'dies. This is useful in environments where partitioning, sensor process life '
            'cycle and failover is handled by a 3rd party service such as kubernetes.'
        )
    ]

    st2cfg.do_register_opts(other_opts,
                            group='sensorcontainer',
                            ignore_errors=ignore_errors)

    # CLI options
    cli_opts = [
        cfg.StrOpt(
            'sensor-ref',
            help=
            'Only run sensor with the provided reference. Value is of the form '
            '<pack>.<sensor-name> (e.g. linux.FileWatchSensor).'),
        cfg.BoolOpt(
            'single-sensor-mode',
            default=False,
            help=
            'Run in a single sensor mode where parent process exits when a sensor crashes / '
            'dies. This is useful in environments where partitioning, sensor process life '
            'cycle and failover is handled by a 3rd party service such as kubernetes.'
        )
    ]

    st2cfg.do_register_cli_opts(cli_opts, ignore_errors=ignore_errors)
def _register_sensor_container_opts(ignore_errors=False):
    logging_opts = [
        cfg.StrOpt('logging',
                   default='conf/logging.sensorcontainer.conf',
                   help='location of the logging.conf file')
    ]
    st2cfg.do_register_opts(logging_opts,
                            group='sensorcontainer',
                            ignore_errors=ignore_errors)

    partition_opts = [
        cfg.StrOpt('sensor_node_name',
                   default='sensornode1',
                   help='name of the sensor node.'),
        cfg.Opt('partition_provider',
                type=types.Dict(value_type=types.String()),
                default={'name': DEFAULT_PARTITION_LOADER},
                help='Provider of sensor node partition config.')
    ]
    st2cfg.do_register_opts(partition_opts,
                            group='sensorcontainer',
                            ignore_errors=ignore_errors)

    sensor_test_opt = cfg.StrOpt(
        'sensor-ref',
        help='Only run sensor with the provided reference. \
        Value is of the form pack.sensor-name.')
    st2cfg.do_register_cli_opts(sensor_test_opt, ignore_errors=ignore_errors)
Example #6
0
 def get_config_opts(cls):
     return [
         cfg.Opt(
             'weights',
             type=types.Dict(value_type=types.Integer()),
             help="These weights are used to schedule the actions. "
                  "Action Plan will be build in accordance with sets of "
                  "actions ordered by descending weights."
                  "Two action types cannot have the same weight. ",
             default=cls.action_weights),
         cfg.Opt(
             'parallelization',
             type=types.Dict(value_type=types.Integer()),
             help="Number of actions to be run in parallel on a per "
                  "action type basis.",
             default=cls.parallelization),
     ]
Example #7
0
def _register_sensor_container_opts():
    partition_opts = [
        cfg.StrOpt('sensor_node_name', default='sensornode1',
                   help='name of the sensor node.'),
        cfg.Opt('partition_provider', type=types.Dict(value_type=types.String()),
                default={'name': DEFAULT_PARTITION_LOADER},
                help='Provider of sensor node partition config.')
    ]
    _register_opts(partition_opts, group='sensorcontainer')

    sensor_test_opt = cfg.StrOpt('sensor-ref', help='Only run sensor with the provided reference. \
        Value is of the form pack.sensor-name.')
    _register_cli_opts([sensor_test_opt])
Example #8
0
def _register_sensor_container_opts():
    partition_opts = [
        cfg.StrOpt("sensor_node_name",
                   default="sensornode1",
                   help="name of the sensor node."),
        cfg.Opt(
            "partition_provider",
            type=types.Dict(value_type=types.String()),
            default={"name": DEFAULT_PARTITION_LOADER},
            help="Provider of sensor node partition config.",
        ),
    ]

    _register_opts(partition_opts, group="sensorcontainer")

    # Other options
    other_opts = [
        cfg.BoolOpt(
            "single_sensor_mode",
            default=False,
            help=
            "Run in a single sensor mode where parent process exits when a sensor crashes / "
            "dies. This is useful in environments where partitioning, sensor process life "
            "cycle and failover is handled by a 3rd party service such as kubernetes.",
        )
    ]

    _register_opts(other_opts, group="sensorcontainer")

    # CLI options
    cli_opts = [
        cfg.StrOpt(
            "sensor-ref",
            help=
            "Only run sensor with the provided reference. Value is of the form "
            "<pack>.<sensor-name> (e.g. linux.FileWatchSensor).",
        ),
        cfg.BoolOpt(
            "single-sensor-mode",
            default=False,
            help=
            "Run in a single sensor mode where parent process exits when a sensor crashes / "
            "dies. This is useful in environments where partitioning, sensor process life "
            "cycle and failover is handled by a 3rd party service such as kubernetes.",
        ),
    ]

    _register_cli_opts(cli_opts)
Example #9
0
 def test_equal_with_equal_custom_item_types(self):
     it1 = types.Integer()
     it2 = types.Integer()
     self.assertTrue(types.Dict(it1) == types.Dict(it2))
Example #10
0
 def test_equal(self):
     self.assertTrue(types.Dict() == types.Dict())
Example #11
0
 def test_repr(self):
     t = types.Dict(types.Integer())
     self.assertEqual('Dict of Integer', repr(t))
Example #12
0
 def test_bounds_required(self):
     self.type_instance = types.Dict(types.String(), bounds=True)
     self.assertInvalid('foo:bar,baz:123')
     self.assertInvalid('{foo:bar,baz:123')
     self.assertInvalid('foo:bar,baz:123}')
Example #13
0
 def test_bounds_parsing(self):
     self.type_instance = types.Dict(types.String(), bounds=True)
     self.assertConvertedValue('{foo:bar,baz:123}', {
         'foo': 'bar',
         'baz': '123'
     })
Example #14
0
 def test_dict_of_values_containing_commas(self):
     self.type_instance = types.Dict(types.String(quotes=True))
     self.assertConvertedValue('foo:"bar, baz",bam:quux', {
         'foo': 'bar, baz',
         'bam': 'quux'
     })
Example #15
0
 def test_custom_value_type(self):
     self.type_instance = types.Dict(types.Integer())
     self.assertConvertedValue('foo:123, bar: 456', {
         'foo': 123,
         'bar': 456
     })
Example #16
0
            default=60,
            help='The maximum time in seconds that the cached aggregates '
            'status will be considered valid. Trying to read the '
            'expired cache leads to refreshing it.'),
 cfg.BoolOpt('netapp_enable_flexgroup',
             default=False,
             help='Specify if the FlexGroup pool is enabled. When it is '
             'enabled, the driver will report a single pool '
             'representing all aggregates (ONTAP chooses on which the '
             'share will be allocated). If you want to Manila control '
             'the aggregate selection, you can configure its custom '
             'FlexGroup pools through netapp_flexgroup_pools option. '
             'The FlexGroup placement is done either by ONTAP or '
             'Manila, not both.'),
 cfg.MultiOpt('netapp_flexgroup_pools',
              item_type=types.Dict(value_type=types.String()),
              default={},
              help="Multi opt of dict to represent the FlexGroup pools. "
              "A FlexGroup pool is configured with its name and its "
              "list of aggregates. Specify this option as many times "
              "as you have FlexGroup pools. Each entry takes the "
              "dict config form: "
              "netapp_flexgroup_pools = "
              "<pool_name>: <aggr_name1> <aggr_name2> .."),
 cfg.BoolOpt('netapp_flexgroup_pool_only',
             default=False,
             help='Specify if the FlexVol pools must not be reported when '
             'the netapp_enable_flexgroup is enabled.'),
 cfg.IntOpt(
     'netapp_flexgroup_volume_online_timeout',
     min=60,
Example #17
0
 def test_not_equal_with_non_equal_custom_item_types(self):
     it1 = types.Integer()
     it2 = types.String()
     self.assertFalse(it1 == it2)
     self.assertFalse(types.Dict(it1) == types.Dict(it2))
Example #18
0
The default is the same for both failure types (host, instance) but the value
can be overridden to make the metadata key different per failure type.
    """),
]

taskflow_options = [
    cfg.StrOpt('connection',
               help="""
The SQLAlchemy connection string to use to connect to the taskflow database.
"""),
]

taskflow_driver_recovery_flows = [
    cfg.Opt('host_auto_failure_recovery_tasks',
            type=types.Dict(bounds=False,
                            value_type=types.List(
                                bounds=True,
                                item_type=types.String(quotes=True))),
            default={
                'pre': ['disable_compute_service_task'],
                'main': ['prepare_HA_enabled_instances_task'],
                'post': ['evacuate_instances_task']
            },
            help=("""
This option allows operator to customize tasks to be executed for host failure
auto recovery workflow.

Provide list of strings reflecting to the task classes that should be included
to the host failure recovery workflow. The full classname path of all task
classes should be defined in the 'masakari.task_flow.tasks' of setup.cfg and
these classes may be implemented by OpenStack Masaskari project team, deployer
or third party.
Example #19
0
opts = [
    cfg.IntOpt('registration_attempts',
               min=1,
               default=5,
               help='Number of attempts to register a service. Currently '
               'has to be larger than 1 because of race conditions '
               'in the zeroconf library.'),
    cfg.IntOpt('lookup_attempts',
               min=1,
               default=3,
               help='Number of attempts to lookup a service.'),
    cfg.Opt(
        'params',
        # This is required for values that contain commas.
        type=cfg_types.Dict(cfg_types.String(quotes=True)),
        default={},
        help='Additional parameters to pass for the registered '
        'service.'),
    cfg.ListOpt('interfaces',
                help='List of IP addresses of interfaces to use for mDNS. '
                'Defaults to all interfaces on the system.'),
]

CONF = cfg.CONF
opt_group = cfg.OptGroup(name='mdns', title='Options for multicast DNS')
CONF.register_group(opt_group)
CONF.register_opts(opts, opt_group)

LOG = logging.getLogger(__name__)
Example #20
0
     'physnet',
     help=_('This is required if Nexus VXLAN overlay feature is '
            'configured.  It should be the physical network name defined '
            'in "network_vlan_ranges" (defined beneath the "ml2_type_vlan" '
            'section) that this switch is controlling.  The configured '
            '"physnet" is the physical network domain that is connected '
            'to this switch. The vlan ranges defined in '
            '"network_vlan_ranges" for a physical '
            'network are allocated dynamically and are unique per physical '
            'network. These dynamic vlans may be reused across physical '
            'networks.  This configuration applies to non-baremetal '
            'only.')),
 cfg.Opt('host_ports_mapping',
         default={},
         sample_default='<None>',
         type=types.Dict(value_type=types.List(bounds=True)),
         help=_(
             'A list of key:value pairs describing which host is '
             'connected to which physical port or portchannel on the '
             'Nexus switch. The format should look like:\n'
             'host_port_mapping='
             '<your-hostname>:[<intf_type><port>,<intf_type><port>],\n'
             '                  <your-second-host>:[<intf_type><port>]\n'
             'For example:\n'
             'host_port_mapping='
             'host-1:[ethernet1/1, ethernet1/2],\n'
             '                  host-2:[ethernet1/3],\n'
             '                  host-3:[port-channel20]\n'
             'Lines can be broken with indentation to ensure config files '
             'remain readable. '
             'All compute nodes must be configured while '
Example #21
0
 def test_not_equal_to_other_class(self):
     self.assertFalse(types.Dict() == types.Integer())
Example #22
0
class DictTypeTests(TypeTestHelper, unittest.TestCase):
    type = types.Dict()

    def test_empty_value(self):
        self.assertConvertedValue('', {})

    def test_single_value(self):
        self.assertConvertedValue(' foo: bar ', {'foo': 'bar'})

    def test_dict_of_values(self):
        self.assertConvertedValue(' foo: bar, baz: 123 ', {
            'foo': 'bar',
            'baz': '123'
        })

    def test_custom_value_type(self):
        self.type_instance = types.Dict(types.Integer())
        self.assertConvertedValue('foo:123, bar: 456', {
            'foo': 123,
            'bar': 456
        })

    def test_dict_of_values_containing_commas(self):
        self.type_instance = types.Dict(types.String(quotes=True))
        self.assertConvertedValue('foo:"bar, baz",bam:quux', {
            'foo': 'bar, baz',
            'bam': 'quux'
        })

    def test_dict_of_dicts(self):
        self.type_instance = types.Dict(types.Dict(types.String(),
                                                   bounds=True))
        self.assertConvertedValue('k1:{k1:v1,k2:v2},k2:{k3:v3}', {
            'k1': {
                'k1': 'v1',
                'k2': 'v2'
            },
            'k2': {
                'k3': 'v3'
            }
        })

    def test_bounds_parsing(self):
        self.type_instance = types.Dict(types.String(), bounds=True)
        self.assertConvertedValue('{foo:bar,baz:123}', {
            'foo': 'bar',
            'baz': '123'
        })

    def test_bounds_required(self):
        self.type_instance = types.Dict(types.String(), bounds=True)
        self.assertInvalid('foo:bar,baz:123')
        self.assertInvalid('{foo:bar,baz:123')
        self.assertInvalid('foo:bar,baz:123}')

    def test_no_mapping_produces_error(self):
        self.assertInvalid('foo,bar')

    def test_repr(self):
        t = types.Dict(types.Integer())
        self.assertEqual('Dict of Integer', repr(t))

    def test_equal(self):
        self.assertTrue(types.Dict() == types.Dict())

    def test_equal_with_equal_custom_item_types(self):
        it1 = types.Integer()
        it2 = types.Integer()
        self.assertTrue(types.Dict(it1) == types.Dict(it2))

    def test_not_equal_with_non_equal_custom_item_types(self):
        it1 = types.Integer()
        it2 = types.String()
        self.assertFalse(it1 == it2)
        self.assertFalse(types.Dict(it1) == types.Dict(it2))

    def test_not_equal_to_other_class(self):
        self.assertFalse(types.Dict() == types.Integer())
Example #23
0
    cfg.StrOpt('vcpu_pin_set',
               help="""
Defines which physical CPUs (pCPUs) can be used by instance
virtual CPUs (vCPUs).

Possible values:

* A comma-separated list of physical CPU numbers that virtual CPUs can be
  allocated to by default. Each element should be either a single CPU number,
  a range of CPU numbers, or a caret followed by a CPU number to be
  excluded from a previous range. For example:

    vcpu_pin_set = "4-12,^8,15"
"""),
    cfg.MultiOpt('reserved_huge_pages',
                 item_type=types.Dict(),
                 help="""
Number of huge/large memory pages to reserved per NUMA host cell.

Possible values:

* A list of valid key=value which reflect NUMA node ID, page size
  (Default unit is KiB) and number of pages to be reserved.

    reserved_huge_pages = node:0,size:2048,count:64
    reserved_huge_pages = node:1,size:1GB,count:1

  In this example we are reserving on NUMA node 0 64 pages of 2MiB
  and on NUMA node 1 1 page of 1GiB.
"""),
    cfg.IntOpt('reserved_host_disk_mb',
Example #24
0
def register_volume():
    volume_opts = [
        cfg.IntOpt(
            'num_shell_tries',
            default=3,
            help='Number of times to attempt to run flakey shell commands'),
        cfg.IntOpt('reserved_percentage',
                   default=0,
                   min=0,
                   max=100,
                   help='The percentage of backend capacity is reserved'),
        cfg.StrOpt('iscsi_target_prefix',
                   default='iqn.2010-10.org.openstack:',
                   help='Prefix for iSCSI volumes'),
        cfg.StrOpt(
            'iscsi_ip_address',
            default='$my_ip',
            help='The IP address that the iSCSI daemon is listening on'),
        cfg.ListOpt(
            'iscsi_secondary_ip_addresses',
            default=[],
            help='The list of secondary IP addresses of the iSCSI daemon'),
        cfg.PortOpt('iscsi_port',
                    default=3260,
                    help='The port that the iSCSI daemon is listening on'),
        cfg.IntOpt('num_volume_device_scan_tries',
                   default=3,
                   help='The maximum number of times to rescan targets'
                   ' to find volume'),
        cfg.StrOpt('volume_backend_name',
                   help='The backend name for a given driver implementation'),
        cfg.BoolOpt(
            'use_multipath_for_image_xfer',
            default=False,
            help='Do we attach/detach volumes in cinder using multipath '
            'for volume to image and image to volume transfers?'),
        cfg.BoolOpt('enforce_multipath_for_image_xfer',
                    default=False,
                    help='If this is set to True, attachment of volumes for '
                    'image transfer will be aborted when multipathd is not '
                    'running. Otherwise, it will fallback to single path.'),
        cfg.StrOpt('volume_clear',
                   default='zero',
                   choices=['none', 'zero', 'shred'],
                   help='Method used to wipe old volumes'),
        cfg.IntOpt(
            'volume_clear_size',
            default=0,
            help='Size in MiB to wipe at start of old volumes. 0 => all'),
        cfg.StrOpt('volume_clear_ionice',
                   help='The flag to pass to ionice to alter the i/o priority '
                   'of the process used to zero a volume after deletion, '
                   'for example "-c3" for idle only priority.'),
        cfg.StrOpt(
            'iscsi_helper',
            default='tgtadm',
            choices=[
                'tgtadm', 'lioadm', 'scstadmin', 'iseradm', 'iscsictl',
                'ietadm', 'fake'
            ],
            help='iSCSI target user-land tool to use. tgtadm is default, '
            'use lioadm for LIO iSCSI support, scstadmin for SCST '
            'target support, iseradm for the ISER protocol, ietadm '
            'for iSCSI Enterprise Target, iscsictl for Chelsio iSCSI '
            'Target or fake for testing.'),
        cfg.StrOpt('volumes_dir',
                   default='$state_path/volumes',
                   help='Volume configuration file storage '
                   'directory'),
        cfg.StrOpt('iet_conf',
                   default='/etc/iet/ietd.conf',
                   help='IET configuration file'),
        cfg.StrOpt('chiscsi_conf',
                   default='/etc/chelsio-iscsi/chiscsi.conf',
                   help='Chiscsi (CXT) global defaults configuration file'),
        cfg.StrOpt('iscsi_iotype',
                   default='fileio',
                   choices=['blockio', 'fileio', 'auto'],
                   help=('Sets the behavior of the iSCSI target '
                         'to either perform blockio or fileio '
                         'optionally, auto can be set and Cinder '
                         'will autodetect type of backing device')),
        cfg.StrOpt('volume_dd_blocksize',
                   default='1M',
                   help='The default block size used when copying/clearing '
                   'volumes'),
        cfg.StrOpt('volume_copy_blkio_cgroup_name',
                   default='cinder-volume-copy',
                   help='The blkio cgroup name to be used to limit bandwidth '
                   'of volume copy'),
        cfg.IntOpt('volume_copy_bps_limit',
                   default=0,
                   help='The upper limit of bandwidth of volume copy. '
                   '0 => unlimited'),
        cfg.StrOpt('iscsi_write_cache',
                   default='on',
                   choices=['on', 'off'],
                   help='Sets the behavior of the iSCSI target to either '
                   'perform write-back(on) or write-through(off). '
                   'This parameter is valid if iscsi_helper is set '
                   'to tgtadm or iseradm.'),
        cfg.StrOpt('iscsi_target_flags',
                   default='',
                   help='Sets the target-specific flags for the iSCSI target. '
                   'Only used for tgtadm to specify backing device flags '
                   'using bsoflags option. The specified string is passed '
                   'as is to the underlying tool.'),
        cfg.StrOpt('iscsi_protocol',
                   default='iscsi',
                   choices=['iscsi', 'iser'],
                   help='Determines the iSCSI protocol for new iSCSI volumes, '
                   'created with tgtadm or lioadm target helpers. In '
                   'order to enable RDMA, this parameter should be set '
                   'with the value "iser". The supported iSCSI protocol '
                   'values are "iscsi" and "iser".'),
        cfg.StrOpt(
            'driver_client_cert_key',
            help='The path to the client certificate key for verification, '
            'if the driver supports it.'),
        cfg.StrOpt('driver_client_cert',
                   help='The path to the client certificate for verification, '
                   'if the driver supports it.'),
        cfg.BoolOpt('driver_use_ssl',
                    default=False,
                    help='Tell driver to use SSL for connection to backend '
                    'storage if the driver supports it.'),
        cfg.FloatOpt(
            'max_over_subscription_ratio',
            default=3.0,
            help='Float representation of the over subscription ratio '
            'when thin provisioning is involved. Default ratio is '
            '3.0, meaning provisioned capacity can be 3 times of '
            'the total physical capacity. If the ratio is 10.5, it '
            'means provisioned capacity can be 10.5 times of the '
            'total physical capacity. A ratio of 1.0 means '
            'provisioned capacity cannot exceed the total physical '
            'capacity. The ratio has to be a minimum of 1.0.'),
        cfg.StrOpt('scst_target_iqn_name',
                   help='Certain ISCSI targets have predefined target names, '
                   'SCST target driver uses this name.'),
        cfg.StrOpt('scst_target_driver',
                   default='iscsi',
                   help='SCST target implementation can choose from multiple '
                   'SCST target drivers.'),
        cfg.BoolOpt('use_chap_auth',
                    default=False,
                    help='Option to enable/disable CHAP authentication for '
                    'targets.',
                    deprecated_opts=deprecated_use_chap_auth_opts),
        cfg.StrOpt('chap_username',
                   default='',
                   help='CHAP user name.',
                   deprecated_opts=deprecated_chap_username_opts),
        cfg.StrOpt('chap_password',
                   default='',
                   help='Password for specified CHAP account name.',
                   deprecated_opts=deprecated_chap_password_opts,
                   secret=True),
        cfg.StrOpt('driver_data_namespace',
                   help='Namespace for driver private data values to be '
                   'saved in.'),
        cfg.StrOpt('filter_function',
                   help='String representation for an equation that will be '
                   'used to filter hosts. Only used when the driver '
                   'filter is set to be used by the Cinder scheduler.'),
        cfg.StrOpt('goodness_function',
                   help='String representation for an equation that will be '
                   'used to determine the goodness of a host. Only used '
                   'when using the goodness weigher is set to be used by '
                   'the Cinder scheduler.'),
        cfg.BoolOpt(
            'driver_ssl_cert_verify',
            default=False,
            help='If set to True the http client will validate the SSL '
            'certificate of the backend endpoint.'),
        cfg.StrOpt('driver_ssl_cert_path',
                   help='Can be used to specify a non default path to a '
                   'CA_BUNDLE file or directory with certificates of '
                   'trusted CAs, which will be used to validate the backend'),
        cfg.ListOpt('trace_flags',
                    help='List of options that control which trace info '
                    'is written to the DEBUG log level to assist '
                    'developers. Valid values are method and api.'),
        cfg.MultiOpt(
            'replication_device',
            item_type=types.Dict(),
            secret=True,
            help="Multi opt of dictionaries to represent a replication "
            "target device.  This option may be specified multiple "
            "times in a single config section to specify multiple "
            "replication target devices.  Each entry takes the "
            "standard dict config form: replication_device = "
            "target_device_id:<required>,"
            "key1:value1,key2:value2..."),
        cfg.BoolOpt('image_upload_use_cinder_backend',
                    default=False,
                    help='If set to True, upload-to-image in raw format will '
                    'create a cloned volume and register its location to '
                    'the image service, instead of uploading the volume '
                    'content. The cinder backend and locations support '
                    'must be enabled in the image service, and '
                    'glance_api_version must be set to 2.'),
        cfg.BoolOpt('image_upload_use_internal_tenant',
                    default=False,
                    help='If set to True, the image volume created by '
                    'upload-to-image will be placed in the internal tenant. '
                    'Otherwise, the image volume is created in the current '
                    'context\'s tenant.'),
        cfg.BoolOpt('image_volume_cache_enabled',
                    default=False,
                    help='Enable the image volume cache for this backend.'),
        cfg.IntOpt(
            'image_volume_cache_max_size_gb',
            default=0,
            help='Max size of the image volume cache for this backend in '
            'GB. 0 => unlimited.'),
        cfg.IntOpt(
            'image_volume_cache_max_count',
            default=0,
            help='Max number of entries allowed in the image volume cache. '
            '0 => unlimited.'),
        cfg.BoolOpt(
            'report_discard_supported',
            default=False,
            help='Report to clients of Cinder that the backend supports '
            'discard (aka. trim/unmap). This will not actually '
            'change the behavior of the backend or the client '
            'directly, it will only notify that it can be used.'),
    ]

    # _option_group = 'oslo_reports'
    # conf.register_opts(_options, group=_option_group)
    CONF.register_opts(volume_opts, group="normal")