# encoding: utf-8
#
# Cookbook Name:: openstack-block-storage

require_relative 'spec_helper'

describe 'openstack-block-storage::cinder-common' do
  describe 'ubuntu' do
    let(:runner) { ChefSpec::Runner.new(UBUNTU_OPTS) }
    let(:node) { runner.node }
    let(:chef_run) do
      node.set['openstack']['mq']['host'] = '127.0.0.1'
      node.set['openstack']['mq']['block-storage']['rabbit']['notification_topic'] = 'rabbit_topic'

      runner.converge(described_recipe)
    end

    include_context 'block-storage-stubs'

    it 'upgrades the cinder-common package' do
      expect(chef_run).to upgrade_package 'cinder-common'
    end

    describe '/etc/cinder' do
      let(:dir) { chef_run.directory('/etc/cinder') }

      it 'should create the /etc/cinder directory' do
        expect(chef_run).to create_directory(dir.name)
      end

      it 'has proper owner' do
        expect(dir.owner).to eq('cinder')
        expect(dir.group).to eq('cinder')
      end

      it 'has proper modes' do
        expect(sprintf('%o', dir.mode)).to eq '750'
      end
    end

    describe 'cinder.conf' do
      let(:file) { chef_run.template('/etc/cinder/cinder.conf') }
      let(:test_pass) { 'test_pass' }
      before do
        endpoint = double(port: 'port', host: 'host', scheme: 'scheme')
        allow_any_instance_of(Chef::Recipe).to receive(:endpoint)
          .with('image-api')
          .and_return(endpoint)
        allow_any_instance_of(Chef::Recipe).to receive(:endpoint)
          .with('identity-admin')
          .and_return(endpoint)
        allow_any_instance_of(Chef::Recipe).to receive(:endpoint)
          .with('identity-api')
          .and_return(endpoint)
        allow_any_instance_of(Chef::Recipe).to receive(:endpoint)
          .with('block-storage-api-bind')
          .and_return(endpoint)
        allow_any_instance_of(Chef::Recipe).to receive(:auth_uri_transform)
          .and_return('auth_uri_transform')
        allow_any_instance_of(Chef::Recipe).to receive(:get_password)
          .with('user', anything)
          .and_return(test_pass)
      end

      it 'should create the cinder.conf template' do
        expect(chef_run).to create_template(file.name)
      end

      it 'has proper owner' do
        expect(file.owner).to eq('cinder')
        expect(file.group).to eq('cinder')
      end

      it 'has proper modes' do
        expect(sprintf('%o', file.mode)).to eq '640'
      end

      context 'keystone authtoken attributes with default values' do
        it 'sets memcached server(s)' do
          expect(chef_run).not_to render_file(file.name).with_content(/^memcached_servers = $/)
        end

        it 'sets memcache security strategy' do
          expect(chef_run).not_to render_file(file.name).with_content(/^memcache_security_strategy = $/)
        end

        it 'sets memcache secret key' do
          expect(chef_run).not_to render_file(file.name).with_content(/^memcache_secret_key = $/)
        end

        it 'sets cafile' do
          expect(chef_run).not_to render_file(file.name).with_content(/^cafile = $/)
        end

        it 'sets insecure' do
          expect(chef_run).to render_file(file.name).with_content(/^insecure = false$/)
        end

        it 'sets token hash algorithms' do
          expect(chef_run).to render_file(file.name).with_content(/^hash_algorithms = md5$/)
        end
      end

      context 'keystone authtoken attributes' do
        it 'has signing_dir' do
          node.set['openstack']['block-storage']['api']['auth']['cache_dir'] = 'auth_cache_dir'

          expect(chef_run).to render_file(file.name).with_content(/^signing_dir = auth_cache_dir$/)
        end

        it 'sets memcached server(s)' do
          node.set['openstack']['block-storage']['api']['auth']['memcached_servers'] = 'localhost:11211'
          expect(chef_run).to render_file(file.name).with_content(/^memcached_servers = localhost:11211$/)
        end

        it 'sets memcache security strategy' do
          node.set['openstack']['block-storage']['api']['auth']['memcache_security_strategy'] = 'MAC'
          expect(chef_run).to render_file(file.name).with_content(/^memcache_security_strategy = MAC$/)
        end

        it 'sets memcache secret key' do
          node.set['openstack']['block-storage']['api']['auth']['memcache_secret_key'] = '0123456789ABCDEF'
          expect(chef_run).to render_file(file.name).with_content(/^memcache_secret_key = 0123456789ABCDEF$/)
        end

        it 'sets cafile' do
          node.set['openstack']['block-storage']['api']['auth']['cafile'] = 'dir/to/path'
          expect(chef_run).to render_file(file.name).with_content(%r{^cafile = dir/to/path$})
        end

        it 'sets insecure' do
          node.set['openstack']['block-storage']['api']['auth']['insecure'] = true
          expect(chef_run).to render_file(file.name).with_content(/^insecure = true$/)
        end

        it 'sets token hash algorithms' do
          node.set['openstack']['block-storage']['api']['auth']['hash_algorithms'] = 'sha2'
          expect(chef_run).to render_file(file.name).with_content(/^hash_algorithms = sha2$/)
        end

        context 'endpoint related' do

          it 'has auth_uri' do
            expect(chef_run).to render_file(file.name).with_content(/^auth_uri = auth_uri_transform$/)
          end

          it 'has auth_host' do
            expect(chef_run).to render_file(file.name).with_content(/^auth_host = host$/)
          end

          it 'has auth_port' do
            expect(chef_run).to render_file(file.name).with_content(/^auth_port = port$/)
          end

          it 'has auth_protocol' do
            expect(chef_run).to render_file(file.name).with_content(/^auth_protocol = scheme$/)
          end
        end

        it 'has no auth_version when auth_version is v2.0' do
          node.set['openstack']['block-storage']['api']['auth']['version'] = 'v2.0'

          expect(chef_run).not_to render_file(file.name).with_content(/^auth_version = v2.0$/)
        end

        it 'has auth_version when auth version is not v2.0' do
          node.set['openstack']['block-storage']['api']['auth']['version'] = 'v3.0'

          expect(chef_run).to render_file(file.name).with_content(/^auth_version = v3.0$/)
        end

        it 'has an admin tenant name' do
          node.set['openstack']['block-storage']['service_tenant_name'] = 'tenant_name'

          expect(chef_run).to render_file(file.name).with_content(/^admin_tenant_name = tenant_name$/)
        end

        it 'has an admin user' do
          node.set['openstack']['block-storage']['service_user'] = 'username'

          expect(chef_run).to render_file(file.name).with_content(/^admin_user = username$/)
        end

        it 'has an admin password' do
          # (fgimenez) the get_password mocking is set in spec/spec_helper.rb
          expect(chef_run).to render_file(file.name).with_content(/^admin_password = cinder-pass$/)
        end
      end

      context 'template contents' do

        context 'commonly named attributes' do
          %w(debug verbose lock_path notification_driver
             storage_availability_zone quota_volumes quota_gigabytes quota_driver
             volume_name_template snapshot_name_template osapi_volume_workers
             use_default_quota_class quota_snapshots no_snapshot_gb_quota
             control_exchange max_gigabytes).each do |attr_key|
            it "has a #{attr_key} attribute" do
              node.set['openstack']['block-storage'][attr_key] = "#{attr_key}_value"

              expect(chef_run).to render_file(file.name).with_content(/^#{attr_key}=#{attr_key}_value$/)
            end
          end
        end

        context 'rdb driver' do
          # FIXME(galstrom21): this block needs to check all of the default
          #   rdb_* configuration options
          it 'has default rbd_* options set' do
            node.set['openstack']['block-storage']['volume'] = {
              'driver' => 'cinder.volume.drivers.rbd.RBDDriver'
            }
            expect(chef_run).to render_file(file.name).with_content(/^rbd_/)
            expect(chef_run).not_to render_file(file.name).with_content(/^netapp_/)
          end
        end

        context 'netapp driver' do
          # FIXME(galstrom21): this block needs to check all of the default
          #   netapp_* configuration options
          it 'has default netapp_* options set' do
            node.set['openstack']['block-storage']['volume'] = {
              'driver' => 'cinder.volume.drivers.netapp.NetAppISCSIDriver'
            }
            expect(chef_run).to render_file(file.name).with_content(/^netapp_/)
            expect(chef_run).not_to render_file(file.name).with_content(/^rbd_/)
          end
        end

        context 'syslog use' do
          it 'sets the log_config value when syslog is in use' do
            node.set['openstack']['block-storage']['syslog']['use'] = true

            expect(chef_run).to render_file(file.name)
              .with_content(%r{^log_config = /etc/openstack/logging.conf$})
          end

          it 'sets the log_file value when syslog is not in use' do
            node.set['openstack']['block-storage']['syslog']['use'] = false

            expect(chef_run).to render_file(file.name)
              .with_content(%r{^log_file = /var/log/cinder/cinder.log$})
          end
        end

        it 'has a sql_connection attribute' do
          allow_any_instance_of(Chef::Recipe).to receive(:db_uri)
            .with('block-storage', anything, '').and_return('sql_connection_value')

          expect(chef_run).to render_file(file.name)
            .with_content(/^sql_connection=sql_connection_value$/)
        end

        it 'has a volume_driver attribute' do
          node.set['openstack']['block-storage']['volume']['driver'] = 'volume_driver_value'
          expect(chef_run).to render_file(file.name).with_content(/^volume_driver=volume_driver_value$/)
        end

        it 'has a state_path attribute' do
          node.set['openstack']['block-storage']['volume']['state_path'] = 'state_path_value'
          expect(chef_run).to render_file(file.name).with_content(/^state_path=state_path_value$/)
        end

        context 'glance endpoint' do
          it 'has a glance_api_servers attribute' do
            expect(chef_run).to render_file(file.name).with_content(%r{^glance_api_servers=scheme://host:port$})
          end

          it 'has glance_api_version attribute' do
            expect(chef_run).to render_file(file.name).with_content(/^glance_api_version=1$/)
          end

          it 'has a glance_api_insecure attribute' do
            expect(chef_run).to render_file(file.name).with_content(/^glance_api_insecure=false$/)
          end

          it 'sets insecure for glance' do
            node.set['openstack']['block-storage']['image']['glance_api_insecure'] = true
            expect(chef_run).to render_file(file.name).with_content(/^glance_api_insecure=true$/)
          end

          it 'has a glance_ca_certificates_file attribute' do
            expect(chef_run).to render_file(file.name).with_content(/^glance_ca_certificates_file=$/)
          end

          it 'sets glance_ca_certificates_file attribute' do
            node.set['openstack']['block-storage']['image']['glance_ca_certificates_file'] = 'dir/to/path'
            expect(chef_run).to render_file(file.name).with_content(%r{^glance_ca_certificates_file=dir/to/path$})
          end

          %w(host port).each do |glance_attr|
            it "has a glance #{glance_attr} attribute" do
              expect(chef_run).to render_file(file.name).with_content(/^glance_#{glance_attr}=#{glance_attr}$/)
            end
          end
        end

        it 'has a api_rate_limit attribute' do
          node.set['openstack']['block-storage']['api']['ratelimit'] = 'api_rate_limit_value'
          expect(chef_run).to render_file(file.name).with_content(/^api_rate_limit=api_rate_limit_value$/)
        end

        context 'cinder endpoint' do
          it 'has osapi_volume_listen set' do
            expect(chef_run).to render_file(file.name).with_content(/^osapi_volume_listen=host$/)
          end

          it 'has osapi_volume_listen_port set' do
            expect(chef_run).to render_file(file.name).with_content(/^osapi_volume_listen_port=port$/)
          end
        end

        it 'has a rpc_backend attribute' do
          node.set['openstack']['block_storage']['rpc_backend'] = 'rpc_backend_value'
          expect(chef_run).to render_file(file.name).with_content(/^rpc_backend=rpc_backend_value$/)
        end

        it 'has default RPC/AMQP options set' do
          [/^rpc_backend=cinder.openstack.common.rpc.impl_kombu$/,
           /^rpc_thread_pool_size=64$/,
           /^rpc_conn_pool_size=30$/,
           /^rpc_response_timeout=60$/,
           /^amqp_durable_queues=false$/,
           /^amqp_auto_delete=false$/].each do |line|
            expect(chef_run).to render_file(file.name).with_content(line)
          end
        end

        context 'rabbitmq as mq service' do
          before do
            node.set['openstack']['mq']['block-storage']['service_type'] = 'rabbitmq'
          end

          context 'ha attributes' do
            before do
              node.set['openstack']['mq']['block-storage']['rabbit']['ha'] = true
            end

            it 'has a rabbit_hosts attribute' do
              allow_any_instance_of(Chef::Recipe).to receive(:rabbit_servers)
                .and_return('rabbit_servers_value')

              expect(chef_run).to render_file(file.name).with_content(/^rabbit_hosts=rabbit_servers_value$/)
            end

            %w(host port).each do |attr|
              it "does not have rabbit_#{attr} attribute" do
                expect(chef_run).not_to render_file(file.name).with_content(/^rabbit_#{attr}=/)
              end
            end
          end

          context 'non ha attributes' do
            before do
              node.set['openstack']['mq']['block-storage']['rabbit']['ha'] = false
            end

            %w(host port).each do |attr|
              it "has rabbit_#{attr} attribute" do
                node.set['openstack']['mq']['block-storage']['rabbit'][attr] = "rabbit_#{attr}_value"
                expect(chef_run).to render_file(file.name).with_content(/^rabbit_#{attr}=rabbit_#{attr}_value$/)
              end
            end

            it 'does not have a rabbit_hosts attribute' do
              expect(chef_run).not_to render_file(file.name).with_content(/^rabbit_hosts=/)
            end
          end

          %w(use_ssl userid).each do |attr|
            it "has rabbit_#{attr}" do
              node.set['openstack']['mq']['block-storage']['rabbit'][attr] = "rabbit_#{attr}_value"
              expect(chef_run).to render_file(file.name).with_content(/^rabbit_#{attr}=rabbit_#{attr}_value$/)
            end
          end

          it 'has rabbit_password' do
            expect(chef_run).to render_file(file.name).with_content(/^rabbit_password=#{test_pass}$/)
          end

          it 'has rabbit_virtual_host' do
            node.set['openstack']['mq']['block-storage']['rabbit']['vhost'] = 'vhost_value'
            expect(chef_run).to render_file(file.name).with_content(/^rabbit_virtual_host=vhost_value$/)
          end
        end

        context 'qpid as mq service' do
          before do
            node.set['openstack']['mq']['block-storage']['service_type'] = 'qpid'
          end

          %w(port username sasl_mechanisms reconnect reconnect_timeout reconnect_limit
             reconnect_interval_min reconnect_interval_max reconnect_interval heartbeat protocol
             tcp_nodelay).each do |attr|
            it "has qpid_#{attr} attribute" do
              node.set['openstack']['mq']['block-storage']['qpid'][attr] = "qpid_#{attr}_value"
              expect(chef_run).to render_file(file.name).with_content(/^qpid_#{attr}=qpid_#{attr}_value$/)
            end
          end

          it 'has qpid_hostname' do
            node.set['openstack']['mq']['block-storage']['qpid']['host'] = 'qpid_host_value'
            expect(chef_run).to render_file(file.name).with_content(/^qpid_hostname=qpid_host_value$/)
          end

          it 'has qpid_password' do
            expect(chef_run).to render_file(file.name).with_content(/^qpid_password=#{test_pass}$/)
          end

          it 'has default qpid topology version' do
            expect(chef_run).to render_file(file.name).with_content(/^qpid_topology_version=1$/)
          end

          it 'has qpid notification_topics' do
            node.set['openstack']['mq']['block-storage']['qpid']['notification_topic'] = 'qpid_notification_topic_value'
            expect(chef_run).to render_file(file.name).with_content(/^notification_topics=qpid_notification_topic_value$/)
          end
        end

        context 'lvm settings' do
          before do
            node.set['openstack']['block-storage']['volume']['driver'] = 'cinder.volume.drivers.lvm.LVMISCSIDriver'
          end

          %w(group clear clear_size).each do |attr|
            it "has lvm volume_#{attr} attribute" do
              node.set['openstack']['block-storage']['volume']["volume_#{attr}"] = "volume_#{attr}_value"
              expect(chef_run).to render_file(file.name).with_content(/^volume_#{attr}=volume_#{attr}_value$/)
            end
          end
        end

        context 'commonly named volume attributes' do
          %w(iscsi_ip_address iscsi_port iscsi_helper volumes_dir).each do |attr|
            it "has volume related #{attr} attribute" do
              node.set['openstack']['block-storage']['volume'][attr] = "common_volume_#{attr}_value"
              expect(chef_run).to render_file(file.name).with_content(/^#{attr}=common_volume_#{attr}_value$/)
            end
          end
        end

        context 'rbd attributes' do
          before do
            node.set['openstack']['block-storage']['volume']['driver'] = 'cinder.volume.drivers.rbd.RBDDriver'
          end

          %w(rbd_pool rbd_user rbd_secret_uuid).each do |attr|
            it "has a #{attr} attribute" do
              node.set['openstack']['block-storage'][attr] = "#{attr}_value"
              expect(chef_run).to render_file(file.name).with_content(/^#{attr}=#{attr}_value$/)
            end
          end
        end

        it 'has volume_driver attribute' do
          node.set['openstack']['block-storage']['volume']['driver'] = 'volume_driver_value'
          expect(chef_run).to render_file(file.name).with_content(/^volume_driver=volume_driver_value$/)
        end

        context 'netapp ISCSI settings' do
          before do
            node.set['openstack']['block-storage']['volume']['driver'] = 'cinder.volume.drivers.netapp.NetAppISCSIDriver'
          end

          %w(login password).each do |attr|
            it "has a netapp_#{attr} attribute" do
              node.set['openstack']['block-storage']['netapp']["dfm_#{attr}"] = "dfm_#{attr}_value"
              expect(chef_run).to render_file(file.name).with_content(/^netapp_#{attr}=dfm_#{attr}_value$/)
            end
          end

          %w(hostname port).each do |attr|
            it "has a netapp_server_#{attr} attribute" do
              node.set['openstack']['block-storage']['netapp']["dfm_#{attr}"] = "dfm_#{attr}_value"
              expect(chef_run).to render_file(file.name).with_content(/^netapp_server_#{attr}=dfm_#{attr}_value$/)
            end
          end

          it 'has a netapp_storage_service attribute' do
            node.set['openstack']['block-storage']['netapp']['storage_service'] = 'netapp_storage_service_value'
            expect(chef_run).to render_file(file.name).with_content(/^netapp_storage_service=netapp_storage_service_value$/)
          end
        end

        context 'netapp direct7 mode nfs settings' do
          let(:hostnames) { %w(hostname1 hostname2 hostname3) }
          before do
            node.set['openstack']['block-storage']['volume']['driver'] = 'cinder.volume.drivers.netapp.nfs.NetAppDirect7modeNfsDriver'
            node.set['openstack']['block-storage']['netapp']['netapp_server_hostname'] = hostnames
          end

          %w(mount_point_base shares_config).each do |attr_key|
            it "has a nfs_#{attr_key} attribute" do
              node.set['openstack']['block-storage']['nfs'][attr_key] = "netapp_nfs_#{attr_key}_value"
              expect(chef_run).to render_file(file.name).with_content(/^nfs_#{attr_key}=netapp_nfs_#{attr_key}_value$/)
            end
          end

          it 'has netapp server_hostname attributes' do
            hostnames.each do |hostname|
              expect(chef_run).to render_file(file.name).with_content(/^netapp_server_hostname=#{hostname}$/)
            end
          end

          it 'has a netapp_server_port attribute' do
            node.set['openstack']['block-storage']['netapp']['netapp_server_port'] = 'netapp_server_port_value'
            expect(chef_run).to render_file(file.name).with_content(/^netapp_server_port=netapp_server_port_value$/)
          end

          %w(login password).each do |attr|
            it "has a netapp_#{attr} attribute" do
              node.set['openstack']['block-storage']['netapp']["netapp_server_#{attr}"] = "netapp_#{attr}_value"
              expect(chef_run).to render_file(file.name).with_content(/^netapp_#{attr}=netapp_#{attr}_value$/)
            end
          end

          %w(disk_util sparsed_volumes).each do |attr|
            it "has a nfs_#{attr} attribute" do
              node.set['openstack']['block-storage']['nfs']["nfs_#{attr}"] = "netapp_nfs_#{attr}_value"
              expect(chef_run).to render_file(file.name).with_content(/^nfs_#{attr}=netapp_nfs_#{attr}_value$/)
            end
          end
        end

        context 'ibmnas settings' do
          before do
            node.set['openstack']['block-storage']['volume']['driver'] = 'cinder.volume.drivers.ibm.ibmnas.IBMNAS_NFSDriver'
          end

          %w(mount_point_base shares_config).each do |attr|
            it "has a ibmnas_#{attr} attribute" do
              node.set['openstack']['block-storage']['ibmnas'][attr] = "ibmnas_#{attr}_value"
              expect(chef_run).to render_file(file.name).with_content(/^nfs_#{attr}=ibmnas_#{attr}_value$/)
            end
          end

          it 'has a nfs_sparsed_volumes attribute' do
            node.set['openstack']['block-storage']['ibmnas']['nfs_sparsed_volumes'] = 'ibmnas_nfs_sparsed_volumes_value'
            expect(chef_run).to render_file(file.name).with_content(/^nfs_sparsed_volumes=ibmnas_nfs_sparsed_volumes_value$/)
          end

          %w(nas_ip nas_login nas_ssh_port ibmnas_platform_type).each do |attr|
            it "has a ibmnas #{attr} attribute" do
              node.set['openstack']['block-storage']['ibmnas'][attr] = "ibmnas_#{attr}_value"
              expect(chef_run).to render_file(file.name).with_content(/^#{attr}=ibmnas_#{attr}_value$/)
            end
          end

          it 'has a default attributes' do
            %w(nas_ip=127.0.0.1
               nas_login=admin
               nas_password=test_pass
               nas_ssh_port=22
               ibmnas_platform_type=v7ku
               nfs_sparsed_volumes=true
               nfs_mount_point_base=/mnt/cinder-volumes
               nfs_shares_config=/etc/cinder/nfs_shares.conf).each do |attr|
              expect(chef_run).to render_file(file.name).with_content(/^#{attr}$/)
            end
          end
        end

        context 'storwize settings' do
          before do
            node.set['openstack']['block-storage']['volume']['driver'] = 'cinder.volume.drivers.ibm.storwize_svc.StorwizeSVCDriver'
          end

          it 'has a default attribute' do
            %w(san_ip=127.0.0.1
               san_private_key=/v7000_rsa
               storwize_svc_volpool_name=volpool
               storwize_svc_vol_rsize=2
               storwize_svc_vol_warning=0
               storwize_svc_vol_autoexpand=true
               storwize_svc_vol_grainsize=256
               storwize_svc_vol_compression=false
               storwize_svc_vol_easytier=true
               storwize_svc_vol_iogrp=0
               storwize_svc_flashcopy_timeout=120
               storwize_svc_connection_protocol=iSCSI
               storwize_svc_iscsi_chap_enabled=true
               storwize_svc_multihostmap_enabled=true).each do |attr|
              expect(chef_run).to render_file(file.name).with_content(/^#{attr}$/)
            end
          end

          it 'has a overridden attribute' do
            %w(san_ip
               san_private_key
               storwize_svc_volpool_name
               storwize_svc_vol_rsize
               storwize_svc_vol_warning
               storwize_svc_vol_autoexpand
               storwize_svc_vol_grainsize
               storwize_svc_vol_compression
               storwize_svc_vol_easytier
               storwize_svc_vol_iogrp
               storwize_svc_flashcopy_timeout
               storwize_svc_connection_protocol
               storwize_svc_multihostmap_enabled).each do |attr|
              node.set['openstack']['block-storage']['storwize'][attr] = "storwize_#{attr}_value"
              expect(chef_run).to render_file(file.name).with_content(/^#{attr}=storwize_#{attr}_value$/)
            end
          end

          context 'storwize with login and password' do
            it 'has a login and password' do
              node.set['openstack']['block-storage']['storwize']['san_private_key'] = ''
              %w(san_login=admin
                 san_password=test_pass
                 san_private_key=).each do |attr|
                expect(chef_run).to render_file(file.name).with_content(/^#{attr}$/)
              end
            end
          end

          context 'storwize with iSCSI connection protocol' do
            before do
              node.set['openstack']['block-storage']['storwize']['storwize_svc_connection_protocol'] = 'iSCSI'
            end

            it 'has a iscsi chap enabled attribute' do
              node.set['openstack']['block-storage']['storwize']['storwize_svc_iscsi_chap_enabled'] = 'storwize_svc_iscsi_chap_enabled_value'
              expect(chef_run).to render_file(file.name).with_content(/^storwize_svc_iscsi_chap_enabled=storwize_svc_iscsi_chap_enabled_value$/)
            end

            it 'does not have a multipath enabled attribute' do
              expect(chef_run).not_to render_file(file.name).with_content(/^storwize_svc_multipath_enabled=/)
            end
          end

          context 'storwize without iSCSI connection protocol' do
            before do
              node.set['openstack']['block-storage']['storwize']['storwize_svc_connection_protocol'] = 'non-iSCSI'
            end

            it 'does not have a iscsi chap enabled attribute' do
              expect(chef_run).not_to render_file(file.name).with_content(/^storwize_svc_iscsi_enabled=/)
            end

            it 'has a multipath enabled attribute' do
              node.set['openstack']['block-storage']['storwize']['storwize_svc_multipath_enabled'] = 'storwize_svc_multipath_enabled_value'
              expect(chef_run).to render_file(file.name).with_content(/^storwize_svc_multipath_enabled=storwize_svc_multipath_enabled_value$/)
            end
          end
        end

        context 'solidfire settings' do
          before do
            node.set['openstack']['block-storage']['volume']['driver'] = 'cinder.volume.drivers.solidfire.SolidFire'
          end

          it 'has solidfire sf_emulate set' do
            node.set['openstack']['block-storage']['solidfire']['sf_emulate'] = 'test'
            expect(chef_run).to render_file(file.name).with_content(/^sf_emulate_512=test$/)
          end

          it 'has solidfire password' do
            expect(chef_run).to render_file(file.name).with_content(/^san_password=test_pass$/)
          end

          %w(san_login san_ip).each do |attr|
            it "has solidfire #{attr} set" do
              node.set['openstack']['block-storage']['solidfire'][attr] = "solidfire_#{attr}_value"
              expect(chef_run).to render_file(file.name).with_content(/^#{attr}=solidfire_#{attr}_value$/)
            end
          end

          it 'does not have iscsi_ip_prefix not specified' do
            node.set['openstack']['block-storage']['solidfire']['iscsi_ip_prefix'] = nil
            expect(chef_run).to_not render_file(file.name).with_content(/^iscsi_ip_prefix=/)
          end

          it 'does have iscsi_ip_prefix when specified' do
            chef_run.node.set['openstack']['block-storage']['solidfire']['iscsi_ip_prefix'] = '203.0.113.*'
            expect(chef_run).to render_file(file.name).with_content(/^iscsi_ip_prefix=203.0.113.*$/)
          end
        end

        context 'emc settings' do
          before do
            node.set['openstack']['block-storage']['volume']['driver'] = 'cinder.volume.drivers.emc.emc_smis_iscsi.EMCSMISISCSIDriver'
          end

          %w(iscsi_target_prefix cinder_emc_config_file).each do |attr|
            it "has emc #{attr} set" do
              node.set['openstack']['block-storage']['emc'][attr] = "emc_#{attr}_value"
              expect(chef_run).to render_file(file.name).with_content(/^#{attr}=emc_#{attr}_value$/)
            end
          end
        end

        context 'vmware vmdk settings' do
          before do
            node.set['openstack']['block-storage']['volume']['driver'] = 'cinder.volume.drivers.vmware.vmdk.VMwareVcVmdkDriver'
            %w(vmware_host_ip vmware_host_username
               vmware_api_retry_count vmware_task_poll_interval vmware_volume_folder
               vmware_image_transfer_timeout_secs vmware_max_objects_retrieval).each do |attr|
              node.set['openstack']['block-storage']['vmware'][attr] = "vmware_#{attr}_value"
            end
          end

          it 'has vmware attributes set' do
            node['openstack']['block-storage']['vmware'].each do |attr, val|
              expect(chef_run).to render_file(file.name).with_content(/^#{attr} = #{val}$/)
            end
          end

          it 'has password set which is from databag' do
            expect(chef_run).to render_file(file.name).with_content(/^vmware_host_password = vmware_secret_name$/)
          end

          it 'has no wsdl_location line without the attribute' do
            node.set['openstack']['block-storage']['vmware']['vmware_wsdl_location'] = nil
            expect(chef_run).not_to render_file(file.name).with_content(/^vmware_wsdl_location = /)
          end

          it 'has wsdl_location line with attribute present' do
            node.set['openstack']['block-storage']['vmware']['vmware_wsdl_location'] = 'http://127.0.0.1/wsdl'
            expect(chef_run).to render_file(file.name).with_content(%r(^vmware_wsdl_location = http://127.0.0.1/wsdl$))
          end
        end

        context 'gpfs settings' do
          before do
            node.set['openstack']['block-storage']['volume']['driver'] = 'cinder.volume.drivers.ibm.gpfs.GPFSDriver'
          end

          %w(gpfs_mount_point_base gpfs_max_clone_depth
             gpfs_sparse_volumes gpfs_storage_pool).each do |attr|
            it "has gpfs #{attr} set" do
              node.set['openstack']['block-storage']['gpfs'][attr] = "gpfs_#{attr}_value"
              expect(chef_run).to render_file(file.name).with_content(/^#{attr} = gpfs_#{attr}_value$/)
            end
          end

          it 'has no gpfs_images_dir line without the attribute' do
            node.set['openstack']['block-storage']['gpfs']['gpfs_images_dir'] = nil
            expect(chef_run).not_to render_file(file.name).with_content(/^gpfs_images_dir = /)
            expect(chef_run).not_to render_file(file.name).with_content(/^gpfs_images_share_mode = /)
          end

          it 'has gpfs_images_dir line with attribute present' do
            node.set['openstack']['block-storage']['gpfs']['gpfs_images_dir'] = 'gpfs_images_dir_value'
            expect(chef_run).to render_file(file.name).with_content(/^gpfs_images_dir = gpfs_images_dir_value$/)
            expect(chef_run).to render_file(file.name).with_content(/^gpfs_images_share_mode = copy_on_write$/)
          end

          it 'templates misc_cinder array correctly' do
            node.set['openstack']['block-storage']['misc_cinder'] = ['# Comments', 'MISC=OPTION']
            expect(chef_run).to render_file(file.name).with_content(
              /^# Comments$/)
            expect(chef_run).to render_file(file.name).with_content(
              /^MISC=OPTION$/)
          end
        end

        context 'multiple backend settings' do
          before do
            node.set['openstack']['block-storage']['volume']['multi_backend'] = {
              'lvm' => {
                'volume_driver' => 'cinder.volume.drivers.lvm.LVMISCSIDriver',
                'volume_backend_name' => 'lvmdrv'
              },
              'rbd' => {
                'volume_driver' => 'cinder.volume.drivers.rbd.RBDDriver',
                'volume_backend_name' => 'rbddrv'
              },
              'netapp_iscsi' => {
                'volume_driver' => 'cinder.volume.drivers.netapp.NetAppISCSIDriver',
                'multi_netapp_iscsi' => 'multi-netapp'
              },
              'netapp_nfs' => {
                'volume_driver' => 'cinder.volume.drivers.netapp.nfs.NetAppDirect7modeNfsDriver',
                'volume_backend_name' => 'netappnfsdrv',
                'multi_netapp_nfs' => 'multi-netapp'
              },
              'ibmnas' => {
                'volume_driver' => 'cinder.volume.drivers.ibm.ibmnas.IBMNAS_NFSDriver',
                'multi_ibmnas' => 'multi-ibmnas'
              },
              'ibmsvc' => {
                'volume_driver' => 'cinder.volume.drivers.ibm.storwize_svc.StorwizeSVCDriver',
                'multi_ibmsvc' => 'multi-ibmsvc'
              },
              'solidfire' => {
                'volume_driver' => 'cinder.volume.drivers.solidfire.SolidFire',
                'multi_solidfire' => 'multi-solidfire'
              },
              'emciscsi' => {
                'volume_driver' => 'cinder.volume.drivers.emc.emc_smis_iscsi.EMCSMISISCSIDriver',
                'multi_emciscsi' => 'multi-emciscsi'
              },
              'vmware' => {
                'volume_driver' => 'cinder.volume.drivers.vmware.vmdk.VMwareVcVmdkDriver',
                'multi_vmware' => 'multi-vmware'
              },
              'gpfs' => {
                'volume_driver' => 'cinder.volume.drivers.ibm.gpfs.GPFSDriver',
                'multi_gpfs' => 'multi-gpfs'
              }
            }
            node.set['openstack']['block-storage']['volume']['volume_group'] = 'multi-lvm-group'
            node.set['openstack']['block-storage']['volume']['default_volume_type'] = 'some-type-name'
            node.set['openstack']['block-storage']['rbd_pool'] = 'multi-rbd-pool'
            node.set['openstack']['block-storage']['netapp']['dfm_login'] = 'multi-netapp-login'
            node.set['openstack']['block-storage']['netapp']['netapp_server_hostname'] = ['netapp-host-1', 'netapp-host-2']
            node.set['openstack']['block-storage']['netapp']['netapp_server_port'] = 'multi-netapp-port'
            node.set['openstack']['block-storage']['ibmnas']['shares_config'] = 'multi-ibmnas-share'
            node.set['openstack']['block-storage']['storwize']['storwize_svc_volpool_name'] = 'multi-svc-volpool'
            node.set['openstack']['block-storage']['solidfire']['sf_emulate'] = 'multi-sf-true'
            node.set['openstack']['block-storage']['emc']['cinder_emc_config_file'] = 'multi-emc-conf'
            node.set['openstack']['block-storage']['vmware']['vmware_host_ip'] = 'multi-vmware-ip'
            node.set['openstack']['block-storage']['gpfs']['gpfs_mount_point_base'] = 'multi-gpfs-mnt'
          end

          it 'enable multiple backends' do
            expect(chef_run).to render_file(file.name).with_content(/^enabled_backends = lvm,rbd,netapp_iscsi,netapp_nfs,ibmnas,ibmsvc,solidfire,emciscsi,vmware,gpfs$/)

            expect(chef_run).to render_file(file.name).with_content(/^\[lvm\]$/)
            expect(chef_run).to render_file(file.name).with_content(/^volume_driver = cinder\.volume\.drivers\.lvm\.LVMISCSIDriver$/)

            expect(chef_run).to render_file(file.name).with_content(/^\[rbd\]$/)
            expect(chef_run).to render_file(file.name).with_content(/^volume_driver = cinder\.volume\.drivers\.rbd\.RBDDriver$/)

            expect(chef_run).to render_file(file.name).with_content(/^\[netapp_iscsi\]$/)
            expect(chef_run).to render_file(file.name).with_content(/^volume_driver = cinder\.volume\.drivers\.netapp\.NetAppISCSIDriver$/)

            expect(chef_run).to render_file(file.name).with_content(/^netapp_server_hostname=netapp-host-1$/)
            expect(chef_run).to render_file(file.name).with_content(/^netapp_server_hostname=netapp-host-2$/)
            expect(chef_run).to render_file(file.name).with_content(/^\[netapp_nfs\]$/)
            expect(chef_run).to render_file(file.name).with_content(/^volume_driver = cinder\.volume\.drivers\.netapp\.nfs\.NetAppDirect7modeNfsDriver$/)

            expect(chef_run).to render_file(file.name).with_content(/^\[ibmnas\]$/)
            expect(chef_run).to render_file(file.name).with_content(/^volume_driver = cinder\.volume\.drivers\.ibm\.ibmnas\.IBMNAS_NFSDriver$/)

            expect(chef_run).to render_file(file.name).with_content(/^\[ibmsvc\]$/)
            expect(chef_run).to render_file(file.name).with_content(/^volume_driver = cinder\.volume\.drivers\.ibm\.storwize_svc\.StorwizeSVCDriver$/)

            expect(chef_run).to render_file(file.name).with_content(/^\[solidfire\]$/)
            expect(chef_run).to render_file(file.name).with_content(/^volume_driver = cinder\.volume\.drivers\.solidfire\.SolidFire$/)

            expect(chef_run).to render_file(file.name).with_content(/^\[emciscsi\]$/)
            expect(chef_run).to render_file(file.name).with_content(/^volume_driver = cinder\.volume\.drivers\.emc\.emc_smis_iscsi\.EMCSMISISCSIDriver$/)

            expect(chef_run).to render_file(file.name).with_content(/^\[vmware\]$/)
            expect(chef_run).to render_file(file.name).with_content(/^volume_driver = cinder\.volume\.drivers\.vmware\.vmdk\.VMwareVcVmdkDriver$/)

            expect(chef_run).to render_file(file.name).with_content(/^\[gpfs\]$/)
            expect(chef_run).to render_file(file.name).with_content(/^volume_driver = cinder\.volume\.drivers\.ibm\.gpfs\.GPFSDriver$/)
          end

          it 'set lvm option' do
            expect(chef_run).to render_file(file.name).with_content(/^volume_group=multi-lvm-group$/)
          end

          it 'set default_volume_type option' do
            expect(chef_run).to render_file(file.name).with_content(/^default_volume_type=some-type-name$/)
          end

          it 'set rbd option' do
            expect(chef_run).to render_file(file.name).with_content(/^rbd_pool=multi-rbd-pool$/)
          end

          it 'set netapp_iscsi option' do
            expect(chef_run).to render_file(file.name).with_content(/^netapp_login=multi-netapp-login$/)
          end

          it 'set netapp_nfs option' do
            expect(chef_run).to render_file(file.name).with_content(/^netapp_server_port=multi-netapp-port$/)
          end

          it 'set ibmnas option' do
            expect(chef_run).to render_file(file.name).with_content(/^nfs_shares_config=multi-ibmnas-share$/)
          end

          it 'set ibmsvc option' do
            expect(chef_run).to render_file(file.name).with_content(/^storwize_svc_volpool_name=multi-svc-volpool$/)
          end

          it 'set solidfire option' do
            expect(chef_run).to render_file(file.name).with_content(/^sf_emulate_512=multi-sf-true$/)
          end

          it 'set emciscsi option' do
            expect(chef_run).to render_file(file.name).with_content(/^cinder_emc_config_file=multi-emc-conf$/)
          end

          it 'set vmware option' do
            expect(chef_run).to render_file(file.name).with_content(/^vmware_host_ip = multi-vmware-ip$/)
          end

          it 'set gpfs option' do
            expect(chef_run).to render_file(file.name).with_content(/^gpfs_mount_point_base = multi-gpfs-mnt$/)
          end

        end

        it 'no multiple backends configured' do
          expect(chef_run).to_not render_file(file.name).with_content(/^enabled_backends = [\w\W]+$/)
        end

        it 'does not set default_volume_type' do
          expect(chef_run).to_not render_file(file.name).with_content(/^default_volume_type=.+$/)
        end
      end
    end

    describe '/var/lock/cinder' do
      let(:dir) { chef_run.directory('/var/lock/cinder') }

      it 'should create the /var/lock/cinder directory' do
        expect(chef_run).to create_directory(dir.name)
      end

      it 'has proper owner' do
        expect(dir.owner).to eq('cinder')
        expect(dir.group).to eq('cinder')
      end

      it 'has proper modes' do
        expect(sprintf('%o', dir.mode)).to eq '700'
      end
    end

    describe 'rootwrap.conf' do
      let(:file) { chef_run.template('/etc/cinder/rootwrap.conf') }

      it 'creates the /etc/cinder/rootwrap.conf file' do
        expect(chef_run).to create_template(file.name).with(
          user: 'root',
          group: 'root',
          mode: 0644
        )
      end

      context 'template contents' do
        it 'shows the custom banner' do
          node.set['openstack']['block-storage']['custom_template_banner'] = 'banner'

          expect(chef_run).to render_file(file.name)
          .with_content(/^banner$/)
        end

        it 'sets the default attributes' do
          [
            %r(^filters_path=/etc/cinder/rootwrap.d,/usr/share/cinder/rootwrap$),
            %r(^exec_dirs=/sbin,/usr/sbin,/bin,/usr/bin$),
            /^use_syslog=False$/,
            /^syslog_log_facility=syslog$/,
            /^syslog_log_level=ERROR$/
          ].each do |line|
            expect(chef_run).to render_file(file.name).with_content(line)
          end
        end
      end
    end
  end
end
