import ast import json import logging import os import re import time import datetime import docker import socket from urlparse import urlparse from invoke import run, task BOOTSTRAP_IMAGE_CHEIP = 'codenvy/che-ip:nightly' @task def waitfordbs(ctx): print "**************************databases*******************************" ctx.run("/usr/bin/wait-for-databases {0}".format('db'), pty=True) @task def waitforgeoserver(ctx): print "****************************geoserver********************************" while not _rest_api_availability(os.environ['GEOSERVER_LOCATION'] + 'rest'): print ("Wait for GeoServer API availability...") print "GeoServer is available for HTTP calls!" @task def update(ctx): print "***************************setting env*********************************" ctx.run("env", pty=True) pub_ip = _geonode_public_host_ip() print "Public Hostname or IP is {0}".format(pub_ip) pub_port = _geonode_public_port() print "Public PORT is {0}".format(pub_port) pub_protocol = 'https' if pub_port == '443' else 'http' if pub_protocol == 'https' or pub_port == '80': pub_port = None db_url = _update_db_connstring() geodb_url = _update_geodb_connstring() service_ready = False while not service_ready: try: socket.gethostbyname('geonode') service_ready = True except Exception: time.sleep(10) override_env = "$HOME/.override_env" if os.path.exists(override_env): os.remove(override_env) else: print("Can not delete the %s file as it doesn't exists" % override_env) envs = { "local_settings": "{0}".format(_localsettings()), "siteurl": os.environ.get('SITEURL', '{0}://{1}:{2}/'.format(pub_protocol, pub_ip, pub_port) if pub_port else '{0}://{1}/'.format(pub_protocol, pub_ip)), "geonode_docker_host": "{0}".format(socket.gethostbyname('geonode')), "public_protocol": pub_protocol, "public_fqdn": "{0}{1}".format(pub_ip, ':' + pub_port if pub_port else ''), "public_host": "{0}".format(pub_ip), "dburl": os.environ.get('DATABASE_URL', db_url), "geodburl": os.environ.get('GEODATABASE_URL', geodb_url), "static_root": os.environ.get('STATIC_ROOT', '/mnt/volumes/statics/static/'), "media_root": os.environ.get('MEDIA_ROOT', '/mnt/volumes/statics/uploaded/'), "geoip_path": os.environ.get('GEOIP_PATH', '/mnt/volumes/statics/geoip.db'), "monitoring": os.environ.get('MONITORING_ENABLED', True), "monitoring_host_name": os.environ.get('MONITORING_HOST_NAME', 'geonode'), "monitoring_service_name": os.environ.get('MONITORING_SERVICE_NAME', 'local-geonode'), "monitoring_data_ttl": os.environ.get('MONITORING_DATA_TTL', 7), "geonode_geodb_passwd": os.environ.get('GEONODE_GEODATABASE_PASSWORD', 'geonode_data'), "default_backend_datastore": os.environ.get('DEFAULT_BACKEND_DATASTORE', 'datastore'), "geonode_db_passwd": os.environ.get('GEONODE_DATABASE_PASSWORD', 'geonode'), "geonode_geodb": os.environ.get('GEONODE_GEODATABASE', 'geonode_data'), "db_url": os.environ.get('DATABASE_URL', 'postgres://geonode:geonode@db:5432/geonode'), "geodb_url": os.environ.get('GEODATABASE_URL', 'postgis://geonode:geonode@db:5432/geonode_data'), "geonode_db": os.environ.get('GEONODE_DATABASE', 'geonode'), "gs_loc": os.environ.get('GEOSERVER_LOCATION', 'http://geoserver:8080/geoserver/'), "gs_web_ui_loc": os.environ.get('GEOSERVER_WEB_UI_LOCATION', 'http://{0}:{1}/geoserver/'.format(pub_ip, pub_port) if pub_port else 'http://{0}/geoserver/'.format(pub_ip)), "gs_pub_loc": os.environ.get('GEOSERVER_PUBLIC_LOCATION', 'http://{0}:{1}/geoserver/'.format(pub_ip, pub_port) if pub_port else 'http://{0}/geoserver/'.format(pub_ip)), "gs_admin_pwd": os.environ.get('GEOSERVER_ADMIN_PASSWORD', 'geoserver'), "override_fn": override_env } try: current_allowed = ast.literal_eval(os.getenv('ALLOWED_HOSTS') or \ "['{public_fqdn}', '{public_host}', 'localhost', 'django', 'haitidata',]".format(**envs)) except ValueError: current_allowed = [] current_allowed.extend(['{}'.format(pub_ip), '{}:{}'.format(pub_ip, pub_port)]) allowed_hosts = ['"{}"'.format(c) for c in current_allowed] + ['"geonode"', '"django"'] ctx.run("echo export DJANGO_SETTINGS_MODULE=\ {local_settings} >> {override_fn}".format(**envs), pty=True) ctx.run("echo export MONITORING_ENABLED=\ {monitoring} >> {override_fn}".format(**envs), pty=True) ctx.run("echo export MONITORING_HOST_NAME=\ {monitoring_host_name} >> {override_fn}".format(**envs), pty=True) ctx.run("echo export MONITORING_SERVICE_NAME=\ {monitoring_service_name} >> {override_fn}".format(**envs), pty=True) ctx.run("echo export MONITORING_DATA_TTL=\ {monitoring_data_ttl} >> {override_fn}".format(**envs), pty=True) ctx.run("echo export GEONODE_GEODATABASE_PASSWORD=\ {geonode_geodb_passwd} >> {override_fn}".format(**envs), pty=True) ctx.run("echo export DEFAULT_BACKEND_DATASTORE=\ {default_backend_datastore} >> {override_fn}".format(**envs), pty=True) ctx.run("echo export GEONODE_DATABASE_PASSWORD=\ {geonode_db_passwd} >> {override_fn}".format(**envs), pty=True) ctx.run("echo export GEONODE_GEODATABASE=\ {geonode_geodb} >> {override_fn}".format(**envs), pty=True) ctx.run("echo export DATABASE_URL=\ {db_url} >> {override_fn}".format(**envs), pty=True) ctx.run("echo export GEODATABASE_URL=\ {geodb_url} >> {override_fn}".format(**envs), pty=True) ctx.run("echo export GEONODE_DATABASE=\ {geonode_db} >> {override_fn}".format(**envs), pty=True) ctx.run("echo export GEOSERVER_LOCATION=\ {gs_loc} >> {override_fn}".format(**envs), pty=True) ctx.run("echo export GEOSERVER_WEB_UI_LOCATION=\ {gs_web_ui_loc} >> {override_fn}".format(**envs), pty=True) ctx.run("echo export GEOSERVER_PUBLIC_LOCATION=\ {gs_pub_loc} >> {override_fn}".format(**envs), pty=True) ctx.run("echo export GEOSERVER_ADMIN_PASSWORD=\ {gs_admin_pwd} >> {override_fn}".format(**envs), pty=True) ctx.run("echo export SITEURL=\ {siteurl} >> {override_fn}".format(**envs), pty=True) ctx.run('echo export ALLOWED_HOSTS=\ "\\"{}\\"" >> {override_fn}'.format(allowed_hosts, **envs), pty=True) ctx.run("echo export DATABASE_URL=\ {dburl} >> {override_fn}".format(**envs), pty=True) ctx.run("echo export GEODATABASE_URL=\ {geodburl} >> {override_fn}".format(**envs), pty=True) ctx.run("echo export STATIC_ROOT=\ {static_root} >> {override_fn}".format(**envs), pty=True) ctx.run("echo export MEDIA_ROOT=\ {media_root} >> {override_fn}".format(**envs), pty=True) ctx.run("echo export GEOIP_PATH=\ {geoip_path} >> {override_fn}".format(**envs), pty=True) ctx.run("echo export LOGIN_URL=\ {siteurl}account/login/ >> {override_fn}".format(**envs), pty=True) ctx.run("echo export LOGOUT_URL=\ {siteurl}account/logout/ >> {override_fn}".format(**envs), pty=True) ctx.run("echo export LOGIN_REDIRECT_URL=\ {siteurl} >> {override_fn}".format(**envs), pty=True) ctx.run("echo export LOGOUT_REDIRECT_URL=\ {siteurl} >> {override_fn}".format(**envs), pty=True) ctx.run("source %s" % override_env, pty=True) print "****************************finalize env**********************************" ctx.run("env", pty=True) @task def migrations(ctx): print "**************************migrations*******************************" ctx.run("python manage.py makemigrations --noinput --merge --settings={0}".format( _localsettings() ), pty=True) ctx.run("python manage.py makemigrations --noinput --settings={0}".format( _localsettings() ), pty=True) ctx.run("python manage.py migrate --noinput --settings={0}".format( _localsettings() ), pty=True) ctx.run("python manage.py updategeoip --settings={0}".format( _localsettings() ), pty=True) try: ctx.run("python manage.py rebuild_index --noinput --settings={0}".format( _localsettings() ), pty=True) except: pass @task def statics(ctx): print "**************************statics*******************************" ctx.run('mkdir -p /mnt/volumes/statics/{static,uploads}') ctx.run("python manage.py collectstatic --noinput --clear --settings={0}".format( _localsettings() ), pty=True) @task def prepare(ctx): print "**********************prepare fixture***************************" ctx.run("rm -rf /tmp/default_oauth_apps_docker.json", pty=True) _prepare_oauth_fixture() ctx.run("rm -rf /tmp/default_site.json", pty=True) _prepare_site_fixture() # Updating OAuth2 Service Config oauth_config = "/geoserver_data/data/security/filter/geonode-oauth2/config.xml" ctx.run( 'sed -i "s|.*|{client_id}|g" {oauth_config}'.format( client_id=os.environ['OAUTH2_CLIENT_ID'], oauth_config=oauth_config ), pty=True) ctx.run( 'sed -i "s|.*|{client_secret}|g" {oauth_config}'.format( client_secret=os.environ['OAUTH2_CLIENT_SECRET'], oauth_config=oauth_config ), pty=True) @task def fixtures(ctx): print "**************************fixtures********************************" ctx.run("python manage.py loaddata sample_admin \ --settings={0}".format(_localsettings()), pty=True) ctx.run("python manage.py loaddata /tmp/default_oauth_apps_docker.json \ --settings={0}".format(_localsettings()), pty=True) ctx.run("python manage.py loaddata /tmp/default_site.json \ --settings={0}".format(_localsettings()), pty=True) ctx.run("python manage.py loaddata /usr/src/haitidata/fixtures/initial_data.json \ --settings={0}".format(_localsettings()), pty=True) ctx.run("python manage.py set_all_layers_alternate \ --settings={0}".format(_localsettings()), pty=True) ctx.run("python manage.py set_all_layers_metadata -d \ --settings={0}".format(_localsettings()), pty=True) @task def collectstatic(ctx): print "************************static artifacts******************************" ctx.run("django-admin.py collectstatic --noinput \ --settings={0}".format(_localsettings()), pty=True) @task def geoserverfixture(ctx): print "********************geoserver fixture********************************" _geoserver_info_provision(os.environ['GEOSERVER_LOCATION'] + "rest/") @task def monitoringfixture(ctx): print "*******************monitoring fixture********************************" ctx.run("rm -rf /tmp/default_monitoring_apps_docker.json", pty=True) _prepare_monitoring_fixture() try: ctx.run("django-admin.py loaddata /tmp/default_monitoring_apps_docker.json \ --settings={0}".format(_localsettings()), pty=True) except Exception as e: print "ERROR installing monitoring fixture: " + str(e) @task def updategeoip(ctx): print "**************************update geoip*******************************" ctx.run("django-admin.py updategeoip \ --settings={0}".format(_localsettings()), pty=True) @task def updateadmin(ctx): print "***********************update admin details**************************" ctx.run("rm -rf /tmp/django_admin_docker.json", pty=True) _prepare_admin_fixture(os.environ.get('ADMIN_PASSWORD', 'admin'), os.environ.get('ADMIN_EMAIL', 'admin@example.org')) ctx.run("django-admin.py loaddata /tmp/django_admin_docker.json \ --settings={0}".format(_localsettings()), pty=True) @task def collectmetrics(ctx): print "************************collect metrics******************************" ctx.run("python -W ignore manage.py collect_metrics \ --settings={0} -n -t xml".format(_localsettings()), pty=True) @task def initialized(ctx): print "**************************init file********************************" ctx.run('date > /mnt/volumes/statics/geonode_init.lock') def _docker_host_ip(): client = docker.from_env() ip_list = client.containers.run(BOOTSTRAP_IMAGE_CHEIP, network_mode='host' ).split("\n") if len(ip_list) > 1: print("Docker daemon is running on more than one \ address {0}".format(ip_list)) print("Only the first address:{0} will be returned!".format( ip_list[0] )) else: print("Docker daemon is running at the following \ address {0}".format(ip_list[0])) return ip_list[0] def _container_exposed_port(component, instname): client = docker.from_env() ports_dict = json.dumps( [c.attrs['Config']['ExposedPorts'] for c in client.containers.list( filters={ 'label': 'org.geonode.component={0}'.format(component), 'status': 'running' } ) if '{0}'.format(instname) in c.name][0] ) for key in json.loads(ports_dict): port = re.split('/tcp', key)[0] return port def _update_db_connstring(): user = os.getenv('GEONODE_DATABASE', 'geonode') pwd = os.getenv('GEONODE_DATABASE_PASSWORD', 'geonode') dbname = os.getenv('GEONODE_DATABASE', 'geonode') connstr = 'postgres://{0}:{1}@db:5432/{2}'.format( user, pwd, dbname ) return connstr def _update_geodb_connstring(): geouser = os.getenv('GEONODE_GEODATABASE', 'geonode_data') geopwd = os.getenv('GEONODE_GEODATABASE_PASSWORD', 'geonode_data') geodbname = os.getenv('GEONODE_GEODATABASE', 'geonode_data') geoconnstr = 'postgis://{0}:{1}@db:5432/{2}'.format( geouser, geopwd, geodbname ) return geoconnstr def _localsettings(): settings = os.getenv('DJANGO_SETTINGS_MODULE', 'haitidata.settings') return settings def _rest_api_availability(url): import requests try: r = requests.request('get', url, verify=False) r.raise_for_status() # Raises a HTTPError if the status is 4xx, 5xxx except (requests.exceptions.ConnectionError, requests.exceptions.Timeout) as e: print "GeoServer connection error is {0}".format(e) return False except requests.exceptions.HTTPError as er: print "GeoServer HTTP error is {0}".format(er) return False else: print "GeoServer API are available!" return True def _geonode_public_host_ip(): gn_pub_hostip = os.getenv('GEONODE_LB_HOST_IP', None) if not gn_pub_hostip: gn_pub_hostip = _docker_host_ip() return gn_pub_hostip def _geonode_public_port(): gn_pub_port = os.getenv('GEONODE_LB_PORT', '') if not gn_pub_port: gn_pub_port = _container_exposed_port( 'nginx', os.getenv('GEONODE_INSTANCE_NAME', 'geonode') ) elif gn_pub_port in ('80', '443'): gn_pub_port = None return gn_pub_port def _geoserver_info_provision(url): from django.conf import settings from geoserver.catalog import Catalog print "Setting GeoServer Admin Password..." cat = Catalog(url, username=settings.OGC_SERVER_DEFAULT_USER, password=settings.OGC_SERVER_DEFAULT_PASSWORD ) headers = { "Content-type": "application/xml", "Accept": "application/xml" } data = """ {0} """.format(os.getenv('GEOSERVER_ADMIN_PASSWORD', 'geoserver')) response = cat.http_request(cat.service_url + '/security/self/password', method="PUT", data=data, headers=headers) print "Response Code: %s" % response.status_code if response.status_code == 200: print "GeoServer admin password updated SUCCESSFULLY!" else: print "WARNING: GeoServer admin password *NOT* updated: code [%s]" % response.status_code def _prepare_oauth_fixture(): upurl = urlparse(os.environ['SITEURL']) net_scheme = upurl.scheme pub_ip = _geonode_public_host_ip() print "Public Hostname or IP is {0}".format(pub_ip) pub_port = _geonode_public_port() print "Public PORT is {0}".format(pub_port) default_fixture = [ { "model": "oauth2_provider.application", "pk": 1001, "fields": { "skip_authorization": True, "created": "2018-05-31T10:00:31.661Z", "updated": "2018-05-31T11:30:31.245Z", "algorithm": "RS256", "redirect_uris": "{0}://{1}:{2}/geoserver/index.html".format(net_scheme, pub_ip, pub_port) if pub_port else "{0}://{1}/geoserver/index.html".format(net_scheme, pub_ip), "name": "GeoServer", "authorization_grant_type": "authorization-code", "client_type": "confidential", "client_id": "{0}".format(os.environ['OAUTH2_CLIENT_ID']), "client_secret": "{0}".format(os.environ['OAUTH2_CLIENT_SECRET']), "user": [ "admin" ] } } ] with open('/tmp/default_oauth_apps_docker.json', 'w') as fixturefile: json.dump(default_fixture, fixturefile) def _prepare_site_fixture(): upurl = urlparse(os.environ['SITEURL']) default_fixture = [ { "model": "sites.site", "pk": 1, "fields": { "domain": "{0}".format(upurl.hostname), "name": "{0}".format(upurl.hostname) } } ] with open('/tmp/default_site.json', 'w') as fixturefile: json.dump(default_fixture, fixturefile) def _prepare_monitoring_fixture(): upurl = urlparse(os.environ['SITEURL']) net_scheme = upurl.scheme net_loc = upurl.netloc pub_ip = _geonode_public_host_ip() print "Public Hostname or IP is {0}".format(pub_ip) pub_port = _geonode_public_port() print "Public PORT is {0}".format(pub_port) #d = str(datetime.datetime.now()) d = '1970-01-01 00:00:00' default_fixture = [ { "fields": { "active": True, "ip": "{0}".format(socket.gethostbyname('geonode')), "name": "{0}".format(os.environ['MONITORING_HOST_NAME']) }, "model": "monitoring.host", "pk": 1 }, { "fields": { "active": True, "ip": "{0}".format(socket.gethostbyname('geoserver')), "name": "geoserver" }, "model": "monitoring.host", "pk": 2 }, { "fields": { "name": "{0}".format(os.environ['MONITORING_SERVICE_NAME']), "url": "{0}://{1}/".format(net_scheme, net_loc), "notes": "", "last_check": d, "active": True, "host": 1, "check_interval": "00:01:00", "service_type": 1 }, "model": "monitoring.service", "pk": 1 }, { "fields": { "name": "geoserver-hostgeonode", "url": "{0}://{1}/".format(net_scheme, net_loc), "notes": "", "last_check": d, "active": True, "host": 1, "check_interval": "00:01:00", "service_type": 3 }, "model": "monitoring.service", "pk": 2 }, { "fields": { "name": "geoserver-hostgeoserver", "url": "{0}".format(os.environ['GEOSERVER_LOCATION']), "notes": "", "last_check": d, "active": True, "host": 2, "check_interval": "00:01:00", "service_type": 4 }, "model": "monitoring.service", "pk": 3 }, { "fields": { "name": "default-geoserver", "url": "{0}".format(os.environ['GEOSERVER_LOCATION']), "notes": "", "last_check": d, "active": True, "host": 2, "check_interval": "00:01:00", "service_type": 2 }, "model": "monitoring.service", "pk": 4 } ] with open('/tmp/default_monitoring_apps_docker.json', 'w') as fixturefile: json.dump(default_fixture, fixturefile) def _prepare_admin_fixture(admin_password, admin_email): from django.contrib.auth.hashers import make_password d = datetime.datetime.now() mdext_date = d.isoformat()[:23] + "Z" default_fixture = [ { "fields": { "date_joined": mdext_date, "email": admin_email, "first_name": "", "groups": [], "is_active": True, "is_staff": True, "is_superuser": True, "last_login": mdext_date, "last_name": "", "password": make_password(admin_password), "user_permissions": [], "username": "admin" }, "model": "people.Profile", "pk": 1000 } ] with open('/tmp/django_admin_docker.json', 'w') as fixturefile: json.dump(default_fixture, fixturefile)