Refactored teh sync_volume_slice step with new style of deletion
[plstackapi.git] / planetstack / syndicate_observer / steps / sync_volumeslice.py
1 #!/usr/bin/python
2
3 import os
4 import sys
5 import base64
6 import traceback
7
8 if __name__ == "__main__":
9     # for testing 
10     if os.getenv("OPENCLOUD_PYTHONPATH"):
11         sys.path.append( os.getenv("OPENCLOUD_PYTHONPATH") )
12     else:
13         print >> sys.stderr, "No OPENCLOUD_PYTHONPATH variable set.  Assuming that OpenCloud is in PYTHONPATH"
14  
15     os.environ.setdefault("DJANGO_SETTINGS_MODULE", "planetstack.settings")
16
17 from django.db.models import F, Q
18 from planetstack.config import Config
19 from observer.syncstep import SyncStep
20 from core.models import Service, Slice
21
22 import logging
23 from logging import Logger
24 logging.basicConfig( format='[%(levelname)s] [%(module)s:%(lineno)d] %(message)s' )
25 logger = logging.getLogger()
26 logger.setLevel( logging.INFO )
27
28 # point to planetstack 
29 if __name__ != "__main__":
30     if os.getenv("OPENCLOUD_PYTHONPATH") is not None:
31         sys.path.insert(0, os.getenv("OPENCLOUD_PYTHONPATH"))
32     else:
33         logger.warning("No OPENCLOUD_PYTHONPATH set; assuming your PYTHONPATH works") 
34
35 from syndicate_storage.models import VolumeSlice,VolumeAccessRight,Volume
36
37 # syndicatelib will be in stes/..
38 parentdir = os.path.join(os.path.dirname(__file__),"..")
39 sys.path.insert(0,parentdir)
40
41 import syndicatelib
42
43
44 class SyncVolumeSlice(SyncStep):
45     provides=[VolumeSlice]
46     requested_interval=0
47
48     def __init__(self, **args):
49         SyncStep.__init__(self, **args)
50
51     def sync_record(self, vs):
52         
53         logger.info("Sync VolumeSlice for (%s, %s)" % (vs.volume_id.name, vs.slice_id.name))
54         
55         # extract arguments...
56         user_email = vs.slice_id.creator.email
57         slice_name = vs.slice_id.name
58         volume_name = vs.volume_id.name
59         syndicate_caps = syndicatelib.opencloud_caps_to_syndicate_caps( vs.cap_read_data, vs.cap_write_data, vs.cap_host_data )
60         RG_port = vs.RG_portnum
61         UG_port = vs.UG_portnum
62         slice_secret = None
63         
64         config = syndicatelib.get_config()
65         try:
66            observer_secret = config.SYNDICATE_OPENCLOUD_SECRET
67            RG_closure = config.SYNDICATE_RG_CLOSURE
68            observer_pkey_path = config.SYNDICATE_PRIVATE_KEY
69            syndicate_url = config.SYNDICATE_SMI_URL
70            
71         except Exception, e:
72            traceback.print_exc()
73            logger.error("syndicatelib config is missing one or more of the following: SYNDICATE_OPENCLOUD_SECRET, SYNDICATE_RG_CLOSURE, SYNDICATE_PRIVATE_KEY, SYNDICATE_SMI_URL")
74            raise e
75             
76         # get secrets...
77         try:
78            observer_pkey_pem = syndicatelib.get_private_key_pem( observer_pkey_path )
79            assert observer_pkey_pem is not None, "Failed to load Observer private key"
80            
81            # get/create the slice secret
82            slice_secret = syndicatelib.get_or_create_slice_secret( observer_pkey_pem, slice_name )    
83            assert slice_secret is not None, "Failed to get or create slice secret for %s" % slice_name
84            
85         except Exception, e:
86            traceback.print_exc()
87            logger.error("Failed to load secret credentials")
88            raise e
89         
90         # make sure there's a slice-controlled Syndicate user account for the slice owner
91         slice_principal_id = syndicatelib.make_slice_principal_id( user_email, slice_name )
92         
93         try:
94             rc, user = syndicatelib.ensure_principal_exists( slice_principal_id, observer_secret, is_admin=False, max_UGs=1100, max_RGs=1 )
95             assert rc is True, "Failed to ensure principal %s exists (rc = %s,%s)" % (slice_principal_id, rc, user)
96         except Exception, e:
97             traceback.print_exc()
98             logger.error('Failed to ensure slice user %s exists' % slice_principal_id)
99             raise e
100             
101         # 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.
102         try:
103             rc = syndicatelib.setup_volume_access( slice_principal_id, volume_name, syndicate_caps, RG_port, observer_secret, RG_closure=RG_closure )
104             assert rc is True, "Failed to set up Volume access for slice %s in %s" % (slice_principal_id, volume_name)
105             
106         except Exception, e:
107             traceback.print_exc()
108             logger.error("Failed to set up Volume access for slice %s in %s" % (slice_principal_id, volume_name))
109             raise e
110             
111         # generate and save slice credentials....
112         try:
113             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 )
114             assert slice_cred is not None, "Failed to generate slice credential for %s in %s" % (slice_principal_id, volume_name )
115                 
116         except Exception, e:
117             traceback.print_exc()
118             logger.error("Failed to generate slice credential for %s in %s" % (slice_principal_id, volume_name))
119             raise e
120              
121         # ... and push them all out.
122         try:
123             rc = syndicatelib.push_credentials_to_slice( slice_name, slice_cred )
124             assert rc is True, "Failed to push credentials to slice %s for volume %s" % (slice_name, volume_name)
125                
126         except Exception, e:
127             traceback.print_exc()
128             logger.error("Failed to push slice credentials to %s for volume %s" % (slice_name, volume_name))
129             raise e
130         
131         return True
132     
133     # This method will simply cause the object to be purged from OpenCloud
134     def delete_record(self, volume_slice):
135         pass
136
137
138 if __name__ == "__main__":
139     sv = SyncVolumeSlice()
140
141     # first, set all VolumeSlice to not-enacted so we can test 
142     for v in VolumeSlice.objects.all():
143        v.enacted = None
144        v.save()
145
146     # NOTE: for resetting only 
147     if len(sys.argv) > 1 and sys.argv[1] == "reset":
148        sys.exit(0)
149
150     recs = sv.fetch_pending()
151
152     for rec in recs:
153         if rec.slice_id.creator is None:
154            print "Ignoring slice %s, since it has no creator" % (rec.slice_id)
155            continue
156
157         sv.sync_record( rec )
158