Skip to content

Commit

Permalink
Merge 6dff1e0 into 4d4e7ea
Browse files Browse the repository at this point in the history
  • Loading branch information
enolfc committed Mar 17, 2015
2 parents 4d4e7ea + 6dff1e0 commit 05d6d53
Show file tree
Hide file tree
Showing 18 changed files with 324 additions and 63 deletions.
19 changes: 0 additions & 19 deletions ooi/api/__init__.py
Original file line number Diff line number Diff line change
@@ -1,19 +0,0 @@
# -*- coding: utf-8 -*-

# Copyright 2015 Spanish National Research Council
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.


class BaseController(object):
pass
27 changes: 27 additions & 0 deletions ooi/api/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-

# Copyright 2015 Spanish National Research Council
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.


class Controller(object):
def __init__(self, app, openstack_version):
self.app = app
self.openstack_version = openstack_version

def _get_req(self, req, path=None):
req.script_name = self.openstack_version
if path is not None:
req.path_info = path
return req
56 changes: 53 additions & 3 deletions ooi/api/compute.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,60 @@
# License for the specific language governing permissions and limitations
# under the License.

import ooi.api
from ooi.api import base
from ooi.occi.core import collection
from ooi.occi.infrastructure import compute
from ooi.openstack import helpers
from ooi.openstack import templates


class ComputeController(ooi.api.BaseController):
class Controller(base.Controller):
def index(self, req):
tenant_id = req.environ["keystone.token_auth"].user.project_id
req.path_info = "/%s/servers" % tenant_id
req = self._get_req(req, path="/%s/servers" % tenant_id)
response = req.get_response(self.app)

servers = response.json_body.get("servers", [])
occi_compute_resources = []
if servers:
for s in servers:
s = compute.ComputeResource(title=s["name"], id=s["id"])
occi_compute_resources.append(s)

return collection.Collection(resources=occi_compute_resources)

def show(self, id, req):
tenant_id = req.environ["keystone.token_auth"].user.project_id

# get info from server
req = self._get_req(req, path="/%s/servers/%s" % (tenant_id, id))
response = req.get_response(self.app)
s = response.json_body.get("server", {})

# get info from flavor
req = self._get_req(req, path="/%s/flavors/%s" % (tenant_id,
s["flavor"]["id"]))
response = req.get_response(self.app)
flavor = response.json_body.get("flavor", {})
res_tpl = templates.OpenStackResourceTemplate(flavor["name"],
flavor["vcpus"],
flavor["ram"],
flavor["disk"])

# get info from image
req = self._get_req(req, path="/%s/images/%s" % (tenant_id,
s["image"]["id"]))
response = req.get_response(self.app)
image = response.json_body.get("image", {})
os_tpl = templates.OpenStackOSTemplate(image["id"],
image["name"])

# build the compute object
# TODO(enolfc): link to network + storage
comp = compute.ComputeResource(title=s["name"], id=s["id"],
cores=flavor["vcpus"],
hostname=s["name"],
memory=flavor["ram"],
state=helpers.occi_state(s["status"]),
mixins=[os_tpl, res_tpl])
return [comp]
10 changes: 3 additions & 7 deletions ooi/api/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,12 @@
# License for the specific language governing permissions and limitations
# under the License.

from ooi.api import base
from ooi.occi.infrastructure import compute
import ooi.wsgi


class Controller(object):
def index(self, *args, **kwargs):
class Controller(base.Controller):
def index(self, req):
l = []
l.extend(compute.ComputeResource.actions)
return l


def create_resource():
return ooi.wsgi.Resource(Controller())
4 changes: 3 additions & 1 deletion ooi/occi/core/action.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,6 @@ class Action(category.Category):
An Action represents an invocable operation applicable to a resource
instance.
"""
pass

def _class_name(self):
return "action"
12 changes: 12 additions & 0 deletions ooi/occi/core/attribute.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,18 @@ def name(self):
def value(self):
return self._value

def _as_str(self):
if isinstance(self._value, six.string_types):
return '"%s"' % self._value
elif isinstance(self._value, bool):
return '"%s"' % str(self._value).lower()
else:
return "%s" % self._value

def __str__(self):
"""Render the attribute to text/plain."""
return "X-OCCI-Attribute: %s=%s" % (self.name, self._as_str())


class MutableAttribute(Attribute):
@Attribute.value.setter
Expand Down
8 changes: 6 additions & 2 deletions ooi/occi/core/category.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,18 @@ def __init__(self, scheme, term, title, attributes=None, location=None):
self.attributes = attributes
self.location = location

def _class_name(self):
"""Returns this class name (see OCCI v1.1 rendering)."""
raise ValueError

def _as_str(self):
d = {
"term": self.term,
"scheme": self.scheme,
"class": self.__class__.__name__.lower()
"class": self._class_name()
}

return "%(term)s; scheme=%(scheme)s; class=%(class)s" % d
return '%(term)s; scheme="%(scheme)s"; class="%(class)s"' % d

def headers(self):
return [("Category", self._as_str())]
Expand Down
56 changes: 56 additions & 0 deletions ooi/occi/core/collection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-

# Copyright 2015 Spanish National Research Council
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.


class Collection(object):
"""An OCCI Collection is used to render a set of OCCI objects.
Depending on the rendering and the contents of the collection, there will
be one output or another. This class should do the magic and render the
proper information, taking into account what is in the collection.
"""
def __init__(self, kinds=[], mixins=[], actions=[],
resources=[], links=[]):

self.kinds = kinds
self.mixins = mixins
self.actions = actions
self.resources = resources
self.links = links

def __str__(self):
"""Render the collection to text/plain."""
# NOTE(aloga): This is unfinished, we need to check what is inside the
# collection and render it properly. For example, if we have a
# collection of resources, we should render only their locations.
ret = []
for what in [self.kinds, self.mixins, self.actions,
self.resources, self.links]:
for el in what:
ret.append("X-OCCI-Location: %s" % el.location)
return "\n".join(ret)

def headers(self):
"""Render the collection to text/occi."""
# NOTE(aloga): This is unfinished, we need to check what is inside the
# collection and render it properly. For example, if we have a
# collection of resources, we should render only their locations.
headers = []
for what in [self.kinds, self.mixins, self.actions,
self.resources, self.links]:
for el in what:
headers.append(("X-OCCI-Location", el.location))
return headers
14 changes: 14 additions & 0 deletions ooi/occi/core/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,17 @@ def title(self):
@title.setter
def title(self, value):
self.attributes["occi.core.title"].value = value

@property
def location(self):
return helpers.join_url(self.kind.location, self.id)

def __str__(self):
"""Render the entity to text/plain."""
ret = ["%s" % self.kind]
for m in self.mixins:
ret.append("%s" % m)
for attr_name in self.attributes:
if self.attributes[attr_name].value is not None:
ret.append("%s" % self.attributes[attr_name])
return "\n".join(ret)
3 changes: 3 additions & 0 deletions ooi/occi/core/kind.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,6 @@ def __init__(self, scheme, term, title, attributes=None, location=None,

self.related = related
self.actions = actions

def _class_name(self):
return "kind"
3 changes: 3 additions & 0 deletions ooi/occi/core/mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,6 @@ def __init__(self, scheme, term, title, attributes=None, location=None,

self.related = related
self.actions = actions

def _class_name(self):
return "mixin"
7 changes: 7 additions & 0 deletions ooi/occi/core/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,10 @@ def summary(self):
@summary.setter
def summary(self, value):
self.attributes["occi.core.summary"].value = value

def __str__(self):
"""Render the resource to text/plain."""
ret = [super(Resource, self).__str__()]
for link in self.links:
ret.append("%s" % link)
return "\n".join(ret)
6 changes: 6 additions & 0 deletions ooi/occi/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,9 @@ def check_type(obj_list, obj_type):

if not all([isinstance(i, obj_type) for i in obj_list]):
raise TypeError('object must be of class %s' % obj_type)


def join_url(prefix, remainder, fragments=None):
if fragments:
remainder = "%s#%s" % (remainder, fragments)
return urlparse.urljoin(prefix, remainder)
4 changes: 1 addition & 3 deletions ooi/occi/infrastructure/compute.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@ class ComputeResource(resource.Resource):

def __init__(self, title, summary=None, id=None, architecture=None,
cores=None, hostname=None, speed=None, memory=None,
state=None):

mixins = []
state=None, mixins=[]):

super(ComputeResource, self).__init__(title, mixins, summary=summary,
id=id)
Expand Down
10 changes: 10 additions & 0 deletions ooi/openstack/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,13 @@

def build_scheme(category):
return helpers.build_scheme(category, prefix=_PREFIX)


# TODO(enolfc): Check the correct names of nova states
def occi_state(nova_status):
if nova_status in ["ACTIVE"]:
return "active"
elif nova_status in ["PAUSED", "SUSPENDED", "STOPPED"]:
return "suspended"
else:
return "inactive"
Loading

0 comments on commit 05d6d53

Please sign in to comment.