Statistics
| Branch: | Revision:

root / snfOCCI / APIserver.py @ c1106cd7

History | View | Annotate | Download (7.4 kB)

1 c687b8f4 John Giannelos
#!/usr/bin/env python
2 c687b8f4 John Giannelos
3 0e9a6098 John Giannelos
import re
4 c1106cd7 John Giannelos
import sys
5 c1106cd7 John Giannelos
from optparse import OptionParser, OptionValueError
6 0e9a6098 John Giannelos
import string
7 b92a3d98 John Giannelos
import sqlite3
8 b92a3d98 John Giannelos
9 ed91cac4 John Giannelos
from snfOCCI.registry import snfRegistry
10 ed91cac4 John Giannelos
from snfOCCI.compute import ComputeBackend
11 088e4262 John Giannelos
from snfOCCI.config import SERVER_CONFIG, KAMAKI_CONFIG
12 ed91cac4 John Giannelos
13 c687b8f4 John Giannelos
from kamaki.clients.compute import ComputeClient
14 4adfebfe John Giannelos
from kamaki.clients.cyclades import CycladesClient
15 c687b8f4 John Giannelos
from kamaki.config  import Config
16 c687b8f4 John Giannelos
17 77182fb8 John Giannelos
from occi.core_model import Mixin, Resource
18 22167a8c John Giannelos
from occi.backend import MixinBackend
19 c687b8f4 John Giannelos
from occi.extensions.infrastructure import COMPUTE, START, STOP, SUSPEND, RESTART, RESOURCE_TEMPLATE, OS_TEMPLATE
20 c687b8f4 John Giannelos
from occi.wsgi import Application
21 8619548c John Giannelos
from occi.exceptions import HTTPError
22 c687b8f4 John Giannelos
23 c687b8f4 John Giannelos
from wsgiref.simple_server import make_server
24 c687b8f4 John Giannelos
from wsgiref.validate import validator
25 c687b8f4 John Giannelos
26 8619548c John Giannelos
import voms
27 c687b8f4 John Giannelos
28 c1106cd7 John Giannelos
def parse_arguments(args):
29 c687b8f4 John Giannelos
30 c1106cd7 John Giannelos
    kw = {}
31 c1106cd7 John Giannelos
    kw["usage"] = "%prog [options]"
32 c1106cd7 John Giannelos
    kw["description"] = "OCCI interface to synnefo API"
33 c1106cd7 John Giannelos
34 c1106cd7 John Giannelos
    parser = OptionParser(**kw)
35 c1106cd7 John Giannelos
    parser.disable_interspersed_args()
36 c1106cd7 John Giannelos
37 c1106cd7 John Giannelos
    parser.add_option("--enable_voms", action="store_true", dest="enable_voms", default=False, help="Enable voms authorization")
38 c1106cd7 John Giannelos
    parser.add_option("--voms_db", action="store", type="string", dest="voms_db", help="Path to sqlite database file")
39 c1106cd7 John Giannelos
40 c1106cd7 John Giannelos
    (opts, args) = parser.parse_args(args)
41 c1106cd7 John Giannelos
42 c1106cd7 John Giannelos
    if opts.enable_voms and not opts.voms_db:
43 c1106cd7 John Giannelos
        print "--voms_db option required"
44 c1106cd7 John Giannelos
        parser.print_help()
45 c1106cd7 John Giannelos
46 c1106cd7 John Giannelos
    return (opts, args)
47 b92a3d98 John Giannelos
48 c687b8f4 John Giannelos
class MyAPP(Application):
49 c687b8f4 John Giannelos
    '''
50 c687b8f4 John Giannelos
    An OCCI WSGI application.
51 c687b8f4 John Giannelos
    '''
52 c687b8f4 John Giannelos
53 55ab2427 John Giannelos
    def refresh_images(self, snf, client):
54 b46572ab John Giannelos
55 711721d6 John Giannelos
        images = snf.list_images()
56 711721d6 John Giannelos
        for image in images:
57 711721d6 John Giannelos
            IMAGE_ATTRIBUTES = {'occi.core.id': str(image['id'])}
58 711721d6 John Giannelos
            IMAGE = Mixin("http://schemas.ogf.org/occi/infrastructure#", str(image['name']), [OS_TEMPLATE], attributes = IMAGE_ATTRIBUTES)
59 b7fca2d2 John Giannelos
            self.register_backend(IMAGE, MixinBackend())
60 711721d6 John Giannelos
61 55ab2427 John Giannelos
    def refresh_flavors(self, snf, client):
62 b7fca2d2 John Giannelos
        
63 711721d6 John Giannelos
        flavors = snf.list_flavors()
64 711721d6 John Giannelos
        for flavor in flavors:
65 711721d6 John Giannelos
            details = snf.get_flavor_details(flavor['id'])
66 711721d6 John Giannelos
            FLAVOR_ATTRIBUTES = {'occi.core.id': flavor['id'],
67 711721d6 John Giannelos
                                 'occi.compute.cores': details['cpu'],
68 711721d6 John Giannelos
                                 'occi.compute.memory': details['ram'],
69 711721d6 John Giannelos
                                 'occi.storage.size': details['disk'],
70 711721d6 John Giannelos
                                 }
71 711721d6 John Giannelos
            FLAVOR = Mixin("http://schemas.ogf.org/occi/infrastructure#", str(flavor['name']), [RESOURCE_TEMPLATE], attributes = FLAVOR_ATTRIBUTES)
72 b7fca2d2 John Giannelos
            self.register_backend(FLAVOR, MixinBackend())
73 b7fca2d2 John Giannelos
74 b7fca2d2 John Giannelos
75 77182fb8 John Giannelos
    def refresh_compute_instances(self, snf):
76 dcb17973 John Giannelos
        '''Syncing registry with cyclades resources'''
77 dcb17973 John Giannelos
78 77182fb8 John Giannelos
        servers = snf.list_servers()
79 77182fb8 John Giannelos
        snf_keys = []
80 77182fb8 John Giannelos
        for server in servers:
81 77182fb8 John Giannelos
            snf_keys.append(str(server['id']))
82 77182fb8 John Giannelos
83 77182fb8 John Giannelos
        resources = self.registry.resources
84 77182fb8 John Giannelos
        occi_keys = resources.keys()
85 77182fb8 John Giannelos
        
86 2bd4ca03 John Giannelos
        #Compute instances in synnefo not available in registry
87 77182fb8 John Giannelos
        diff = [x for x in snf_keys if '/compute/'+x not in occi_keys]
88 77182fb8 John Giannelos
        for key in diff:
89 77182fb8 John Giannelos
90 77182fb8 John Giannelos
            details = snf.get_server_details(int(key))
91 77182fb8 John Giannelos
            flavor = snf.get_flavor_details(details['flavorRef'])
92 2bd4ca03 John Giannelos
            image = snf.get_image_details(details['imageRef'])
93 77182fb8 John Giannelos
94 2bd4ca03 John Giannelos
            for i in self.registry.backends:
95 2bd4ca03 John Giannelos
                if i.term == str(image['name']):
96 2bd4ca03 John Giannelos
                    rel_image = i
97 2bd4ca03 John Giannelos
                if i.term == str(flavor['name']):
98 2bd4ca03 John Giannelos
                    rel_flavor = i
99 2bd4ca03 John Giannelos
100 2bd4ca03 John Giannelos
            resource = Resource(key, COMPUTE, [rel_flavor, rel_image])
101 77182fb8 John Giannelos
            resource.actions = [START]
102 77182fb8 John Giannelos
            resource.attributes['occi.core.id'] = key
103 77182fb8 John Giannelos
            resource.attributes['occi.compute.state'] = 'inactive'
104 77182fb8 John Giannelos
            resource.attributes['occi.compute.architecture'] = SERVER_CONFIG['compute_arch']
105 77182fb8 John Giannelos
            resource.attributes['occi.compute.cores'] = flavor['cpu']
106 77182fb8 John Giannelos
            resource.attributes['occi.compute.memory'] = flavor['ram']
107 77182fb8 John Giannelos
            resource.attributes['occi.compute.hostname'] = SERVER_CONFIG['hostname'] % {'id':int(key)}
108 088e4262 John Giannelos
109 77182fb8 John Giannelos
            self.registry.add_resource(key, resource, None)
110 77182fb8 John Giannelos
111 2bd4ca03 John Giannelos
        #Compute instances in registry not available in synnefo
112 dcb17973 John Giannelos
        diff = [x for x in occi_keys if x[9:] not in snf_keys]
113 dcb17973 John Giannelos
        for key in diff:
114 dcb17973 John Giannelos
            self.registry.delete_resource(key, None)
115 dcb17973 John Giannelos
116 dcb17973 John Giannelos
117 b7fca2d2 John Giannelos
    def __call__(self, environ, response):
118 b7fca2d2 John Giannelos
119 b92a3d98 John Giannelos
        #Authorization
120 2bd4ca03 John Giannelos
121 c1106cd7 John Giannelos
        if ENABLE_VOMS:
122 c1106cd7 John Giannelos
123 c1106cd7 John Giannelos
            global VOMS_DB
124 c1106cd7 John Giannelos
            conn = sqlite3.connect(VOMS_DB)
125 0e9a6098 John Giannelos
126 c1106cd7 John Giannelos
            ssl_dict = dict()
127 c1106cd7 John Giannelos
            
128 c1106cd7 John Giannelos
            #Regular expression in HTTP headers
129 c1106cd7 John Giannelos
            #raw environ[HTTP_SSL] contains PEM certificates in wrong format
130 4c9a536c John Giannelos
        
131 c1106cd7 John Giannelos
            pem_re = r'^(-----BEGIN CERTIFICATE----- )(.*|\s]*)( -----END CERTIFICATE-----)'
132 4c9a536c John Giannelos
133 c1106cd7 John Giannelos
            client_cert = re.search(pem_re, environ["HTTP_SSL_CLIENT_CERT"])
134 c1106cd7 John Giannelos
            client_chain = re.search(pem_re, environ["HTTP_SSL_CLIENT_CERT_CHAIN_0"])
135 0e9a6098 John Giannelos
136 c1106cd7 John Giannelos
            client_cert_list=[]
137 c1106cd7 John Giannelos
            client_chain_list=[]
138 0e9a6098 John Giannelos
139 c1106cd7 John Giannelos
            for i in range(1,4):
140 c1106cd7 John Giannelos
                client_cert_list.append(string.strip(client_cert.group(i)))
141 0e9a6098 John Giannelos
142 c1106cd7 John Giannelos
            for i in range(1,4):
143 c1106cd7 John Giannelos
                client_chain_list.append(string.strip(client_chain.group(i)))
144 0e9a6098 John Giannelos
145 0e9a6098 John Giannelos
146 c1106cd7 John Giannelos
            cert = client_cert_list[0]+"\n"+client_cert_list[1].replace(" "," \n")+"\n"+client_cert_list[2]
147 c1106cd7 John Giannelos
            chain = client_chain_list[0]+"\n"+client_chain_list[1].replace(" "," \n")+"\n"+client_chain_list[2]
148 0e9a6098 John Giannelos
149 c1106cd7 John Giannelos
            ssl_dict["SSL_CLIENT_S_DN"] = environ["HTTP_SSL_CLIENT_S_DN"]
150 c1106cd7 John Giannelos
            ssl_dict["SSL_CLIENT_CERT"] = cert
151 c1106cd7 John Giannelos
            ssl_dict["SSL_CLIENT_CERT_CHAIN_0"] = chain
152 8619548c John Giannelos
153 c1106cd7 John Giannelos
            (user_dn, user_vo, user_fqans) = voms.authenticate(ssl_dict)
154 c1106cd7 John Giannelos
            print (user_dn, user_vo, user_fqans)
155 8619548c John Giannelos
156 c1106cd7 John Giannelos
            cursor = conn.cursor()
157 c1106cd7 John Giannelos
            query = "SELECT token FROM vo_map WHERE vo_name=?"
158 c1106cd7 John Giannelos
            cursor.execute(query,[(user_vo)])
159 19f06355 John Giannelos
160 c1106cd7 John Giannelos
            (token,) = cursor.fetchone()
161 19f06355 John Giannelos
162 c1106cd7 John Giannelos
            if token:
163 c1106cd7 John Giannelos
                compClient = ComputeClient(KAMAKI_CONFIG['compute_url'], token)
164 c1106cd7 John Giannelos
                cyclClient = CycladesClient(KAMAKI_CONFIG['compute_url'], token)
165 8619548c John Giannelos
166 c1106cd7 John Giannelos
                self.refresh_images(compClient,cyclClient)
167 c1106cd7 John Giannelos
                self.refresh_flavors(compClient,cyclClient)
168 c1106cd7 John Giannelos
                self.refresh_compute_instances(compClient)
169 b92a3d98 John Giannelos
170 b92a3d98 John Giannelos
171 c1106cd7 John Giannelos
                return self._call_occi(environ, response, security = None, token = token, snf = compClient, client = cyclClient)
172 c1106cd7 John Giannelos
            else:
173 c1106cd7 John Giannelos
                raise HTTPError(404, "Unauthorized access")
174 b92a3d98 John Giannelos
175 8619548c John Giannelos
        else:
176 c1106cd7 John Giannelos
            #Authorize with user token
177 c1106cd7 John Giannelos
            compClient = ComputeClient(KAMAKI_CONFIG['compute_url'], environ['HTTP_AUTH_TOKEN'])
178 c1106cd7 John Giannelos
            cyclClient = CycladesClient(KAMAKI_CONFIG['compute_url'], environ['HTTP_AUTH_TOKEN'])
179 c1106cd7 John Giannelos
            
180 c1106cd7 John Giannelos
            return self._call_occi(environ, response, security = None, token = environ['HTTP_AUTH_TOKEN'], snf = compClient, client = cyclClient)
181 22167a8c John Giannelos
182 b92a3d98 John Giannelos
183 43b14afb John Giannelos
def main():
184 43b14afb John Giannelos
185 c1106cd7 John Giannelos
    global ENABLE_VOMS, VOMS_DB
186 c1106cd7 John Giannelos
    (opts, args) = parse_arguments(sys.argv[1:])
187 c1106cd7 John Giannelos
188 c1106cd7 John Giannelos
    ENABLE_VOMS = opts.enable_voms
189 c1106cd7 John Giannelos
    VOMS_DB = opts.voms_db
190 c1106cd7 John Giannelos
191 b46572ab John Giannelos
    APP = MyAPP(registry = snfRegistry())
192 c687b8f4 John Giannelos
193 c1106cd7 John Giannelos
    COMPUTE_BACKEND = ComputeBackend()
194 c687b8f4 John Giannelos
    APP.register_backend(COMPUTE, COMPUTE_BACKEND)
195 c687b8f4 John Giannelos
    APP.register_backend(START, COMPUTE_BACKEND)
196 c687b8f4 John Giannelos
    APP.register_backend(STOP, COMPUTE_BACKEND)
197 c687b8f4 John Giannelos
    APP.register_backend(RESTART, COMPUTE_BACKEND)
198 c687b8f4 John Giannelos
    APP.register_backend(SUSPEND, COMPUTE_BACKEND)
199 c687b8f4 John Giannelos
    APP.register_backend(RESOURCE_TEMPLATE, MixinBackend())
200 c687b8f4 John Giannelos
    APP.register_backend(OS_TEMPLATE, MixinBackend())
201 c687b8f4 John Giannelos
 
202 c687b8f4 John Giannelos
    VALIDATOR_APP = validator(APP)
203 d7dfc401 John Giannelos
    HTTPD = make_server('', SERVER_CONFIG['port'], VALIDATOR_APP)
204 c687b8f4 John Giannelos
    HTTPD.serve_forever()
205 43b14afb John Giannelos