Merge "Modernizing the compute servers model"

This commit is contained in:
Jenkins 2013-08-29 15:19:31 +00:00 committed by Gerrit Code Review
commit b0996cffaa
4 changed files with 129 additions and 111 deletions

View File

@ -42,6 +42,55 @@ class NovaServerStatusTypes(object):
PAUSED = "PAUSED"
class ComputeTaskStates(object):
NONE = 'none'
# Basic server lifecycle
SCHEDULING = 'scheduling'
SPAWNING = 'spawning'
BLOCK_DEVICE_MAPPING = 'block_device_mapping'
DELETING = 'deleting'
SOFT_DELETING = 'soft-deleting'
RESTORING = 'restoring'
SHELVING = 'shelving'
SHELVING_IMAGE_PENDING_UPLOAD = 'shelving_image_pending_upload'
SHELVING_IMAGE_UPLOADING = 'shelving_image_uploading'
SHELVING_OFFLOADING = 'shelving_offloading'
UNSHELVING = 'unshelving'
# Server Actions
REBUILDING = 'rebuilding'
REBUILD_BLOCK_DEVICE_MAPPING = 'rebuild_block_device_mapping'
REBUILD_SPAWNING = 'rebuild_spawning'
RESIZE_PREP = 'resize_prep'
RESIZE_MIGRATING = 'resize_migrating'
RESIZE_MIGRATED = 'resize_migrated'
RESIZE_FINISH = 'resize_finish'
RESIZE_REVERTING = 'resize_reverting'
RESIZE_CONFIRMING = 'resize_confirming'
RESCUING = 'rescuing'
UNRESCUING = 'unrescuing'
UPDATING_PASSWORD = 'updating_password'
PAUSING = 'pausing'
UNPAUSING = 'unpausing'
SUSPENDING = 'suspending'
RESUMING = 'resuming'
STOPPING = 'stopping'
STARTING = 'starting'
POWERING_OFF = 'powering-off'
POWERING_ON = 'powering-on'
MIGRATING = 'migrating'
REBOOTING = 'rebooting'
REBOOTING_HARD = 'rebooting_hard'
# Imaging
IMAGE_SNAPSHOT = 'image_snapshot'
IMAGE_PENDING_UPLOAD = 'image_pending_upload'
IMAGE_UPLOADING = 'image_uploading'
IMAGE_BACKUP = 'image_backup'
IMAGE_LIVE_SNAPSHOT = 'image_live_snapshot'
class NovaImageStatusTypes(object):
"""
@summary: Types dictating an individual Server Status

View File

@ -20,7 +20,8 @@ from cloudcafe.compute.common.models.metadata import Metadata
from cloudcafe.compute.common.models.metadata import MetadataItem
from cloudcafe.compute.extensions.security_groups_api.models.security_group \
import SecurityGroups, SecurityGroup
from cloudcafe.compute.servers_api.models.servers import Server
from cloudcafe.compute.servers_api.models.servers import Server, Servers, \
ServerMins
from cloudcafe.compute.servers_api.models.servers import Addresses
from cloudcafe.compute.servers_api.models.servers import InstanceActions
from cloudcafe.compute.servers_api.models.requests import CreateServer, \
@ -89,7 +90,7 @@ class ServersClient(AutoMarshallingRestClient):
'limit': limit, 'changes-since': changes_since}
url = '{base_url}/servers'.format(base_url=self.url)
resp = self.request('GET', url, params=params,
response_entity_type=Server,
response_entity_type=ServerMins,
requestslib_kwargs=requestslib_kwargs)
return resp
@ -123,7 +124,7 @@ class ServersClient(AutoMarshallingRestClient):
'changes-since': changes_since}
url = '{base_url}/servers/detail'.format(base_url=self.url)
resp = self.request('GET', url, params=params,
response_entity_type=Server,
response_entity_type=Servers,
requestslib_kwargs=requestslib_kwargs)
return resp

View File

@ -16,36 +16,38 @@ limitations under the License.
import IPy
import json
import re
import xml.etree.ElementTree as ET
from cafe.engine.models.base import AutoMarshallingModel, \
AutoMarshallingListModel
from cafe.engine.models.base import BaseModel
from cafe.engine.models.base import AutoMarshallingModel
from cloudcafe.compute.common.constants import Constants
from cloudcafe.compute.common.types import ComputeTaskStates
from cloudcafe.compute.common.equality_tools import EqualityTools
from cloudcafe.compute.common.models.link import Links
from cloudcafe.compute.common.models.metadata import Metadata
from cloudcafe.compute.flavors_api.models.flavor import Flavor, FlavorMin
from cloudcafe.compute.images_api.models.image import Image, ImageMin
from cloudcafe.compute.common.equality_tools import EqualityTools
from cloudcafe.compute.common.constants import Constants
from cloudcafe.compute.common.models.metadata import Metadata
class Server(AutoMarshallingModel):
def __init__(self, id=None, disk_config=None, config_drive=None,
power_state=None, progress=None, task_state=None,
vm_state=None, name=None, tenant_id=None, status=None,
updated=None, created=None, host_id=None, user_id=None,
accessIPv4=None, accessIPv6=None, addresses=None,
flavor=None, image=None, links=None, metadata=None,
admin_pass=None, key_name=None):
self.diskConfig = disk_config
def __init__(self, id=None, disk_config=None, power_state=None,
progress=None, task_state=None, vm_state=None, name=None,
tenant_id=None, status=None, updated=None, created=None,
host_id=None, user_id=None, accessIPv4=None, accessIPv6=None,
addresses=None, flavor=None, image=None, links=None,
metadata=None, admin_pass=None, key_name=None,
config_drive=None):
super(Server, self).__init__()
self.disk_config = disk_config
self.config_drive = config_drive
try:
self.power_state = int(power_state)
except TypeError:
self.power_state = 0
self.progress = progress
self.task_state = task_state
self.task_state = task_state or ComputeTaskStates.NONE
self.vm_state = vm_state
self.name = name
self.id = id
@ -59,12 +61,10 @@ class Server(AutoMarshallingModel):
self.accessIPv4 = str(IPy.IP(accessIPv4))
else:
self.accessIPv4 = None
if accessIPv6:
self.accessIPv6 = str(IPy.IP(accessIPv6))
else:
self.accessIPv6 = None
self.addresses = addresses
self.flavor = flavor
self.image = image
@ -75,27 +75,12 @@ class Server(AutoMarshallingModel):
@classmethod
def _json_to_obj(cls, serialized_str):
'''
Returns an instance of a Server based on the json serialized_str
passed in
'''
ret = None
json_dict = json.loads(serialized_str)
if 'server' in json_dict.keys():
ret = cls._dict_to_obj(json_dict['server'])
if 'servers' in json_dict.keys():
ret = []
for server in json_dict['servers']:
s = cls._dict_to_obj(server)
ret.append(s)
ret = cls._dict_to_obj(json_dict['server'])
return ret
@classmethod
def _xml_to_obj(cls, serialized_str):
'''
Returns an instance of a Server based on the xml serialized_str
passed in
'''
element = ET.fromstring(serialized_str)
cls._remove_xml_etree_namespace(
element, Constants.XML_API_NAMESPACE)
@ -105,18 +90,11 @@ class Server(AutoMarshallingModel):
element, Constants.XML_API_DISK_CONFIG_NAMESPACE)
cls._remove_xml_etree_namespace(
element, Constants.XML_API_ATOM_NAMESPACE)
if element.tag == 'server':
ret = cls._xml_ele_to_obj(element)
if element.tag == 'servers':
ret = []
for server in element.findall('server'):
s = cls._xml_ele_to_obj(server)
ret.append(s)
ret = cls._xml_ele_to_obj(element)
return ret
@classmethod
def _xml_ele_to_obj(cls, element):
'''Helper method to turn ElementTree instance to Server instance.'''
server = element.attrib
addresses = None
@ -135,19 +113,19 @@ class Server(AutoMarshallingModel):
metadata = Metadata._xml_ele_to_obj(element.find('metadata'))
if 'progress' in server:
progress = server.get('progress') \
and int(server.get('progress'))
progress = (server.get('progress')
and int(server.get('progress')))
else:
progress = None
server = Server(
id=server.get('id'), disk_config=server.get('diskConfig'),
power_state=server.get('power_state'), progress=progress,
task_state=server.get('task_state'),
task_state=server.get('task_state').lower(),
vm_state=server.get('vm_state'), name=server.get('name'),
tenant_id=server.get('tenant_id'), status=server.get('status'),
tenant_id=server.get('tenantId'), status=server.get('status'),
updated=server.get('updated'), created=server.get('created'),
host_id=server.get('hostId'), user_id=server.get('user_id'),
host_id=server.get('hostId'), user_id=server.get('userId'),
accessIPv4=server.get('accessIPv4'),
config_drive=server.get('config_drive'),
accessIPv6=server.get('accessIPv6'), addresses=addresses,
@ -159,7 +137,6 @@ class Server(AutoMarshallingModel):
@classmethod
def _dict_to_obj(cls, server_dict):
'''Helper method to turn dictionary into Server instance.'''
addresses = None
flavor = None
@ -202,92 +179,82 @@ class Server(AutoMarshallingModel):
return server
def __eq__(self, other):
"""
@summary: Overrides the default equals
@param other: Server object to compare with
@type other: Server
@return: True if Server objects are equal, False otherwise
@rtype: bool
"""
return EqualityTools.are_objects_equal(self, other,
['admin_pass', 'updated',
'progress'])
def __ne__(self, other):
"""
@summary: Overrides the default not-equals
@param other: Server object to compare with
@type other: Server
@return: True if Server objects are not equal, False otherwise
@rtype: bool
"""
return not self == other
def min_details(self):
"""
@summary: Get the Minimum details of server
@return: Minimum details of server
@rtype: ServerMin
"""
return ServerMin(name=self.name, id=self.id, links=self.links)
class ServerMin(Server):
"""
@summary: Represents minimum details of a server
"""
def __init__(self, **kwargs):
for keys, values in kwargs.items():
setattr(self, keys, values)
def __init__(self, id=None, name=None, links=None):
super(ServerMin, self).__init__()
self.id = id
self.name = name
self.links = links
def __eq__(self, other):
"""
@summary: Overrides the default equals
@param other: ServerMin object to compare with
@type other: ServerMin
@return: True if ServerMin objects are equal, False otherwise
@rtype: bool
"""
return EqualityTools.are_objects_equal(self, other)
def __ne__(self, other):
"""
@summary: Overrides the default equals
@param other: ServerMin object to compare with
@type other: ServerMin
@return: True if ServerMin objects are not equal, False otherwise
@rtype: bool
"""
return not self == other
@classmethod
def _xml_ele_to_obj(cls, element):
'''Helper method to turn ElementTree instance to Server instance.'''
if element.find('server') is not None:
element = element.find('server')
server_dict = element.attrib
servermin = ServerMin(**server_dict)
servermin.links = Links._xml_ele_to_obj(element)
return servermin
server_dict = element.attrib
links = Links._xml_ele_to_obj(element)
server = ServerMin(id=server_dict.get('id'),
name=server_dict.get('name'), links=links)
return server
@classmethod
def _dict_to_obj(cls, server_dict):
'''Helper method to turn dictionary into Server instance.'''
servermin = ServerMin(**server_dict)
if hasattr(servermin, 'links'):
servermin.links = Links._dict_to_obj(servermin.links)
'''
Parse for those keys which have the namespace prefixed,
strip the namespace out
and take only the actual values such as diskConfig,
power_state and assign to server obj
'''
for each in server_dict:
if each.startswith("{"):
newkey = re.split("}", each)[1]
setattr(servermin, newkey, server_dict[each])
links = Links._dict_to_obj(server_dict['links'])
server = ServerMin(id=server_dict.get('id'),
name=server_dict.get('name'), links=links)
return server
return servermin
class Servers(AutoMarshallingListModel):
server_type = Server
@classmethod
def _json_to_obj(cls, serialized_str):
json_dict = json.loads(serialized_str)
return cls._list_to_obj(json_dict.get('servers'))
@classmethod
def _list_to_obj(cls, server_dict_list):
servers = Servers()
for server_dict in server_dict_list:
server = cls.server_type._dict_to_obj(server_dict)
servers.append(server)
return servers
@classmethod
def _xml_to_obj(cls, serialized_str):
element = ET.fromstring(serialized_str)
if element.tag != 'servers':
return None
return cls._xml_list_to_obj(element.findall('server'))
@classmethod
def _xml_list_to_obj(cls, xml_list):
servers = Servers()
for ele in xml_list:
servers.append(cls.server_type._xml_ele_to_obj(ele))
return servers
class ServerMins(Servers):
server_type = ServerMin
class Addresses(AutoMarshallingModel):

View File

@ -16,6 +16,7 @@ limitations under the License.
import unittest2 as unittest
from cloudcafe.compute.common.types import ComputeTaskStates
from cloudcafe.compute.servers_api.models.servers import Server
@ -31,7 +32,7 @@ class ServerDomainTest(object):
self.assertEqual(self.server.progress, 100)
def test_server_task_state(self):
self.assertEqual(self.server.task_state, None)
self.assertEqual(self.server.task_state, ComputeTaskStates.NONE)
def test_server_vm_state(self):
self.assertEqual(self.server.vm_state, "active")