Commit 4ab8bfab authored by nasia's avatar nasia
Browse files

New features and network backend support, newer version of kamaki

parent 1fa7e54b
......@@ -2,22 +2,24 @@
from snfOCCI.registry import snfRegistry
from snfOCCI.compute import ComputeBackend
from snfOCCI.network import NetworkBackend, IpNetworkBackend, IpNetworkInterfaceBackend, NetworkInterfaceBackend
from snfOCCI.config import SERVER_CONFIG, KAMAKI_CONFIG
from kamaki.clients.compute import ComputeClient
from kamaki.clients.cyclades import CycladesClient
from kamaki.config import Config
from kamaki.clients import ClientError
from occi.core_model import Mixin, Resource
from occi.backend import MixinBackend
from occi.extensions.infrastructure import COMPUTE, START, STOP, SUSPEND, RESTART, RESOURCE_TEMPLATE, OS_TEMPLATE
from occi.backend import MixinBackend, KindBackend
from occi.extensions.infrastructure import COMPUTE, START, STOP, SUSPEND, RESTART, RESOURCE_TEMPLATE, OS_TEMPLATE, NETWORK, IPNETWORK, NETWORKINTERFACE,IPNETWORKINTERFACE
from occi.wsgi import Application
from occi.exceptions import HTTPError
from occi import core_model
from wsgiref.simple_server import make_server
from wsgiref.validate import validator
import uuid
class MyAPP(Application):
'''
......@@ -35,20 +37,63 @@ class MyAPP(Application):
def refresh_flavors(self, snf, client):
flavors = snf.list_flavors()
print "Retrieving details for each image id"
for flavor in flavors:
details = snf.get_flavor_details(flavor['id'])
FLAVOR_ATTRIBUTES = {'occi.core.id': flavor['id'],
'occi.compute.cores': details['cpu'],
'occi.compute.memory': details['ram'],
'occi.storage.size': details['disk'],
'occi.compute.cores': str(details['vcpus']),
'occi.compute.memory': str(details['ram']),
'occi.storage.size': str(details['disk']),
}
FLAVOR = Mixin("http://schemas.ogf.org/occi/infrastructure#", str(flavor['name']), [RESOURCE_TEMPLATE], attributes = FLAVOR_ATTRIBUTES)
self.register_backend(FLAVOR, MixinBackend())
def refresh_compute_instances(self, snf):
def refresh_flavors_norecursive(self, snf, client):
flavors = snf.list_flavors(True)
print "Retrieving details for each image id"
for flavor in flavors:
# details = snf.get_flavor_details(flavor['id'])
FLAVOR_ATTRIBUTES = {'occi.core.id': flavor['id'],
'occi.compute.cores': str(flavor['vcpus']),
'occi.compute.memory': str(flavor['ram']),
'occi.storage.size': str(flavor['disk']),
}
FLAVOR = Mixin("http://schemas.ogf.org/occi/infrastructure#", str(flavor['name']), [RESOURCE_TEMPLATE], attributes = FLAVOR_ATTRIBUTES)
self.register_backend(FLAVOR, MixinBackend())
def refresh_network_instances(self,client):
networks =client.networks_get(command = 'detail')
network_details = networks.json['networks']
resources = self.registry.resources
occi_keys = resources.keys()
for network in network_details:
if '/network/'+str(network['id']) not in occi_keys:
netID = '/network/'+str(network['id'])
snf_net = core_model.Resource(netID,
NETWORK,
[IPNETWORK])
snf_net.attributes['occi.core.id'] = str(network['id'])
#This info comes from the network details
snf_net.attributes['occi.network.state'] = str(network['status'])
snf_net.attributes['occi.network.gateway'] = str(network['gateway'])
if network['public'] == True:
snf_net.attributes['occi.network.type'] = "Public = True"
else:
snf_net.attributes['occi.network.type'] = "Public = False"
self.registry.add_resource(netID, snf_net, None)
def refresh_compute_instances(self, snf, client):
'''Syncing registry with cyclades resources'''
servers = snf.list_servers()
snf_keys = []
for server in servers:
......@@ -57,56 +102,135 @@ class MyAPP(Application):
resources = self.registry.resources
occi_keys = resources.keys()
print resources.keys()
for serverID in occi_keys:
if '/compute/' in serverID and resources[serverID].attributes['occi.compute.hostname'] == "":
self.registry.delete_resource(serverID, None)
occi_keys = resources.keys()
#Compute instances in synnefo not available in registry
diff = [x for x in snf_keys if '/compute/'+x not in occi_keys]
for key in diff:
details = snf.get_server_details(int(key))
flavor = snf.get_flavor_details(details['flavorRef'])
image = snf.get_image_details(details['imageRef'])
for i in self.registry.backends:
if i.term == str(image['name']):
rel_image = i
if i.term == str(flavor['name']):
rel_flavor = i
resource = Resource(key, COMPUTE, [rel_flavor, rel_image])
resource.actions = [START]
resource.attributes['occi.core.id'] = key
resource.attributes['occi.compute.state'] = 'inactive'
resource.attributes['occi.compute.architecture'] = SERVER_CONFIG['compute_arch']
resource.attributes['occi.compute.cores'] = flavor['cpu']
resource.attributes['occi.compute.memory'] = flavor['ram']
resource.attributes['occi.compute.hostname'] = SERVER_CONFIG['hostname'] % {'id':int(key)}
self.registry.add_resource(key, resource, None)
flavor = snf.get_flavor_details(details['flavor']['id'])
try:
print "line 65:Finished getting image details for VM with ID" + str(details['flavor']['id'])
image = snf.get_image_details(details['image']['id'])
for i in self.registry.backends:
if i.term == str(image['name']):
rel_image = i
if i.term == str(flavor['name']):
rel_flavor = i
resource = Resource(key, COMPUTE, [rel_flavor, rel_image])
resource.actions = [START]
resource.attributes['occi.core.id'] = key
resource.attributes['occi.compute.state'] = 'inactive'
resource.attributes['occi.compute.architecture'] = SERVER_CONFIG['compute_arch']
resource.attributes['occi.compute.cores'] = str(flavor['vcpus'])
resource.attributes['occi.compute.memory'] = str(flavor['ram'])
resource.attributes['occi.core.title'] = str(details['name'])
networkIDs = details['addresses'].keys()
if len(networkIDs)>0:
#resource.attributes['occi.compute.hostname'] = SERVER_CONFIG['hostname'] % {'id':int(key)}
resource.attributes['occi.compute.hostname'] = str(details['addresses'][networkIDs[0]][0]['addr'])
#resource.attributes['occi.networkinterface.address'] = str(details['addresses'][networkIDs[0]][0]['addr'])
else:
resource.attributes['occi.compute.hostname'] = ""
self.registry.add_resource(key, resource, None)
for netKey in networkIDs:
link_id = str(uuid.uuid4())
NET_LINK = core_model.Link("http://schemas.ogf.org/occi/infrastructure#networkinterface" + link_id,
NETWORKINTERFACE,
[IPNETWORKINTERFACE], resource,
self.registry.resources['/network/'+str(netKey)])
for version in details['addresses'][netKey]:
if version['version']==4:
ip4address = str(version['addr'])
allocheme = str(version['OS-EXT-IPS:type'])
elif version['version']==6:
ip6address = str(version['addr'])
if 'attachments' in details.keys():
for item in details['attachments']:
NET_LINK.attributes ={'occi.core.id':link_id,
'occi.networkinterface.allocation' : allocheme,
'occi.networking.interface': str(item['id']),
'occi.networkinterface.mac' : str(item['mac_address']),
'occi.networkinterface.ip4' : ip4address,
'occi.networkinterface.ip6' : ip6address
}
elif len(details['addresses'][netKey])>0:
NET_LINK.attributes ={'occi.core.id':link_id,
'occi.networkinterface.allocation' : allocheme,
'occi.networking.interface': '',
'occi.networkinterface.mac' : '',
'occi.networkinterface.ip4' : ip4address,
'occi.networkinterface.ip6' : ip6address
}
else:
NET_LINK.attributes ={'occi.core.id':link_id,
'occi.networkinterface.allocation' : '',
'occi.networking.interface': '',
'occi.networkinterface.mac' : '',
'occi.networkinterface.ip4' :'',
'occi.networkinterface.ip6' : '' }
resource.links.append(NET_LINK)
self.registry.add_resource(link_id, NET_LINK, None)
except ClientError as ce:
if ce.status == 404:
print('Image not found, sorry!!!')
continue
else:
raise ce
#Compute instances in registry not available in synnefo
diff = [x for x in occi_keys if x[9:] not in snf_keys]
for key in diff:
self.registry.delete_resource(key, None)
if '/network/' not in key:
self.registry.delete_resource(key, None)
def __call__(self, environ, response):
compClient = ComputeClient(KAMAKI_CONFIG['compute_url'], environ['HTTP_AUTH_TOKEN'])
cyclClient = CycladesClient(KAMAKI_CONFIG['compute_url'], environ['HTTP_AUTH_TOKEN'])
#Up-to-date flavors and images
self.refresh_images(compClient,cyclClient)
self.refresh_flavors(compClient,cyclClient)
self.refresh_compute_instances(compClient)
# token will be represented in self.extras
return self._call_occi(environ, response, security = None, token = environ['HTTP_AUTH_TOKEN'], snf = compClient, client = cyclClient)
compClient = ComputeClient(KAMAKI_CONFIG['compute_url'], environ['HTTP_AUTH_TOKEN'])
cyclClient = CycladesClient(KAMAKI_CONFIG['compute_url'], environ['HTTP_AUTH_TOKEN'])
#Up-to-date flavors and images
print "@refresh_images"
self.refresh_images(compClient,cyclClient)
print "@refresh_flavors"
self.refresh_flavors_norecursive(compClient,cyclClient)
self.refresh_network_instances(cyclClient)
print "@refresh_compute_instances"
self.refresh_compute_instances(compClient,cyclClient)
# token will be represented in self.extras
return self._call_occi(environ, response, security = None, token = environ['HTTP_AUTH_TOKEN'], snf = compClient, client = cyclClient)
def main():
APP = MyAPP(registry = snfRegistry())
COMPUTE_BACKEND = ComputeBackend()
NETWORK_BACKEND = NetworkBackend()
NETWORKINTERFACE_BACKEND = NetworkInterfaceBackend()
IPNETWORK_BACKEND = IpNetworkBackend()
IPNETWORKINTERFACE_BACKEND = IpNetworkInterfaceBackend()
APP.register_backend(COMPUTE, COMPUTE_BACKEND)
APP.register_backend(START, COMPUTE_BACKEND)
APP.register_backend(STOP, COMPUTE_BACKEND)
......@@ -115,7 +239,14 @@ def main():
APP.register_backend(RESOURCE_TEMPLATE, MixinBackend())
APP.register_backend(OS_TEMPLATE, MixinBackend())
# Network related backends
APP.register_backend(NETWORK, NETWORK_BACKEND)
APP.register_backend(IPNETWORK, IPNETWORK_BACKEND)
APP.register_backend(NETWORKINTERFACE,NETWORKINTERFACE_BACKEND)
APP.register_backend(IPNETWORKINTERFACE, IPNETWORKINTERFACE_BACKEND)
VALIDATOR_APP = validator(APP)
HTTPD = make_server('', SERVER_CONFIG['port'], VALIDATOR_APP)
HTTPD.serve_forever()
......@@ -40,15 +40,24 @@ class ComputeBackend(MyBackend):
vm_name = entity.attributes['occi.core.title']
info = snf.create_server(vm_name, flavor_id, image_id)
entity.actions = [START]
entity.attributes['occi.compute.state'] = 'inactive'
entity.attributes['occi.core.id'] = str(info['id'])
entity.attributes['occi.compute.architecture'] = SERVER_CONFIG['compute_arch']
entity.attributes['occi.compute.cores'] = flavor.attributes['occi.compute.cores']
entity.attributes['occi.compute.memory'] = flavor.attributes['occi.compute.memory']
entity.attributes['occi.compute.hostname'] = SERVER_CONFIG['hostname'] % {'id':info['id']}
# entity.attributes['occi.compute.hostname'] = SERVER_CONFIG['hostname'] % {'id':info['id']}
info['adminPass']= ""
print info
networkIDs = info['addresses'].keys()
#resource.attributes['occi.compute.hostname'] = SERVER_CONFIG['hostname'] % {'id':int(key)}
if len(networkIDs)>0:
entity.attributes['occi.compute.hostname'] = str(info['addresses'][networkIDs[0]][0]['addr'])
else:
entity.attributes['occi.compute.hostname'] = ""
except (UnboundLocalError, KeyError) as e:
raise HTTPError(406, 'Missing details about compute instance')
......
from snfOCCI.config import SERVER_CONFIG
from occi.backend import ActionBackend, KindBackend, MixinBackend
from occi.exceptions import HTTPError
#Network Backend for snf-occi-server
class NetworkBackend(KindBackend, ActionBackend):
def create(self, entity, extras):
raise HTTPError(501,"Currently not supported.")
def action(self, entity, action, attributes, extras):
raise HTTPError(501, "Currently not supported.")
class IpNetworkBackend(MixinBackend):
def create(self, entity, extras):
raise HTTPError(501,"Currently not supported.")
class IpNetworkInterfaceBackend(MixinBackend):
pass
class NetworkInterfaceBackend(KindBackend):
def create(self, entity, extras):
raise HTTPError(501,"Currently not supported.")
def action(self, entity, action, attributes, extras):
raise HTTPError(501, "Currently not supported.")
def update(self, old, new, extras):
raise HTTPError(501, "Currently not supported.")
def replace(self, old, new, extras):
raise HTTPError(501, "Currently not supported.")
from kamaki.clients.compute import ComputeClient
from kamaki.clients.cyclades import CycladesClient
from kamaki.config import Config
from kamaki.cli.config import Config
from occi import registry
from occi.core_model import Mixin
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment