Commit 09e73a8e by Simon János

added new resource types; changed tests accordingly

parent 553e5137
import copy
import json
import uuid
from socket import inet_aton
from enum import Enum
from oslo_config import cfg
from voluptuous import Schema, Invalid, MultipleInvalid, Any, ALLOW_EXTRA, PREVENT_EXTRA, re, Required, Optional, All, \
Range
from voluptuous import Schema, Invalid, MultipleInvalid, Any, ALLOW_EXTRA, PREVENT_EXTRA, re
from orchestrator.util.task_client import Tasks
class Resource(object):
......@@ -23,7 +27,7 @@ class Resource(object):
@classmethod
def __attributes_from_dict(cls, attributes):
cls.__validate_attributes(attributes, cls.__schema(extend=False))
attributes = copy.deepcopy(attributes)
attributes = attributes.copy()
attributes['id'] = attributes.get('id', Resource.__generate_random_id())
attributes['type'] = ResourceType.validate(attributes.get('type', cls))
return attributes
......@@ -37,17 +41,28 @@ class Resource(object):
@classmethod
def __schema(cls, resource_type=None, extend=False):
schema = Schema(schema={'id': cls.__id_validator, 'type': ResourceType.validate}, extra=ALLOW_EXTRA)
schema = Schema(schema={'id': cls._id_validator, 'type': ResourceType.validate}, extra=ALLOW_EXTRA)
if extend:
additional = resource_type.ADDITIONAL_SCHEMA if resource_type else cls.ADDITIONAL_SCHEMA
schema = schema.extend(additional, extra=PREVENT_EXTRA)
return schema
@staticmethod
def __id_validator(resource_id):
def _id_validator(resource_id):
if not re.compile('^[a-zA-Z0-9_-]{2,42}$').match(resource_id):
raise Invalid("'%s' is invalid" % resource_id)
@staticmethod
def _mac_validator(mac):
return re.match("[0-9a-f]{2}([-:])[0-9a-f]{2}(\\1[0-9a-f]{2}){4}$", mac.lower())
@staticmethod
def _ip_validator(ip_address):
try:
return inet_aton(ip_address)
except AttributeError:
return False
@property
def type(self):
return str(self._attributes['type'])
......@@ -92,7 +107,10 @@ class Resource(object):
def flatten(self, fqn=None, flat_leaves=True):
fqn = '%s.%s' % (fqn, self.id) if fqn else self.id
if flat_leaves:
return {'%s.%s' % (fqn, key): str(value) for key, value in self.items()}
leaves = {}
for key, value in self.items():
leaves['%s.%s' % (fqn, key)] = str(value) if isinstance(value, ResourceType) else value
return leaves
return {fqn: self}
@staticmethod
......@@ -101,10 +119,13 @@ class Resource(object):
return str(data)
return dict(data)
def deploy(self, name):
pass
class ResourceGroup(Resource):
ADDITIONAL_SCHEMA = {
'resources': Any(list, set, tuple)
Optional('resources'): Any(list, set, tuple)
}
def __init__(self, *_, **__):
......@@ -162,7 +183,53 @@ class ResourceGroup(Resource):
class Instance(Resource):
ADDITIONAL_SCHEMA = {
'number_of_cores': int
Required('cpu_count'): int,
Required('memory'): int
}
def deploy(self, name):
args = {
'name': name,
'vcpu': self.cpu_count,
'memory_max': self.memory
}
result = Tasks.send_task('vmdriver.create', args=[args])
return result
class Disk(Resource):
ADDITIONAL_SCHEMA = {
Required('size'): All(int, Range(min=1)),
Optional('base'): str
}
def deploy(self, name):
args = {
'dir': cfg.CONF.storage.datastore_root,
'name': name,
'format': 'qcow2',
'type': 'normal',
'size': self.size,
'base_name': self.base or None
}
task_name = 'storagedriver.snapshot' if self.base else 'storagedriver.create'
result = Tasks.send_task(task_name, args=[args])
return result
class DiskAttachment(Resource):
ADDITIONAL_SCHEMA = {
Required('instance_id'): Resource._id_validator,
Required('stack_id'): Resource._id_validator
}
class NetworkConnection(Resource):
ADDITIONAL_SCHEMA = {
Required('instance_id'): Resource._id_validator,
Required('mac'): Resource._mac_validator,
Required('vlan'): All(int, Range(min=1, max=4094)),
Required('ip_address'): Resource._ip_validator
}
......@@ -170,6 +237,9 @@ class ResourceType(Enum):
null = Resource
group = ResourceGroup
instance = Instance
disk = Disk
attachment = DiskAttachment
connection = NetworkConnection
@classmethod
def validate(cls, value):
......
......@@ -5,6 +5,10 @@ from falcon.testing import TestCase
from orchestrator.api import stacks
TEST_INSTANCE_ARGS = {
'cpu_count': 2,
'memory': 256 * 1000 * 1000
}
class StackTest(TestCase):
def setUp(self):
......@@ -30,7 +34,9 @@ class StackTest(TestCase):
'resources': [
{
'id': 'instance-1',
'type': 'instance'
'type': 'instance',
'cpu_count': 1,
'memory': 100
},
{
'id': 'level-1',
......@@ -38,11 +44,23 @@ class StackTest(TestCase):
'resources': [
{
'id': 'instance-2',
'type': 'instance'
'type': 'instance',
'cpu_count': 2,
'memory': 200
},
{
'id': 'instance-3',
'type': 'instance'
'type': 'instance',
'cpu_count': 3,
'memory': 300
},
{
'id': 'connection-1',
'type': 'connection',
'instance_id': 'instance-1',
'vlan': 42,
'mac': 'aa:bb:cc:dd:ee:ff',
'ip_address': '10.0.0.42'
}
]
}
......@@ -96,6 +114,7 @@ class StackTest(TestCase):
resource_id = 'new_resource'
group1 = {'id': stack_id, 'type': 'group', 'resources': []}
resource = {'id': resource_id, 'type': 'instance'}
resource.update(TEST_INSTANCE_ARGS)
group2 = {'id': stack_id, 'type': 'group', 'resources': [resource]}
expected_diff = {
'added': {
......@@ -117,6 +136,7 @@ class StackTest(TestCase):
# given
resource_id = 'some_resource'
resource = {'id': resource_id, 'type': 'instance'}
resource.update(TEST_INSTANCE_ARGS)
# when
self.simulate_post('/stacks', body=json.dumps(resource))
......@@ -132,7 +152,9 @@ class StackTest(TestCase):
def test_stacks_api_get_list(self):
# given
resource1 = {'id': 'some_resource', 'type': 'instance'}
resource1.update(TEST_INSTANCE_ARGS)
resource2 = {'id': 'some_other_resource', 'type': 'instance'}
resource2.update(TEST_INSTANCE_ARGS)
# when
self.simulate_post('/stacks', body=json.dumps(resource1))
......@@ -148,6 +170,7 @@ class StackTest(TestCase):
# given
resource_id = 'some_resource'
resource = {'id': resource_id, 'type': 'instance'}
resource.update(TEST_INSTANCE_ARGS)
# when
self.simulate_post('/stacks', body=json.dumps(resource))
......
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 sign in to comment