Revision 4ab8bfab

b/snfOCCI/APIserver.py
2 2

  
3 3
from snfOCCI.registry import snfRegistry
4 4
from snfOCCI.compute import ComputeBackend
5
from snfOCCI.network import NetworkBackend, IpNetworkBackend, IpNetworkInterfaceBackend, NetworkInterfaceBackend
6

  
5 7
from snfOCCI.config import SERVER_CONFIG, KAMAKI_CONFIG
6 8

  
7 9
from kamaki.clients.compute import ComputeClient
8 10
from kamaki.clients.cyclades import CycladesClient
9
from kamaki.config  import Config
11
from kamaki.clients import ClientError
10 12

  
11 13
from occi.core_model import Mixin, Resource
12
from occi.backend import MixinBackend
13
from occi.extensions.infrastructure import COMPUTE, START, STOP, SUSPEND, RESTART, RESOURCE_TEMPLATE, OS_TEMPLATE
14
from occi.backend import MixinBackend, KindBackend
15
from occi.extensions.infrastructure import COMPUTE, START, STOP, SUSPEND, RESTART, RESOURCE_TEMPLATE, OS_TEMPLATE, NETWORK, IPNETWORK, NETWORKINTERFACE,IPNETWORKINTERFACE 
14 16
from occi.wsgi import Application
17
from occi.exceptions import HTTPError
18
from occi import core_model
15 19

  
16 20
from wsgiref.simple_server import make_server
17 21
from wsgiref.validate import validator
18

  
19

  
20

  
22
import uuid
21 23

  
22 24
class MyAPP(Application):
23 25
    '''
......
35 37
    def refresh_flavors(self, snf, client):
36 38
        
37 39
        flavors = snf.list_flavors()
40
        print "Retrieving details for each image id"
38 41
        for flavor in flavors:
39 42
            details = snf.get_flavor_details(flavor['id'])
40 43
            FLAVOR_ATTRIBUTES = {'occi.core.id': flavor['id'],
41
                                 'occi.compute.cores': details['cpu'],
42
                                 'occi.compute.memory': details['ram'],
43
                                 'occi.storage.size': details['disk'],
44
                                 'occi.compute.cores': str(details['vcpus']),
45
                                 'occi.compute.memory': str(details['ram']),
46
                                 'occi.storage.size': str(details['disk']),
44 47
                                 }
45 48
            FLAVOR = Mixin("http://schemas.ogf.org/occi/infrastructure#", str(flavor['name']), [RESOURCE_TEMPLATE], attributes = FLAVOR_ATTRIBUTES)
46 49
            self.register_backend(FLAVOR, MixinBackend())
47

  
48

  
49
    def refresh_compute_instances(self, snf):
50
            
51
    def refresh_flavors_norecursive(self, snf, client):
52
        flavors = snf.list_flavors(True)
53
        print "Retrieving details for each image id"
54
        for flavor in flavors:
55
            # details = snf.get_flavor_details(flavor['id'])
56
            FLAVOR_ATTRIBUTES = {'occi.core.id': flavor['id'],
57
                                 'occi.compute.cores': str(flavor['vcpus']),
58
                                 'occi.compute.memory': str(flavor['ram']),
59
                                 'occi.storage.size': str(flavor['disk']),
60
                                 }
61
             
62
            FLAVOR = Mixin("http://schemas.ogf.org/occi/infrastructure#", str(flavor['name']), [RESOURCE_TEMPLATE], attributes = FLAVOR_ATTRIBUTES)
63
            self.register_backend(FLAVOR, MixinBackend())
64
            
65
       
66
    def refresh_network_instances(self,client):
67
        networks =client.networks_get(command = 'detail')
68
        network_details = networks.json['networks']
69
        resources = self.registry.resources
70
        occi_keys = resources.keys()
71
         
72
        for network in network_details:
73
            if '/network/'+str(network['id']) not in occi_keys:
74
                netID = '/network/'+str(network['id'])   
75
                snf_net = core_model.Resource(netID,
76
                                           NETWORK,
77
                                           [IPNETWORK])
78
                
79
                snf_net.attributes['occi.core.id'] = str(network['id']) 
80
               
81
                #This info comes from the network details
82
                snf_net.attributes['occi.network.state'] = str(network['status'])
83
                snf_net.attributes['occi.network.gateway'] = str(network['gateway'])
84
               
85
                if network['public'] == True:
86
                    snf_net.attributes['occi.network.type'] = "Public = True"
87
                else:
88
                    snf_net.attributes['occi.network.type'] = "Public = False"
89
                    
90
                self.registry.add_resource(netID, snf_net, None)       
91
            
92
        
93
            
94
    def refresh_compute_instances(self, snf, client):
50 95
        '''Syncing registry with cyclades resources'''
51

  
96
        
52 97
        servers = snf.list_servers()
53 98
        snf_keys = []
54 99
        for server in servers:
......
57 102
        resources = self.registry.resources
58 103
        occi_keys = resources.keys()
59 104
        
105
        print resources.keys()
106
        
107
        for serverID in occi_keys:
108
            if '/compute/' in serverID and resources[serverID].attributes['occi.compute.hostname'] == "":
109
                self.registry.delete_resource(serverID, None)
110
        
111
        occi_keys = resources.keys()
112
        
113
            
60 114
        #Compute instances in synnefo not available in registry
61 115
        diff = [x for x in snf_keys if '/compute/'+x not in occi_keys]
62 116
        for key in diff:
63 117

  
64 118
            details = snf.get_server_details(int(key))
65
            flavor = snf.get_flavor_details(details['flavorRef'])
66
            image = snf.get_image_details(details['imageRef'])
67

  
68
            for i in self.registry.backends:
69
                if i.term == str(image['name']):
70
                    rel_image = i
71
                if i.term == str(flavor['name']):
72
                    rel_flavor = i
73

  
74
            resource = Resource(key, COMPUTE, [rel_flavor, rel_image])
75
            resource.actions = [START]
76
            resource.attributes['occi.core.id'] = key
77
            resource.attributes['occi.compute.state'] = 'inactive'
78
            resource.attributes['occi.compute.architecture'] = SERVER_CONFIG['compute_arch']
79
            resource.attributes['occi.compute.cores'] = flavor['cpu']
80
            resource.attributes['occi.compute.memory'] = flavor['ram']
81
            resource.attributes['occi.compute.hostname'] = SERVER_CONFIG['hostname'] % {'id':int(key)}
82

  
83
            self.registry.add_resource(key, resource, None)
84

  
119
            flavor = snf.get_flavor_details(details['flavor']['id'])
120
            
121
            try:
122
                print "line 65:Finished getting image details for VM with ID" + str(details['flavor']['id'])
123
                image = snf.get_image_details(details['image']['id'])
124
                
125
                for i in self.registry.backends:
126
                    if i.term == str(image['name']):
127
                        rel_image = i
128
                    if i.term == str(flavor['name']):
129
                        rel_flavor = i
130
                        
131
                resource = Resource(key, COMPUTE, [rel_flavor, rel_image])
132
                resource.actions = [START]
133
                resource.attributes['occi.core.id'] = key
134
                resource.attributes['occi.compute.state'] = 'inactive'
135
                resource.attributes['occi.compute.architecture'] = SERVER_CONFIG['compute_arch']
136
                resource.attributes['occi.compute.cores'] = str(flavor['vcpus'])
137
                resource.attributes['occi.compute.memory'] = str(flavor['ram'])
138
                resource.attributes['occi.core.title'] = str(details['name'])
139
                networkIDs = details['addresses'].keys()
140
                if len(networkIDs)>0: 
141
                    #resource.attributes['occi.compute.hostname'] = SERVER_CONFIG['hostname'] % {'id':int(key)}
142
                    resource.attributes['occi.compute.hostname'] =  str(details['addresses'][networkIDs[0]][0]['addr'])
143
                    #resource.attributes['occi.networkinterface.address'] = str(details['addresses'][networkIDs[0]][0]['addr'])
144
                else:
145
                    resource.attributes['occi.compute.hostname'] = ""
146
                    
147
                self.registry.add_resource(key, resource, None)  
148
                
149
                for netKey in networkIDs:
150
                    link_id = str(uuid.uuid4())
151
                    NET_LINK = core_model.Link("http://schemas.ogf.org/occi/infrastructure#networkinterface" + link_id,
152
                                               NETWORKINTERFACE,
153
                                               [IPNETWORKINTERFACE], resource,
154
                                               self.registry.resources['/network/'+str(netKey)])
155
                    
156
                    for version in details['addresses'][netKey]:
157
                        if version['version']==4:
158
                            ip4address = str(version['addr'])
159
                            allocheme = str(version['OS-EXT-IPS:type'])
160
                        elif version['version']==6:
161
                            ip6address = str(version['addr'])
162
                   
163
                    if 'attachments' in details.keys():
164
                        for item in details['attachments']:
165
                            NET_LINK.attributes ={'occi.core.id':link_id,
166
                                          'occi.networkinterface.allocation' : allocheme,
167
                                          'occi.networking.interface': str(item['id']),
168
                                          'occi.networkinterface.mac' : str(item['mac_address']),
169
                                          'occi.networkinterface.ip4' : ip4address,
170
                                          'occi.networkinterface.ip6' :  ip6address                      
171
                                      }
172
                    elif  len(details['addresses'][netKey])>0:
173
                        NET_LINK.attributes ={'occi.core.id':link_id,
174
                                          'occi.networkinterface.allocation' : allocheme,
175
                                          'occi.networking.interface': '',
176
                                          'occi.networkinterface.mac' : '',
177
                                          'occi.networkinterface.ip4' : ip4address,
178
                                          'occi.networkinterface.ip6' :  ip6address                      
179
                                      }
180
    
181
                    else:
182
                        NET_LINK.attributes ={'occi.core.id':link_id,
183
                                          'occi.networkinterface.allocation' : '',
184
                                          'occi.networking.interface': '',
185
                                          'occi.networkinterface.mac' : '',
186
                                          'occi.networkinterface.ip4' :'',
187
                                          'occi.networkinterface.ip6' : '' }
188
                                      
189
                    resource.links.append(NET_LINK)
190
                    self.registry.add_resource(link_id, NET_LINK, None)
191
                     
192
                
193
            except ClientError as ce:
194
                if ce.status == 404:
195
                    print('Image not found, sorry!!!')
196
                    continue
197
                else:
198
                    raise ce
199
                  
85 200
        #Compute instances in registry not available in synnefo
86 201
        diff = [x for x in occi_keys if x[9:] not in snf_keys]
87 202
        for key in diff:
88
            self.registry.delete_resource(key, None)
89

  
203
            if '/network/' not in key:
204
                self.registry.delete_resource(key, None)
90 205

  
206
    
91 207
    def __call__(self, environ, response):
92

  
93
        compClient = ComputeClient(KAMAKI_CONFIG['compute_url'], environ['HTTP_AUTH_TOKEN'])
94
        cyclClient = CycladesClient(KAMAKI_CONFIG['compute_url'], environ['HTTP_AUTH_TOKEN'])
95

  
96
        #Up-to-date flavors and images
97
        self.refresh_images(compClient,cyclClient)
98
        self.refresh_flavors(compClient,cyclClient)
99
        self.refresh_compute_instances(compClient)
100

  
101
        # token will be represented in self.extras
102
        return self._call_occi(environ, response, security = None, token = environ['HTTP_AUTH_TOKEN'], snf = compClient, client = cyclClient)
208
        
209
            compClient = ComputeClient(KAMAKI_CONFIG['compute_url'], environ['HTTP_AUTH_TOKEN'])
210
            cyclClient = CycladesClient(KAMAKI_CONFIG['compute_url'], environ['HTTP_AUTH_TOKEN'])
211

  
212
            #Up-to-date flavors and images
213
            print "@refresh_images"
214
            self.refresh_images(compClient,cyclClient)
215
            print "@refresh_flavors"
216
            self.refresh_flavors_norecursive(compClient,cyclClient)
217
            self.refresh_network_instances(cyclClient)
218
            print "@refresh_compute_instances"
219
            self.refresh_compute_instances(compClient,cyclClient)
220
           
221
            # token will be represented in self.extras
222
            return self._call_occi(environ, response, security = None, token = environ['HTTP_AUTH_TOKEN'], snf = compClient, client = cyclClient)
103 223

  
104 224

  
105 225
def main():
106 226

  
107 227
    APP = MyAPP(registry = snfRegistry())
108 228
    COMPUTE_BACKEND = ComputeBackend()
109

  
229
    NETWORK_BACKEND = NetworkBackend() 
230
    NETWORKINTERFACE_BACKEND = NetworkInterfaceBackend()
231
    IPNETWORK_BACKEND = IpNetworkBackend()
232
    IPNETWORKINTERFACE_BACKEND = IpNetworkInterfaceBackend()
233
      
110 234
    APP.register_backend(COMPUTE, COMPUTE_BACKEND)
111 235
    APP.register_backend(START, COMPUTE_BACKEND)
112 236
    APP.register_backend(STOP, COMPUTE_BACKEND)
......
115 239
    APP.register_backend(RESOURCE_TEMPLATE, MixinBackend())
116 240
    APP.register_backend(OS_TEMPLATE, MixinBackend())
117 241
 
242
    # Network related backends
243
    APP.register_backend(NETWORK, NETWORK_BACKEND)
244
    APP.register_backend(IPNETWORK, IPNETWORK_BACKEND)
245
    APP.register_backend(NETWORKINTERFACE,NETWORKINTERFACE_BACKEND)
246
    APP.register_backend(IPNETWORKINTERFACE, IPNETWORKINTERFACE_BACKEND)
247
     
118 248
    VALIDATOR_APP = validator(APP)
249
  
119 250
    HTTPD = make_server('', SERVER_CONFIG['port'], VALIDATOR_APP)
120 251
    HTTPD.serve_forever()
121 252
    
b/snfOCCI/compute.py
40 40

  
41 41
            vm_name = entity.attributes['occi.core.title']
42 42
            info = snf.create_server(vm_name, flavor_id, image_id)
43

  
43
           
44 44
            entity.actions = [START]
45 45
            entity.attributes['occi.compute.state'] = 'inactive'
46 46
            entity.attributes['occi.core.id'] = str(info['id'])
47 47
            entity.attributes['occi.compute.architecture'] = SERVER_CONFIG['compute_arch']
48 48
            entity.attributes['occi.compute.cores'] = flavor.attributes['occi.compute.cores']
49 49
            entity.attributes['occi.compute.memory'] = flavor.attributes['occi.compute.memory']
50
            entity.attributes['occi.compute.hostname'] = SERVER_CONFIG['hostname'] % {'id':info['id']}
51

  
50
           
51
            # entity.attributes['occi.compute.hostname'] = SERVER_CONFIG['hostname'] % {'id':info['id']}
52
            info['adminPass']= ""
53
            print info
54
            networkIDs = info['addresses'].keys()
55
                #resource.attributes['occi.compute.hostname'] = SERVER_CONFIG['hostname'] % {'id':int(key)}
56
            if len(networkIDs)>0:    
57
                entity.attributes['occi.compute.hostname'] =  str(info['addresses'][networkIDs[0]][0]['addr'])
58
            else:
59
                entity.attributes['occi.compute.hostname'] = ""
60
               
52 61
        except (UnboundLocalError, KeyError) as e:
53 62
            raise HTTPError(406, 'Missing details about compute instance')
54 63
            
b/snfOCCI/network.py
1
from snfOCCI.config import SERVER_CONFIG
2

  
3
from occi.backend import ActionBackend, KindBackend, MixinBackend
4
from occi.exceptions import HTTPError
5

  
6

  
7
#Network Backend for snf-occi-server
8

  
9
class NetworkBackend(KindBackend, ActionBackend):
10
    def create(self, entity, extras):
11
        raise HTTPError(501,"Currently not supported.")
12

  
13
    def action(self, entity, action, attributes, extras):
14
        raise HTTPError(501, "Currently not supported.")
15
    
16
class IpNetworkBackend(MixinBackend):
17
    def create(self, entity, extras):
18
        raise HTTPError(501,"Currently not supported.")
19

  
20
class IpNetworkInterfaceBackend(MixinBackend):
21
    
22
    pass
23

  
24
class NetworkInterfaceBackend(KindBackend):
25
    
26
    def create(self, entity, extras):
27
        raise HTTPError(501,"Currently not supported.")
28

  
29
    def action(self, entity, action, attributes, extras):
30
        raise HTTPError(501, "Currently not supported.")
31

  
32

  
33
    def update(self, old, new, extras):
34
        raise HTTPError(501, "Currently not supported.")
35

  
36
    def replace(self, old, new, extras):
37
        raise HTTPError(501, "Currently not supported.")
38

  
39
    
b/snfOCCI/registry.py
1 1
from kamaki.clients.compute import ComputeClient
2 2
from kamaki.clients.cyclades import CycladesClient
3
from kamaki.config  import Config
3
from kamaki.cli.config  import Config
4 4

  
5 5
from occi import registry
6 6
from occi.core_model import Mixin

Also available in: Unified diff