From 9e03b17132f172ef5fe6b3694d8dbfcddbb0225e Mon Sep 17 00:00:00 2001
From: Marco Mariani <marco.mariani@nexedi.com>
Date: Mon, 7 Jan 2013 14:14:12 +0100
Subject: [PATCH] listen on all provided ip addresses; ipv4/v6 support cleanup

---
 slapos/recipe/postgres/__init__.py           | 51 +++++++++-----------
 software/postgres/instance.cfg.in            |  7 +--
 software/postgres/software.cfg               |  2 +-
 stack/lapp/buildout.cfg                      |  2 +-
 stack/lapp/postgres/instance-postgres.cfg.in | 18 +++----
 5 files changed, 37 insertions(+), 43 deletions(-)

diff --git a/slapos/recipe/postgres/__init__.py b/slapos/recipe/postgres/__init__.py
index 484a66c7c..c8494d4af 100644
--- a/slapos/recipe/postgres/__init__.py
+++ b/slapos/recipe/postgres/__init__.py
@@ -40,7 +40,7 @@ class Recipe(GenericBaseRecipe):
     This recipe creates:
 
         - a Postgres cluster
-        - configuration to allow connections from IPV6 only (or unix socket)
+        - configuration to allow connections from IPv4, IPv6 or unix socket.
         - a superuser with provided name and generated password
         - a database with provided name
         - a foreground start script in the services directory
@@ -49,22 +49,9 @@ class Recipe(GenericBaseRecipe):
     The URL can be used as-is (ie. in sqlalchemy) or by the _urlparse.py recipe.
     """
 
-    def fetch_ipv6_host(self, options):
-        """\
-        Returns a string represtation of ipv6_host.
-        May receive a regular string, a set or a string serialized by buildout.
-        """
-        ipv6_host = options['ipv6_host']
-
-        if isinstance(ipv6_host, set):
-            return ipv6_host.pop()
-        else:
-            return ipv6_host
-
-
     def _options(self, options):
         options['password'] = self.generatePassword()
-        options['url'] = 'postgresql://%(user)s:%(password)s@[%(ipv4_host)s]:%(port)s/%(dbname)s' % options
+        options['url'] = 'postgresql://%(user)s:%(password)s@[%(ipv6_random)s]:%(port)s/%(dbname)s' % options
 
 
     def install(self):
@@ -117,10 +104,12 @@ class Recipe(GenericBaseRecipe):
 
     def createConfig(self):
         pgdata = self.options['pgdata-directory']
+        ipv4 = self.options['ipv4']
+        ipv6 = self.options['ipv6']
 
         with open(os.path.join(pgdata, 'postgresql.conf'), 'wb') as cfg:
             cfg.write(textwrap.dedent("""\
-                    listen_addresses = '%s,%s'
+                    listen_addresses = '%s'
                     logging_collector = on
                     log_rotation_size = 50MB
                     max_connections = 100
@@ -135,25 +124,29 @@ class Recipe(GenericBaseRecipe):
                     unix_socket_directory = '%s'
                     unix_socket_permissions = 0700
                     """ % (
-                        self.options['ipv4_host'],
-                        self.fetch_ipv6_host(self.options),
+                        ','.join(ipv4.union(ipv6)),
                         pgdata,
                         )))
 
-
         with open(os.path.join(pgdata, 'pg_hba.conf'), 'wb') as cfg:
             # see http://www.postgresql.org/docs/9.1/static/auth-pg-hba-conf.html
 
-            cfg.write(textwrap.dedent("""\
-                    # TYPE  DATABASE        USER            ADDRESS                 METHOD
-
-                    # "local" is for Unix domain socket connections only (check unix_socket_permissions!)
-                    local   all             all                                     ident
-                    host    all             all             127.0.0.1/32            md5
-                    host    all             all             %s/32                   md5
-                    host    all             all             ::1/128                 md5
-                    host    all             all             %s/128                  md5
-                    """ % (self.options['ipv4_host'], self.fetch_ipv6_host(self.options))))
+            cfg_lines = [
+                '# TYPE  DATABASE        USER            ADDRESS                 METHOD',
+                '',
+                '# "local" is for Unix domain socket connections only (check unix_socket_permissions!)',
+                'local   all             all                                     ident',
+                'host    all             all             127.0.0.1/32            md5',
+                'host    all             all             ::1/128                 md5',
+            ]
+
+            for ip in ipv4:
+                cfg_lines.append('host    all             all             %s/32                   md5' % ip)
+
+            for ip in ipv6:
+                cfg_lines.append('host    all             all             %s/128                   md5' % ip)
+
+            cfg.write('\n'.join(cfg_lines))
 
 
     def createDatabase(self):
diff --git a/software/postgres/instance.cfg.in b/software/postgres/instance.cfg.in
index 8a7c19058..e5397dfbd 100644
--- a/software/postgres/instance.cfg.in
+++ b/software/postgres/instance.cfg.in
@@ -42,15 +42,16 @@ symlink_base = ${postgresql:location}/bin
 recipe = slapos.cookbook:postgres
 
 # Options
-ipv6_host = $${instance-parameters:ipv6}
-ipv4_host = $${slap-network-information:local-ipv4}
+ipv6 = $${instance-parameters:ipv6}
+ipv4 = $${instance-parameters:ipv4}
+ipv6_random = $${instance-parameters:ipv6_random}
 user = user
 port = 5432
 dbname = db
 # pgdata_directory is created by initdb, and should not exist beforehand.
 pgdata-directory = $${directories:var}/data
-services = $${directories:services}
 bin = $${directories:bin}
+services = $${directories:services}
 
 
 [publish]
diff --git a/software/postgres/software.cfg b/software/postgres/software.cfg
index 46d218418..1bdf0eb31 100644
--- a/software/postgres/software.cfg
+++ b/software/postgres/software.cfg
@@ -14,7 +14,7 @@ parts =
 recipe = slapos.recipe.template
 url = ${:_profile_base_location_}/instance.cfg.in
 output = ${buildout:directory}/template.cfg
-#md5sum = 
+md5sum = 5ccffbfc2f1d06fd3ef199bc8b643db7
 mode = 0644
 
 
diff --git a/stack/lapp/buildout.cfg b/stack/lapp/buildout.cfg
index 695af121b..e02dde4c7 100644
--- a/stack/lapp/buildout.cfg
+++ b/stack/lapp/buildout.cfg
@@ -86,7 +86,7 @@ mode = 0644
 recipe = slapos.recipe.template
 url = ${:_profile_base_location_}/postgres/instance-postgres.cfg.in
 output = ${buildout:directory}/instance-postgres.cfg
-md5sum = 9644856614d8f595d0666d76093e1031
+md5sum = 4a339ed20f7579e5558fc53637e441fd
 mode = 0644
 
 [instance-postgres-import]
diff --git a/stack/lapp/postgres/instance-postgres.cfg.in b/stack/lapp/postgres/instance-postgres.cfg.in
index 9af75f8b0..646b751d2 100644
--- a/stack/lapp/postgres/instance-postgres.cfg.in
+++ b/stack/lapp/postgres/instance-postgres.cfg.in
@@ -134,9 +134,9 @@ config-file = $${directory:stunnel-conf}/stunnel.conf
 key-file = $${directory:stunnel-conf}/stunnel.key
 cert-file = $${directory:stunnel-conf}/stunnel.crt
 pid-file = $${basedirectory:run}/stunnel.pid
-local-host = $${postgres-instance:ipv4_host}
+local-host = $${instance-parameters:ipv4_random}
 local-port = $${postgres-instance:port}
-remote-host = $${slap-network-information:global-ipv6}
+remote-host = $${instance-parameters:ipv6_random}
 remote-port = 6446
 client = false
 post-rotate-script = $${rootdirectory:bin}/stunnel_post_rotate
@@ -171,17 +171,17 @@ crl = $${directory:ca-dir}/crl/
 
 [postgres-instance]
 recipe = slapos.cookbook:postgres
-bin = $${rootdirectory:bin}
-services = $${basedirectory:services}
+ipv6 = $${instance-parameters:ipv6}
+ipv4 = $${instance-parameters:ipv4}
+ipv6_random = $${instance-parameters:ipv6_random}
 user = postgres
 port = 5432
 dbname = db
-ipv6_host = $${slap-network-information:global-ipv6}
-# XXX the next line is required by stunnel, not by us
-ipv4_host = $${slap-network-information:local-ipv4}
 # pgdata_directory is created by initdb, and should not exist beforehand.
 pgdata-directory = $${rootdirectory:var}/data
 backup-directory = $${basedirectory:backup}/postgres
+bin = $${rootdirectory:bin}
+services = $${basedirectory:services}
 dependency-symlinks = $${symlinks:recipe}
 
 [ca-stunnel]
@@ -227,7 +227,7 @@ path = $${directory:report}/slapmonitor-xml
 [postgres-promise]
 recipe = slapos.cookbook:check_port_listening
 path = $${basedirectory:promises}/postgres
-hostname = $${slap-network-information:global-ipv6}
+hostname = $${instance-parameters:ipv6_random}
 port = $${postgres-instance:port}
 
 
@@ -238,7 +238,7 @@ port = $${postgres-instance:port}
 [urls]
 recipe = slapos.cookbook:publish
 url = $${postgres-instance:url}
-ip = $${slap-network-information:global-ipv6}
+ip = $${instance-parameters:ipv6_random}
 
 #----------------
 #--
-- 
2.30.9