#!/usr/bin/python

import os
import sys
import base64
import traceback

if __name__ == "__main__":
    # for testing 
    if os.getenv("OPENCLOUD_PYTHONPATH"):
        sys.path.append( os.getenv("OPENCLOUD_PYTHONPATH") )
    else:
        print >> sys.stderr, "No OPENCLOUD_PYTHONPATH variable set.  Assuming that OpenCloud is in PYTHONPATH"
 
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "planetstack.settings")

from django.db.models import F, Q
from planetstack.config import Config
from observer.syncstep import SyncStep
from core.models import Service, Slice

import logging
from logging import Logger
logging.basicConfig( format='[%(levelname)s] [%(module)s:%(lineno)d] %(message)s' )
logger = logging.getLogger()
logger.setLevel( logging.INFO )

# point to planetstack 
if __name__ != "__main__":
    if os.getenv("OPENCLOUD_PYTHONPATH") is not None:
        sys.path.insert(0, os.getenv("OPENCLOUD_PYTHONPATH"))
    else:
        logger.warning("No OPENCLOUD_PYTHONPATH set; assuming your PYTHONPATH works") 

from syndicate_storage.models import VolumeSlice,VolumeAccessRight,Volume

# syndicatelib will be in stes/..
parentdir = os.path.join(os.path.dirname(__file__),"..")
sys.path.insert(0,parentdir)

import syndicatelib


class SyncVolumeSlice(SyncStep):
    provides=[VolumeSlice]
    requested_interval=0

    def __init__(self, **args):
        SyncStep.__init__(self, **args)

    def fetch_pending(self):
        return VolumeSlice.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))

    def sync_record(self, vs):
        
        logger.info("Sync VolumeSlice for (%s, %s)" % (vs.volume_id.name, vs.slice_id.name))
        
        # extract arguments...
        user_email = vs.slice_id.creator.email
        slice_name = vs.slice_id.name
        volume_name = vs.volume_id.name
        syndicate_caps = syndicatelib.opencloud_caps_to_syndicate_caps( vs.cap_read_data, vs.cap_write_data, vs.cap_host_data )
        RG_port = vs.RG_portnum
        UG_port = vs.UG_portnum
        slice_secret = None
        
        config = syndicatelib.get_config()
        try:
           observer_secret = config.SYNDICATE_OPENCLOUD_SECRET
           RG_closure = config.SYNDICATE_RG_CLOSURE
           observer_pkey_path = config.SYNDICATE_PRIVATE_KEY
           syndicate_url = config.SYNDICATE_SMI_URL
           
        except Exception, e:
           traceback.print_exc()
           logger.error("syndicatelib config is missing one or more of the following: SYNDICATE_OPENCLOUD_SECRET, SYNDICATE_RG_CLOSURE, SYNDICATE_PRIVATE_KEY, SYNDICATE_SMI_URL")
           raise e
            
        # get secrets...
        try:
           observer_pkey_pem = syndicatelib.get_private_key_pem( observer_pkey_path )
           assert observer_pkey_pem is not None, "Failed to load Observer private key"
           
           # get/create the slice secret
           slice_secret = syndicatelib.get_or_create_slice_secret( observer_pkey_pem, slice_name )    
           assert slice_secret is not None, "Failed to get or create slice secret for %s" % slice_name
           
        except Exception, e:
           traceback.print_exc()
           logger.error("Failed to load secret credentials")
           raise e
        
        # make sure there's a slice-controlled Syndicate user account for the slice owner
        slice_principal_id = syndicatelib.make_slice_principal_id( user_email, slice_name )
        
        try:
            rc, user = syndicatelib.ensure_principal_exists( slice_principal_id, observer_secret, is_admin=False, max_UGs=1100, max_RGs=1 )
            assert rc is True, "Failed to ensure principal %s exists (rc = %s,%s)" % (slice_principal_id, rc, user)
        except Exception, e:
            traceback.print_exc()
            logger.error('Failed to ensure slice user %s exists' % slice_principal_id)
            raise e
            
        # grant the slice-owning user the ability to provision UGs in this Volume, and also provision for the user the (single) RG the slice will instantiate in each VM.
        try:
            rc = syndicatelib.setup_volume_access( slice_principal_id, volume_name, syndicate_caps, RG_port, observer_secret, RG_closure=RG_closure )
            assert rc is True, "Failed to set up Volume access for slice %s in %s" % (slice_principal_id, volume_name)
            
        except Exception, e:
            traceback.print_exc()
            logger.error("Failed to set up Volume access for slice %s in %s" % (slice_principal_id, volume_name))
            raise e
            
        # generate and save slice credentials....
        try:
            slice_cred = syndicatelib.save_slice_credentials( observer_pkey_pem, syndicate_url, slice_principal_id, volume_name, slice_name, observer_secret, slice_secret, UG_port, existing_user=user )
            assert slice_cred is not None, "Failed to generate slice credential for %s in %s" % (slice_principal_id, volume_name )
                
        except Exception, e:
            traceback.print_exc()
            logger.error("Failed to generate slice credential for %s in %s" % (slice_principal_id, volume_name))
            raise e
             
        # ... and push them all out.
        try:
            rc = syndicatelib.push_credentials_to_slice( slice_name, slice_cred )
            assert rc is True, "Failed to push credentials to slice %s for volume %s" % (slice_name, volume_name)
               
        except Exception, e:
            traceback.print_exc()
            logger.error("Failed to push slice credentials to %s for volume %s" % (slice_name, volume_name))
            raise e
        
        return True


if __name__ == "__main__":
    sv = SyncVolumeSlice()

    # first, set all VolumeSlice to not-enacted so we can test 
    for v in VolumeSlice.objects.all():
       v.enacted = None
       v.save()

    # NOTE: for resetting only 
    if len(sys.argv) > 1 and sys.argv[1] == "reset":
       sys.exit(0)

    recs = sv.fetch_pending()

    for rec in recs:
        if rec.slice_id.creator is None:
           print "Ignoring slice %s, since it has no creator" % (rec.slice_id)
           continue

        sv.sync_record( rec )

