Glance quotas (#20)

* Add parameters for quota options

Quota options are parametrized. Each quota can be optionaly specified
otherwise default values are used. If parameter doesn't have value,
default value is used.

* Add Sample and test pillars

Add sample and test pillars for quota options.

* Conditionals on separate lines

* Add parameters also to pike config

* Reflect parameters rename in Sample and test pillars
diff --git a/README.rst b/README.rst
index 415c31f..7439a02 100644
--- a/README.rst
+++ b/README.rst
@@ -127,6 +127,21 @@
           virtual_host: '/openstack'
         ....
 
+Quota Options
+
+.. code-block:: yaml
+
+    glance:
+      server:
+        ....
+        quota:
+          image_member: -1
+          image_property: 256
+          image_tag: 256
+          image_location: 15
+          user_storage: 0
+        ....
+
 Configuring TLS communications
 ------------------------------
 
diff --git a/glance/files/kilo/glance-api.conf.Debian b/glance/files/kilo/glance-api.conf.Debian
index 67a6b7e..d3d4d3a 100644
--- a/glance/files/kilo/glance-api.conf.Debian
+++ b/glance/files/kilo/glance-api.conf.Debian
@@ -1,4 +1,4 @@
-{%- from "glance/map.jinja" import server with context %}
+{%-- from "glance/map.jinja" import server with context %}
 [DEFAULT]
 # Show more verbose log output (sets INFO log level output)
 #verbose = False
@@ -214,9 +214,9 @@
 #auth_url = None
 # Keystone region
 #auth_region = None
-{% if server.identity.region is defined %}
+{%- if server.identity.region is defined %}
 auth_region = {{ server.identity.region }}
-{% endif %}
+{%- endif %}
 # Auth strategy
 #auth_strategy = keystone
 
@@ -240,22 +240,22 @@
 
 # Messaging driver used for 'messaging' notifications driver
 # rpc_backend = 'rabbit'
-{% if server.notification %}
+{%- if server.notification %}
 rpc_backend = rabbit
 notifier_strategy=rabbit
 notification_driver = messagingv2
 # Configuration options if sending notifications via rabbitmq (these are
 # the defaults)
 
-{%- if server.message_queue.members is defined %}
-rabbit_hosts = {% for member in server.message_queue.members -%}
+{%-- if server.message_queue.members is defined %}
+rabbit_hosts = {%- for member in server.message_queue.members -%}
                    {{ member.host }}:{{ member.get('port', 5672) }}
-                   {%- if not loop.last -%},{%- endif -%}
-               {%- endfor -%}
-{%- else %}
+                   {%-- if not loop.last -%},{%-- endif -%}
+               {%-- endfor -%}
+{%-- else %}
 rabbit_host = {{ server.message_queue.host }}
 rabbit_port = {{ server.message_queue.port }}
-{%- endif %}
+{%-- endif %}
 
 rabbit_use_ssl = false
 rabbit_userid = {{ server.message_queue.user }}
@@ -265,10 +265,10 @@
 rabbit_notification_topic = notifications
 #rabbit_durable_queues = False
 
-{% else %}
+{%- else %}
 #notifier_strategy=qpid
 notifier_strategy=noop
-{% endif %}
+{%- endif %}
 # Configuration options if sending notifications via Qpid (these are
 # the defaults)
 qpid_notification_exchange = glance
@@ -304,20 +304,45 @@
 
 # The maximum number of image members allowed per image
 #image_member_quota = 128
+{%- if server.quota is defined %}
+{%- if server.quota.image_member is defined %}
+image_member_quota = {{ server.quota.image_member|default('128') }}
+{%- endif %}
+{%- endif %}
 
 # The maximum number of image properties allowed per image
 #image_property_quota = 128
+{%- if server.quota is defined %}
+{%- if server.quota.image_property is defined %}
+image_property_quota = {{ server.quota.image_property|default('128') }}
+{%- endif %}
+{%- endif %}
 
 # The maximum number of tags allowed per image
 #image_tag_quota = 128
+{%- if server.quota is defined %}
+{%- if server.quota.image_tag is defined %}
+image_tag_quota = {{ server.quota.image_tag|default('128') }}
+{%- endif %}
+{%- endif %}
 
 # The maximum number of locations allowed per image
 #image_location_quota = 10
+{%- if server.quota is defined %}
+{%- if server.quota.image_location is defined %}
+image_location_quota = {{ server.quota.image_location|default('10') }}
+{%- endif %}
+{%- endif %}
 
 # Set a system wide quota for every user.  This value is the total number
 # of bytes that a user can use across all storage systems.  A value of
 # 0 means unlimited.
 #user_storage_quota = 0
+{%- if server.quota is defined %}
+{%- if server.quota.user_storage is defined %}
+user_storage_quota = {{ server.quota.user_storage|default('0') }}
+{%- endif %}
+{%- endif %}
 
 # =============== Image Cache Options =============================
 
@@ -460,7 +485,7 @@
 # Deprecated group/name - [DEFAULT]/lock_path (string value)
 #lock_path = /tmp
 
-{%- if server.identity.get('version', 2) == 2 %}
+{%-- if server.identity.get('version', 2) == 2 %}
 
 [keystone_authtoken]
 identity_uri = http://{{ server.identity.host }}:35357
@@ -471,7 +496,7 @@
 auth_uri=http://{{ server.identity.host }}:5000
 auth_url=http://{{ server.identity.host }}:35357
 
-{%- else %}
+{%-- else %}
 
 [keystone_authtoken]
 identity_uri = http://{{ server.identity.host }}:35357/v3
@@ -488,7 +513,7 @@
 auth_uri=http://{{ server.identity.host }}:5000/v3
 auth_url=http://{{ server.identity.host }}:35357/v3
 
-{%- endif %}
+{%-- endif %}
 
 [paste_deploy]
 # Name of the paste configuration file that defines the available pipelines
@@ -578,14 +603,14 @@
 # Deprecated group/name - [DEFAULT]/default_store
 # Default: 'file'
 
-{%- if server.storage.engine == 'file' %}
+{%-- if server.storage.engine == 'file' %}
 default_store = file
 stores = glance.store.filesystem.Store,
          glance.store.http.Store
-{%- else %}
+{%-- else %}
 default_store = {{ server.storage.engine }}
 stores = {{ server.storage.engine }}
-{%- endif %}
+{%-- endif %}
 # ============ Filesystem Store Options ========================
 
 # Directory that the Filesystem backend store
@@ -610,9 +635,9 @@
 # system.  When show_multiple_locations is True the information in this
 # file will be returned with any location that is contained in this
 # store.
-{%- if server.filesystem_store_metadata_file is defined %}
+{%-- if server.filesystem_store_metadata_file is defined %}
 filesystem_store_metadata_file = {{ server.get('filesystem_store_metadata_file', '/etc/glance/filesystem_store_metadata.json') }}
-{%- endif %}
+{%-- endif %}
 
 # ============ Swift Store Options =============================
 
@@ -768,7 +793,7 @@
 
 # ============ RBD Store Options =============================
 
-{%- if server.storage.engine == 'rbd' %}
+{%-- if server.storage.engine == 'rbd' %}
 # ============ RBD Store Options =============================
 
 # Ceph configuration file path
@@ -792,7 +817,7 @@
 #rbd_store_chunk_size = 8
 rbd_store_chunk_size = {{ server.storage.chunk_size }}
 
-{%- endif %}
+{%-- endif %}
 
 # ============ Sheepdog Store Options =============================
 
@@ -817,9 +842,9 @@
 
 # Region name of this node (string value)
 #os_region_name = <None>
-{% if server.identity.region is defined %}
+{%- if server.identity.region is defined %}
 os_region_name = {{ server.identity.region }}
-{% endif %}
+{%- endif %}
 # Location of ca certicates file to use for cinder client requests
 # (string value)
 #cinder_ca_certificates_file = <None>
diff --git a/glance/files/liberty/glance-api.conf.Debian b/glance/files/liberty/glance-api.conf.Debian
index 1b432ca..239c110 100644
--- a/glance/files/liberty/glance-api.conf.Debian
+++ b/glance/files/liberty/glance-api.conf.Debian
@@ -314,20 +314,45 @@
 
 # The maximum number of image members allowed per image
 #image_member_quota = 128
+{%- if server.quota is defined %}
+{%- if server.quota.image_member is defined %}
+image_member_quota = {{ server.quota.image_member|default('128') }}
+{%- endif %}
+{%- endif %}
 
 # The maximum number of image properties allowed per image
 #image_property_quota = 128
+{%- if server.quota is defined %}
+{%- if server.quota.image_property is defined %}
+image_property_quota = {{ server.quota.image_property|default('128') }}
+{%- endif %}
+{%- endif %}
 
 # The maximum number of tags allowed per image
 #image_tag_quota = 128
+{%- if server.quota is defined %}
+{%- if server.quota.image_tag is defined %}
+image_tag_quota = {{ server.quota.image_tag|default('128') }}
+{%- endif %}
+{%- endif %}
 
 # The maximum number of locations allowed per image
 #image_location_quota = 10
+{%- if server.quota is defined %}
+{%- if server.quota.image_location is defined %}
+image_location_quota = {{ server.quota.image_location|default('10') }}
+{%- endif %}
+{%- endif %}
 
 # Set a system wide quota for every user.  This value is the total number
 # of bytes that a user can use across all storage systems.  A value of
 # 0 means unlimited.
 #user_storage_quota = 0
+{%- if server.quota is defined %}
+{%- if server.quota.user_storage is defined %}
+user_storage_quota = {{ server.quota.user_storage|default('0') }}
+{%- endif %}
+{%- endif %}
 
 # =============== Image Cache Options =============================
 
diff --git a/glance/files/mitaka/glance-api.conf.Debian b/glance/files/mitaka/glance-api.conf.Debian
index 940b683..500b139 100644
--- a/glance/files/mitaka/glance-api.conf.Debian
+++ b/glance/files/mitaka/glance-api.conf.Debian
@@ -36,18 +36,38 @@
 # Maximum number of image members per image. Negative values evaluate
 # to unlimited. (integer value)
 #image_member_quota = 128
+{%- if server.quota is defined %}
+{%- if server.quota.image_member is defined %}
+image_member_quota = {{ server.quota.image_member|default('128') }}
+{%- endif %}
+{%- endif %}
 
 # Maximum number of properties allowed on an image. Negative values
 # evaluate to unlimited. (integer value)
 #image_property_quota = 128
+{%- if server.quota is defined %}
+{%- if server.quota.image_property is defined %}
+image_property_quota = {{ server.quota.image_property|default('128') }}
+{%- endif %}
+{%- endif %}
 
 # Maximum number of tags allowed on an image. Negative values evaluate
 # to unlimited. (integer value)
 #image_tag_quota = 128
+{%- if server.quota is defined %}
+{%- if server.quota.image_tag is defined %}
+image_tag_quota = {{ server.quota.image_tag|default('128') }}
+{%- endif %}
+{%- endif %}
 
 # Maximum number of locations allowed on an image. Negative values
 # evaluate to unlimited. (integer value)
 #image_location_quota = 10
+{%- if server.quota is defined %}
+{%- if server.quota.image_location is defined %}
+image_location_quota = {{ server.quota.image_location|default('10') }}
+{%- endif %}
+{%- endif %}
 
 # Python module path of data access API (string value)
 #data_api = glance.db.sqlalchemy.api
@@ -91,6 +111,11 @@
 # be any space between value and unit and units are case sensitive.
 # (string value)
 #user_storage_quota = 0
+{%- if server.quota is defined %}
+{%- if server.quota.user_storage is defined %}
+user_storage_quota = {{ server.quota.user_storage|default('0') }}
+{%- endif %}
+{%- endif %}
 
 # Deploy the v1 OpenStack Images API. (boolean value)
 #enable_v1_api = true
diff --git a/glance/files/newton/glance-api.conf.Debian b/glance/files/newton/glance-api.conf.Debian
index 8e906f3..3aa8ac0 100644
--- a/glance/files/newton/glance-api.conf.Debian
+++ b/glance/files/newton/glance-api.conf.Debian
@@ -136,6 +136,11 @@
 #
 #  (integer value)
 #image_member_quota = 128
+{%- if server.quota is defined %}
+{%- if server.quota.image_member is defined %}
+image_member_quota = {{ server.quota.image_member|default('128') }}
+{%- endif %}
+{%- endif %}
 
 #
 # Maximum number of properties allowed on an image.
@@ -151,6 +156,11 @@
 #
 #  (integer value)
 #image_property_quota = 128
+{%- if server.quota is defined %}
+{%- if server.quota.image_property is defined %}
+image_property_quota = {{ server.quota.image_property|default('128') }}
+{%- endif %}
+{%- endif %}
 
 #
 # Maximum number of tags allowed on an image.
@@ -162,6 +172,11 @@
 #
 #  (integer value)
 #image_tag_quota = 128
+{%- if server.quota is defined %}
+{%- if server.quota.image_tag is defined %}
+image_tag_quota = {{ server.quota.image_tag|default('128') }}
+{%- endif %}
+{%- endif %}
 
 #
 # Maximum number of locations allowed on an image.
@@ -173,6 +188,11 @@
 #
 #  (integer value)
 #image_location_quota = 10
+{%- if server.quota is defined %}
+{%- if server.quota.image_location is defined %}
+image_location_quota = {{ server.quota.image_location|default('10') }}
+{%- endif %}
+{%- endif %}
 
 #
 # Python module path of data access API.
@@ -381,6 +401,11 @@
 #
 #  (string value)
 #user_storage_quota = 0
+{%- if server.quota is defined %}
+{%- if server.quota.user_storage is defined %}
+user_storage_quota = {{ server.quota.user_storage|default('0') }}
+{%- endif %}
+{%- endif %}
 
 #
 # Deploy the v1 OpenStack Images API.
diff --git a/glance/files/ocata/glance-api.conf.Debian b/glance/files/ocata/glance-api.conf.Debian
index a2ad833..a29833a 100644
--- a/glance/files/ocata/glance-api.conf.Debian
+++ b/glance/files/ocata/glance-api.conf.Debian
@@ -136,6 +136,11 @@
 #
 #  (integer value)
 #image_member_quota = 128
+{%- if server.quota is defined %}
+{%- if server.quota.image_member is defined %}
+image_member_quota = {{ server.quota.image_member|default('128') }}
+{%- endif %}
+{%- endif %}
 
 #
 # Maximum number of properties allowed on an image.
@@ -151,6 +156,11 @@
 #
 #  (integer value)
 #image_property_quota = 128
+{%- if server.quota is defined %}
+{%- if server.quota.image_property is defined %}
+image_property_quota = {{ server.quota.image_property|default('128') }}
+{%- endif %}
+{%- endif %}
 
 #
 # Maximum number of tags allowed on an image.
@@ -162,6 +172,11 @@
 #
 #  (integer value)
 #image_tag_quota = 128
+{%- if server.quota is defined %}
+{%- if server.quota.image_tag is defined %}
+image_tag_quota = {{ server.quota.image_tag|default('128') }}
+{%- endif %}
+{%- endif %}
 
 #
 # Maximum number of locations allowed on an image.
@@ -173,6 +188,11 @@
 #
 #  (integer value)
 #image_location_quota = 10
+{%- if server.quota is defined %}
+{%- if server.quota.image_location is defined %}
+image_location_quota = {{ server.quota.image_location|default('10') }}
+{%- endif %}
+{%- endif %}
 
 #
 # Python module path of data access API.
@@ -381,6 +401,11 @@
 #
 #  (string value)
 #user_storage_quota = 0
+{%- if server.quota is defined %}
+{%- if server.quota.user_storage is defined %}
+user_storage_quota = {{ server.quota.user_storage|default('0') }}
+{%- endif %}
+{%- endif %}
 
 #
 # Deploy the v1 OpenStack Images API.
diff --git a/glance/files/pike/glance-api.conf.Debian b/glance/files/pike/glance-api.conf.Debian
index a2ad833..a29833a 100644
--- a/glance/files/pike/glance-api.conf.Debian
+++ b/glance/files/pike/glance-api.conf.Debian
@@ -136,6 +136,11 @@
 #
 #  (integer value)
 #image_member_quota = 128
+{%- if server.quota is defined %}
+{%- if server.quota.image_member is defined %}
+image_member_quota = {{ server.quota.image_member|default('128') }}
+{%- endif %}
+{%- endif %}
 
 #
 # Maximum number of properties allowed on an image.
@@ -151,6 +156,11 @@
 #
 #  (integer value)
 #image_property_quota = 128
+{%- if server.quota is defined %}
+{%- if server.quota.image_property is defined %}
+image_property_quota = {{ server.quota.image_property|default('128') }}
+{%- endif %}
+{%- endif %}
 
 #
 # Maximum number of tags allowed on an image.
@@ -162,6 +172,11 @@
 #
 #  (integer value)
 #image_tag_quota = 128
+{%- if server.quota is defined %}
+{%- if server.quota.image_tag is defined %}
+image_tag_quota = {{ server.quota.image_tag|default('128') }}
+{%- endif %}
+{%- endif %}
 
 #
 # Maximum number of locations allowed on an image.
@@ -173,6 +188,11 @@
 #
 #  (integer value)
 #image_location_quota = 10
+{%- if server.quota is defined %}
+{%- if server.quota.image_location is defined %}
+image_location_quota = {{ server.quota.image_location|default('10') }}
+{%- endif %}
+{%- endif %}
 
 #
 # Python module path of data access API.
@@ -381,6 +401,11 @@
 #
 #  (string value)
 #user_storage_quota = 0
+{%- if server.quota is defined %}
+{%- if server.quota.user_storage is defined %}
+user_storage_quota = {{ server.quota.user_storage|default('0') }}
+{%- endif %}
+{%- endif %}
 
 #
 # Deploy the v1 OpenStack Images API.
diff --git a/glance/files/pike/glance-api.conf.RedHat b/glance/files/pike/glance-api.conf.RedHat
deleted file mode 120000
index 7a47331..0000000
--- a/glance/files/pike/glance-api.conf.RedHat
+++ /dev/null
@@ -1 +0,0 @@
-glance-api.conf.Debian
\ No newline at end of file
diff --git a/glance/files/pike/glance-api.conf.RedHat b/glance/files/pike/glance-api.conf.RedHat
new file mode 100644
index 0000000..7a47331
--- /dev/null
+++ b/glance/files/pike/glance-api.conf.RedHat
@@ -0,0 +1 @@
+glance-api.conf.Debian
\ No newline at end of file
diff --git a/glance/files/pike/glance-cache.conf.RedHat b/glance/files/pike/glance-cache.conf.RedHat
deleted file mode 120000
index ac4c3d1..0000000
--- a/glance/files/pike/glance-cache.conf.RedHat
+++ /dev/null
@@ -1 +0,0 @@
-glance-cache.conf.Debian
\ No newline at end of file
diff --git a/glance/files/pike/glance-cache.conf.RedHat b/glance/files/pike/glance-cache.conf.RedHat
new file mode 100644
index 0000000..ac4c3d1
--- /dev/null
+++ b/glance/files/pike/glance-cache.conf.RedHat
@@ -0,0 +1 @@
+glance-cache.conf.Debian
\ No newline at end of file
diff --git a/glance/files/pike/glance-registry.conf.RedHat b/glance/files/pike/glance-registry.conf.RedHat
deleted file mode 120000
index a4170b8..0000000
--- a/glance/files/pike/glance-registry.conf.RedHat
+++ /dev/null
@@ -1 +0,0 @@
-glance-registry.conf.Debian
\ No newline at end of file
diff --git a/glance/files/pike/glance-registry.conf.RedHat b/glance/files/pike/glance-registry.conf.RedHat
new file mode 100644
index 0000000..a4170b8
--- /dev/null
+++ b/glance/files/pike/glance-registry.conf.RedHat
@@ -0,0 +1 @@
+glance-registry.conf.Debian
\ No newline at end of file
diff --git a/glance/files/pike/glance-scrubber.conf.RedHat b/glance/files/pike/glance-scrubber.conf.RedHat
deleted file mode 120000
index 2fc1db1..0000000
--- a/glance/files/pike/glance-scrubber.conf.RedHat
+++ /dev/null
@@ -1 +0,0 @@
-glance-scrubber.conf.Debian
\ No newline at end of file
diff --git a/glance/files/pike/glance-scrubber.conf.RedHat b/glance/files/pike/glance-scrubber.conf.RedHat
new file mode 100644
index 0000000..2fc1db1
--- /dev/null
+++ b/glance/files/pike/glance-scrubber.conf.RedHat
@@ -0,0 +1 @@
+glance-scrubber.conf.Debian
\ No newline at end of file
diff --git a/tests/pillar/cluster.sls b/tests/pillar/cluster.sls
index 3b6cd0d..7753194 100644
--- a/tests/pillar/cluster.sls
+++ b/tests/pillar/cluster.sls
@@ -43,3 +43,9 @@
     policy:
       publicize_image: "role:admin"
       add_member:
+    quota:
+      image_member: -1
+      image_property: 256
+      image_tag: 256
+      image_location: 15
+      user_storage: 0
diff --git a/tests/pillar/single.sls b/tests/pillar/single.sls
index 6a2779c..94e57aa 100644
--- a/tests/pillar/single.sls
+++ b/tests/pillar/single.sls
@@ -37,3 +37,9 @@
     policy:
       publicize_image: "role:admin"
       add_member:
+    quota:
+      image_member: -1
+      image_property: 256
+      image_tag: 256
+      image_location: 15
+      user_storage: 0