Common objects and relative test units added
- the common classes are needed for a more objected oriented style - fixed pep8 Change-Id: I1a5dbb510168002c4c537beece4961741aed1d93
This commit is contained in:
parent
88e73f1399
commit
a37e4fb0ff
0
synergy_scheduler_manager/common/__init__.py
Normal file
0
synergy_scheduler_manager/common/__init__.py
Normal file
204
synergy_scheduler_manager/common/block_device.py
Normal file
204
synergy_scheduler_manager/common/block_device.py
Normal file
@ -0,0 +1,204 @@
|
||||
__author__ = "Lisa Zangrando"
|
||||
__email__ = "lisa.zangrando[AT]pd.infn.it"
|
||||
__copyright__ = """Copyright (c) 2015 INFN - INDIGO-DataCloud
|
||||
All Rights Reserved
|
||||
|
||||
Licensed under the Apache License, Version 2.0;
|
||||
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."""
|
||||
|
||||
"""
|
||||
from nova.objects.base import NovaObject
|
||||
from nova.objects.base import NovaObjectDictCompat
|
||||
|
||||
class BlockDeviceMapping(NovaObject, NovaObjectDictCompat):
|
||||
fields = {
|
||||
}
|
||||
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(BlockDeviceMapping, self).__init__(*args, **kwargs)
|
||||
"""
|
||||
|
||||
|
||||
class BlockDeviceMapping(object):
|
||||
|
||||
def __init__(self, id):
|
||||
self.id = id
|
||||
self.created_at = None
|
||||
self.updated_at = None
|
||||
self.deleted_at = None
|
||||
self.device_name = None
|
||||
self.delete_on_termination = None
|
||||
self.snapshot_id = None
|
||||
self.volume_id = None
|
||||
self.volume_size = None
|
||||
self.no_device = None
|
||||
self.connection_info = None
|
||||
self.instance_uuid = None
|
||||
self.deleted = None
|
||||
self.source_type = None
|
||||
self.destination_type = None
|
||||
self.guest_format = None
|
||||
self.device_type = None
|
||||
self.disk_bus = None
|
||||
self.boot_index = None
|
||||
self.image_id = None
|
||||
|
||||
def getId(self):
|
||||
return self.id
|
||||
|
||||
def getImageId(self):
|
||||
return self.image_id
|
||||
|
||||
def setImageId(self, image_id):
|
||||
self.image_id = image_id
|
||||
|
||||
def getInstanceId(self):
|
||||
return self.instance_uuid
|
||||
|
||||
def setInstanceId(self, instance_uuid):
|
||||
self.instance_uuid = instance_uuid
|
||||
|
||||
def getSnapshotId(self):
|
||||
return self.snapshot_id
|
||||
|
||||
def setSnapshotId(self, snapshot_id):
|
||||
self.snapshot_id = snapshot_id
|
||||
|
||||
def getVolumeId(self):
|
||||
return self.volume_id
|
||||
|
||||
def setVolumeId(self, volume_id):
|
||||
self.volume_id = volume_id
|
||||
|
||||
def getVolumeSize(self):
|
||||
return self.volume_size
|
||||
|
||||
def setVolumeSize(self, volume_size):
|
||||
self.volume_size = volume_size
|
||||
|
||||
def getBootIndex(self):
|
||||
return self.boot_index
|
||||
|
||||
def setBootIndex(self, boot_index):
|
||||
self.boot_index = boot_index
|
||||
|
||||
def getCreatedAt(self):
|
||||
return self.created_at
|
||||
|
||||
def setCreatedAt(self, created_at):
|
||||
self.created_at = created_at
|
||||
|
||||
def getUpdatedAt(self):
|
||||
return self.updated_at
|
||||
|
||||
def setUpdatedAt(self, updated_at):
|
||||
self.updated_at = updated_at
|
||||
|
||||
def getDeletedAt(self):
|
||||
return self.deleted_at
|
||||
|
||||
def setDeletedAt(self, deleted_at):
|
||||
self.deleted_at = deleted_at
|
||||
|
||||
def getDeviceName(self):
|
||||
return self.device_name
|
||||
|
||||
def setDeviceName(self, device_name):
|
||||
self.device_name = device_name
|
||||
|
||||
def getNoDevice(self):
|
||||
return self.no_device
|
||||
|
||||
def setNoDevice(self, no_device):
|
||||
self.no_device = no_device
|
||||
|
||||
def getConnectionInfo(self):
|
||||
return self.connection_info
|
||||
|
||||
def setConnectionInfo(self, connection_info):
|
||||
self.connection_info = connection_info
|
||||
|
||||
def getDestinationType(self):
|
||||
return self.destination_type
|
||||
|
||||
def setDestinationType(self, destination_type):
|
||||
self.destination_type = destination_type
|
||||
|
||||
def getDeviceType(self):
|
||||
return self.device_type
|
||||
|
||||
def setDeviceType(self, device_type):
|
||||
self.device_type = device_type
|
||||
|
||||
def getSourceType(self):
|
||||
return self.source_type
|
||||
|
||||
def setSourceType(self, source_type):
|
||||
self.source_type = source_type
|
||||
|
||||
def getDiskBus(self):
|
||||
return self.disk_bus
|
||||
|
||||
def setDiskBus(self, disk_bus):
|
||||
self.disk_bus = disk_bus
|
||||
|
||||
def getGuestFormat(self):
|
||||
return self.guest_format
|
||||
|
||||
def setGuestFormat(self, guest_format):
|
||||
self.guest_format = guest_format
|
||||
|
||||
def isDeleteOnTermination(self):
|
||||
return self.delete_on_termination
|
||||
|
||||
def setDeleteOnTermination(self, delete_on_termination):
|
||||
self.delete_on_termination = delete_on_termination
|
||||
|
||||
def isDeleted(self):
|
||||
return self.deleted
|
||||
|
||||
def setDeleted(self, deleted):
|
||||
self.deleted = deleted
|
||||
|
||||
def serialize(self):
|
||||
data = {}
|
||||
data["id"] = self.id
|
||||
data["created_at"] = self.created_at
|
||||
data["updated_at"] = self.updated_at
|
||||
data["deleted_at"] = self.deleted_at
|
||||
data["device_name"] = self.device_name
|
||||
data["device_type"] = self.device_type
|
||||
data["delete_on_termination"] = self.delete_on_termination
|
||||
data["snapshot_id"] = self.snapshot_id
|
||||
data["volume_id"] = self.volume_id
|
||||
data["volume_size"] = self.volume_size
|
||||
data["no_device"] = self.no_device
|
||||
data["connection_info"] = self.connection_info
|
||||
data["instance_uuid"] = self.instance_uuid
|
||||
data["deleted"] = self.deleted
|
||||
data["source_type"] = self.source_type
|
||||
data["destination_type"] = self.destination_type
|
||||
data["guest_format"] = self.guest_format
|
||||
data["disk_bus"] = self.disk_bus
|
||||
data["boot_index"] = self.boot_index
|
||||
data["image_id"] = self.image_id
|
||||
|
||||
blockDeviceMap = {}
|
||||
blockDeviceMap["nova_object.version"] = "1.15"
|
||||
blockDeviceMap["nova_object.namespace"] = "nova"
|
||||
blockDeviceMap["nova_object.changes"] = ["device_name"]
|
||||
blockDeviceMap["nova_object.name"] = "BlockDeviceMapping"
|
||||
blockDeviceMap["nova_object.data"] = data
|
||||
|
||||
return blockDeviceMap
|
44
synergy_scheduler_manager/common/compute.py
Normal file
44
synergy_scheduler_manager/common/compute.py
Normal file
@ -0,0 +1,44 @@
|
||||
from synergy.common.serializer import SynergyObject
|
||||
|
||||
|
||||
__author__ = "Lisa Zangrando"
|
||||
__email__ = "lisa.zangrando[AT]pd.infn.it"
|
||||
__copyright__ = """Copyright (c) 2015 INFN - INDIGO-DataCloud
|
||||
All Rights Reserved
|
||||
|
||||
Licensed under the Apache License, Version 2.0;
|
||||
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 Compute(SynergyObject):
|
||||
|
||||
def __init__(self):
|
||||
super(Compute, self).__init__()
|
||||
|
||||
def getHost(self):
|
||||
return self.get("host")
|
||||
|
||||
def setHost(self, host):
|
||||
self.set("host", host)
|
||||
|
||||
def getNodeName(self):
|
||||
return self.get("nodename")
|
||||
|
||||
def setNodeName(self, nodename):
|
||||
self.set("nodename", nodename)
|
||||
|
||||
def getLimits(self):
|
||||
return self.get("limits")
|
||||
|
||||
def setLimits(self, limits):
|
||||
self.set("limits", limits)
|
64
synergy_scheduler_manager/common/endpoint.py
Normal file
64
synergy_scheduler_manager/common/endpoint.py
Normal file
@ -0,0 +1,64 @@
|
||||
from synergy.common.serializer import SynergyObject
|
||||
|
||||
|
||||
__author__ = "Lisa Zangrando"
|
||||
__email__ = "lisa.zangrando[AT]pd.infn.it"
|
||||
__copyright__ = """Copyright (c) 2015 INFN - INDIGO-DataCloud
|
||||
All Rights Reserved
|
||||
|
||||
Licensed under the Apache License, Version 2.0;
|
||||
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 Endpoint(SynergyObject):
|
||||
|
||||
def __init__(self):
|
||||
super(Endpoint, self).__init__()
|
||||
|
||||
self.set("enabled", False)
|
||||
|
||||
def getInterface(self):
|
||||
return self.get("interface")
|
||||
|
||||
def setInterface(self, interface):
|
||||
self.set("interface", interface)
|
||||
|
||||
def getRegion(self):
|
||||
return self.get("region")
|
||||
|
||||
def setRegion(self, region):
|
||||
self.set("region", region)
|
||||
|
||||
def getRegionId(self):
|
||||
return self.get("region_id")
|
||||
|
||||
def setRegionId(self, region_id):
|
||||
self.set("region_id", region_id)
|
||||
|
||||
def getServiceId(self):
|
||||
return self.get("service_id")
|
||||
|
||||
def setServiceId(self, service_id):
|
||||
self.set("service_id", service_id)
|
||||
|
||||
def getURL(self):
|
||||
return self.get("url")
|
||||
|
||||
def setURL(self, url):
|
||||
self.set("url", url)
|
||||
|
||||
def isEnabled(self):
|
||||
return self.get("enabled")
|
||||
|
||||
def setEnabled(self, enabled=True):
|
||||
self.set("enabled", enabled)
|
48
synergy_scheduler_manager/common/flavor.py
Normal file
48
synergy_scheduler_manager/common/flavor.py
Normal file
@ -0,0 +1,48 @@
|
||||
from synergy.common.serializer import SynergyObject
|
||||
|
||||
|
||||
__author__ = "Lisa Zangrando"
|
||||
__email__ = "lisa.zangrando[AT]pd.infn.it"
|
||||
__copyright__ = """Copyright (c) 2015 INFN - INDIGO-DataCloud
|
||||
All Rights Reserved
|
||||
|
||||
Licensed under the Apache License, Version 2.0;
|
||||
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 Flavor(SynergyObject):
|
||||
|
||||
def __init__(self):
|
||||
super(Flavor, self).__init__()
|
||||
|
||||
self.set("vcpus", 0)
|
||||
self.set("memory", 0)
|
||||
self.set("storage", 0)
|
||||
|
||||
def getVCPUs(self):
|
||||
return self.get("vcpus")
|
||||
|
||||
def setVCPUs(self, vcpus):
|
||||
self.set("vcpus", vcpus)
|
||||
|
||||
def getMemory(self):
|
||||
return self.get("memory")
|
||||
|
||||
def setMemory(self, memory):
|
||||
self.set("memory", memory)
|
||||
|
||||
def getStorage(self):
|
||||
return self.get("storage")
|
||||
|
||||
def setStorage(self, storage):
|
||||
self.set("storage", storage)
|
95
synergy_scheduler_manager/common/hypervisor.py
Normal file
95
synergy_scheduler_manager/common/hypervisor.py
Normal file
@ -0,0 +1,95 @@
|
||||
from service import Service
|
||||
|
||||
|
||||
__author__ = "Lisa Zangrando"
|
||||
__email__ = "lisa.zangrando[AT]pd.infn.it"
|
||||
__copyright__ = """Copyright (c) 2015 INFN - INDIGO-DataCloud
|
||||
All Rights Reserved
|
||||
|
||||
Licensed under the Apache License, Version 2.0;
|
||||
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 Hypervisor(Service):
|
||||
|
||||
def __init__(self):
|
||||
super(Hypervisor, self).__init__()
|
||||
|
||||
self.set("vcpus", 0)
|
||||
self.set("vcpus_used", 0)
|
||||
self.set("memory", 0)
|
||||
self.set("memory_used", 0)
|
||||
self.set("storage", 0)
|
||||
self.set("storage_used", 0)
|
||||
self.set("vms", 0)
|
||||
self.set("workload", 0)
|
||||
|
||||
def getIP(self):
|
||||
return self.get("ip")
|
||||
|
||||
def setIP(self, ip):
|
||||
self.set("ip", ip)
|
||||
|
||||
def getState(self):
|
||||
return self.get("state")
|
||||
|
||||
def setState(self, state):
|
||||
self.set("state", state)
|
||||
|
||||
def getWorkload(self):
|
||||
return self.get("workload")
|
||||
|
||||
def setWorkload(self, workload):
|
||||
self.set("workload", workload)
|
||||
|
||||
def getVMs(self):
|
||||
return self.get("vms")
|
||||
|
||||
def setVMs(self, vms):
|
||||
self.set("vms", vms)
|
||||
|
||||
def getVCPUs(self, used=False):
|
||||
if used:
|
||||
return self.get("vcpus_used")
|
||||
else:
|
||||
return self.get("vcpus")
|
||||
|
||||
def setVCPUs(self, vcpus, used=False):
|
||||
if used:
|
||||
self.set("vcpus_used", vcpus)
|
||||
else:
|
||||
self.set("vcpus", vcpus)
|
||||
|
||||
def getMemory(self, used=False):
|
||||
if used:
|
||||
return self.get("memory_used")
|
||||
else:
|
||||
return self.get("memory")
|
||||
|
||||
def setMemory(self, memory, used=False):
|
||||
if used:
|
||||
self.set("memory_used", memory)
|
||||
else:
|
||||
self.set("memory", memory)
|
||||
|
||||
def getStorage(self, used=False):
|
||||
if used:
|
||||
return self.get("storage_used")
|
||||
else:
|
||||
return self.get("storage")
|
||||
|
||||
def setStorage(self, storage, used=False):
|
||||
if used:
|
||||
self.set("storage_used", storage)
|
||||
else:
|
||||
self.set("storage", storage)
|
65
synergy_scheduler_manager/common/priority.py
Normal file
65
synergy_scheduler_manager/common/priority.py
Normal file
@ -0,0 +1,65 @@
|
||||
import threading
|
||||
|
||||
from datetime import datetime
|
||||
from synergy.common.serializer import SynergyObject
|
||||
|
||||
|
||||
__author__ = "Lisa Zangrando"
|
||||
__email__ = "lisa.zangrando[AT]pd.infn.it"
|
||||
__copyright__ = """Copyright (c) 2015 INFN - INDIGO-DataCloud
|
||||
All Rights Reserved
|
||||
|
||||
Licensed under the Apache License, Version 2.0;
|
||||
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 Priority(SynergyObject):
|
||||
|
||||
def __init__(self):
|
||||
super(Priority, self).__init__()
|
||||
|
||||
self.condition = threading.Condition()
|
||||
|
||||
self.set("value", 0)
|
||||
self.set("last_update", datetime.utcnow())
|
||||
self.set("fairshare", {"vcpus": float(0),
|
||||
"memory": float(0),
|
||||
"disk": float(0)})
|
||||
|
||||
def getValue(self):
|
||||
return self.get("value")
|
||||
|
||||
def setValue(self, value):
|
||||
self.set("value", value)
|
||||
self.set("last_update", datetime.utcnow())
|
||||
|
||||
def getLastUpdate(self):
|
||||
return self.get("last_update")
|
||||
|
||||
def getFairShare(self, resource):
|
||||
fairshare = self.get("fairshare")
|
||||
|
||||
if resource not in fairshare:
|
||||
raise Exception("wrong resource %r" % resource)
|
||||
|
||||
return fairshare[resource]
|
||||
|
||||
def setFairShare(self, resource, value=0):
|
||||
fairshare = self.get("fairshare")
|
||||
|
||||
if resource not in fairshare:
|
||||
raise Exception("wrong resource %r" % resource)
|
||||
|
||||
with self.condition:
|
||||
fairshare[resource] = value
|
||||
self.condition.notifyAll()
|
92
synergy_scheduler_manager/common/project.py
Normal file
92
synergy_scheduler_manager/common/project.py
Normal file
@ -0,0 +1,92 @@
|
||||
from quota import Quota
|
||||
from share import Share
|
||||
from synergy.common.serializer import SynergyObject
|
||||
|
||||
|
||||
__author__ = "Lisa Zangrando"
|
||||
__email__ = "lisa.zangrando[AT]pd.infn.it"
|
||||
__copyright__ = """Copyright (c) 2015 INFN - INDIGO-DataCloud
|
||||
All Rights Reserved
|
||||
|
||||
Licensed under the Apache License, Version 2.0;
|
||||
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 Project(SynergyObject):
|
||||
|
||||
def __init__(self):
|
||||
super(Project, self).__init__()
|
||||
|
||||
self.set("data", {})
|
||||
self.set("users", {})
|
||||
self.set("share", Share())
|
||||
self.set("quota", Quota())
|
||||
self.set("TTL", float(0))
|
||||
self.set("enabled", False)
|
||||
|
||||
def getData(self):
|
||||
return self.get("data")
|
||||
|
||||
def getQuota(self):
|
||||
return self.get("quota")
|
||||
|
||||
def getShare(self):
|
||||
return self.get("share")
|
||||
|
||||
def getTTL(self):
|
||||
return self.get("TTL")
|
||||
|
||||
def setTTL(self, TTL):
|
||||
self.set("TTL", TTL)
|
||||
|
||||
def addUser(self, user):
|
||||
if self.get("users").get(user.getId(), None):
|
||||
raise Exception("user %r already exists!" % (user.getId()))
|
||||
|
||||
self.get("users")[user.getId()] = user
|
||||
|
||||
def getUser(self, id=None, name=None):
|
||||
if id:
|
||||
return self.get("users").get(id, None)
|
||||
elif name:
|
||||
for user in self.get("users").values():
|
||||
if name == user.getName():
|
||||
return user
|
||||
return None
|
||||
|
||||
def getUsers(self):
|
||||
return self.get("users").values()
|
||||
|
||||
def isEnabled(self):
|
||||
return self.get("enabled")
|
||||
|
||||
def setEnabled(self, enabled=True):
|
||||
self.set("enabled", enabled)
|
||||
|
||||
|
||||
def main():
|
||||
project = Project()
|
||||
project.setId("22222222")
|
||||
project.setName("LISA")
|
||||
|
||||
print(project.getName())
|
||||
ser = project.serialize()
|
||||
print(ser)
|
||||
|
||||
project1 = SynergyObject.deserialize(ser)
|
||||
print(project1.serialize())
|
||||
print(project1.getName())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
397
synergy_scheduler_manager/common/queue.py
Normal file
397
synergy_scheduler_manager/common/queue.py
Normal file
@ -0,0 +1,397 @@
|
||||
import heapq
|
||||
import json
|
||||
import threading
|
||||
|
||||
from datetime import datetime
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
|
||||
__author__ = "Lisa Zangrando"
|
||||
__email__ = "lisa.zangrando[AT]pd.infn.it"
|
||||
__copyright__ = """Copyright (c) 2015 INFN - INDIGO-DataCloud
|
||||
All Rights Reserved
|
||||
|
||||
Licensed under the Apache License, Version 2.0;
|
||||
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 QueueItem(object):
|
||||
|
||||
def __init__(self, id, user_id, prj_id, priority,
|
||||
retry_count, creation_time, last_update, data=None):
|
||||
self.id = id
|
||||
self.user_id = user_id
|
||||
self.prj_id = prj_id
|
||||
self.priority = priority
|
||||
self.retry_count = retry_count
|
||||
self.creation_time = creation_time
|
||||
self.last_update = last_update
|
||||
self.data = data
|
||||
|
||||
def getId(self):
|
||||
return self.id
|
||||
|
||||
def setId(self, id):
|
||||
self.id = id
|
||||
|
||||
def getUserId(self):
|
||||
return self.user_id
|
||||
|
||||
def setUserId(self, user_id):
|
||||
self.user_id = user_id
|
||||
|
||||
def getProjectId(self):
|
||||
return self.prj_id
|
||||
|
||||
def setProjectId(self, prj_id):
|
||||
self.prj_id = prj_id
|
||||
|
||||
def getPriority(self):
|
||||
return self.priority
|
||||
|
||||
def setPriority(self, priority):
|
||||
self.priority = priority
|
||||
|
||||
def getRetryCount(self):
|
||||
return self.retry_count
|
||||
|
||||
def setRetryCount(self, retry_count):
|
||||
self.retry_count = retry_count
|
||||
|
||||
def incRetryCount(self):
|
||||
self.retry_count += 1
|
||||
|
||||
def getCreationTime(self):
|
||||
return self.creation_time
|
||||
|
||||
def setCreationTime(self, creation_time):
|
||||
self.creation_time = creation_time
|
||||
|
||||
def getLastUpdate(self):
|
||||
return self.last_update
|
||||
|
||||
def setLastUpdate(self, last_update):
|
||||
self.last_update = last_update
|
||||
|
||||
def getData(self):
|
||||
return self.data
|
||||
|
||||
def setData(self, data):
|
||||
self.data = data
|
||||
|
||||
|
||||
class PriorityQueue(object):
|
||||
|
||||
def __init__(self):
|
||||
self._heap = []
|
||||
self._count = 0
|
||||
|
||||
def __len__(self):
|
||||
return len(self._heap)
|
||||
|
||||
def __iter__(self):
|
||||
"""Get all elements ordered by asc. priority. """
|
||||
return self
|
||||
|
||||
def put(self, priority, item):
|
||||
heapq.heappush(self._heap, (-priority, self._count, item))
|
||||
self._count += 1
|
||||
|
||||
def get(self):
|
||||
return heapq.heappop(self._heap)[2]
|
||||
|
||||
def size(self):
|
||||
return len(self._heap)
|
||||
|
||||
def items(self):
|
||||
return [heapq.heappop(self._heap) for i in range(len(self._heap))]
|
||||
|
||||
def smallest(self, x):
|
||||
return heapq.nsmallest(x, self._heap)
|
||||
|
||||
def largest(self, x):
|
||||
return heapq.nlargest(x, self._heap)
|
||||
|
||||
|
||||
class QueueDB(object):
|
||||
|
||||
def __init__(self, name, db_engine, fairshare_manager=None):
|
||||
self.name = name
|
||||
self.db_engine = db_engine
|
||||
self.fairshare_manager = fairshare_manager
|
||||
self.is_closed = False
|
||||
self.priority_updater = None
|
||||
self.condition = threading.Condition()
|
||||
self.pqueue = PriorityQueue()
|
||||
self.createTable()
|
||||
self.buildFromDB()
|
||||
|
||||
def getName(self):
|
||||
return self.name
|
||||
|
||||
def getSize(self):
|
||||
connection = self.db_engine.connect()
|
||||
|
||||
try:
|
||||
QUERY = "select count(*) from `%s`" % self.name
|
||||
result = connection.execute(QUERY)
|
||||
|
||||
row = result.fetchone()
|
||||
|
||||
return row[0]
|
||||
except SQLAlchemyError as ex:
|
||||
raise Exception(ex.message)
|
||||
finally:
|
||||
connection.close()
|
||||
|
||||
def createTable(self):
|
||||
TABLE = """CREATE TABLE IF NOT EXISTS `%s` (`id` BIGINT NOT NULL \
|
||||
AUTO_INCREMENT PRIMARY KEY, `priority` INT DEFAULT 0, user_id CHAR(40) \
|
||||
NOT NULL, prj_id CHAR(40) NOT NULL, `retry_count` INT DEFAULT 0, \
|
||||
`creation_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `last_update` \
|
||||
TIMESTAMP NULL, `data` TEXT NOT NULL ) ENGINE=InnoDB""" % self.name
|
||||
|
||||
connection = self.db_engine.connect()
|
||||
|
||||
try:
|
||||
connection.execute(TABLE)
|
||||
except SQLAlchemyError as ex:
|
||||
raise Exception(ex.message)
|
||||
except Exception as ex:
|
||||
raise Exception(ex.message)
|
||||
finally:
|
||||
connection.close()
|
||||
|
||||
def close(self):
|
||||
if not self.is_closed:
|
||||
self.is_closed = True
|
||||
|
||||
with self.condition:
|
||||
self.condition.notifyAll()
|
||||
|
||||
def isClosed(self):
|
||||
return self.is_closed
|
||||
|
||||
def buildFromDB(self):
|
||||
connection = self.db_engine.connect()
|
||||
|
||||
try:
|
||||
QUERY = "select id, user_id, prj_id, priority, retry_count, " \
|
||||
"creation_time, last_update from `%s`" % self.name
|
||||
result = connection.execute(QUERY)
|
||||
|
||||
for row in result:
|
||||
queue_item = QueueItem(row[0], row[1], row[2],
|
||||
row[3], row[4], row[5], row[6])
|
||||
|
||||
self.pqueue.put(row[3], queue_item)
|
||||
except SQLAlchemyError as ex:
|
||||
raise Exception(ex.message)
|
||||
finally:
|
||||
connection.close()
|
||||
|
||||
with self.condition:
|
||||
self.condition.notifyAll()
|
||||
|
||||
def insertItem(self, user_id, prj_id, priority, data):
|
||||
with self.condition:
|
||||
idRecord = -1
|
||||
QUERY = "insert into `%s` (user_id, prj_id, priority, " \
|
||||
"data) values" % self.name
|
||||
QUERY += "(%s, %s, %s, %s)"
|
||||
|
||||
connection = self.db_engine.connect()
|
||||
trans = connection.begin()
|
||||
|
||||
try:
|
||||
result = connection.execute(QUERY,
|
||||
[user_id, prj_id, priority,
|
||||
json.dumps(data)])
|
||||
|
||||
idRecord = result.lastrowid
|
||||
|
||||
trans.commit()
|
||||
except SQLAlchemyError as ex:
|
||||
trans.rollback()
|
||||
raise Exception(ex.message)
|
||||
finally:
|
||||
connection.close()
|
||||
|
||||
now = datetime.now()
|
||||
queue_item = QueueItem(idRecord, user_id, prj_id,
|
||||
priority, 0, now, now)
|
||||
|
||||
self.pqueue.put(priority, queue_item)
|
||||
|
||||
self.condition.notifyAll()
|
||||
|
||||
def reinsertItem(self, queue_item):
|
||||
with self.condition:
|
||||
self.pqueue.put(queue_item.getPriority(), queue_item)
|
||||
self.condition.notifyAll()
|
||||
|
||||
def getItem(self, blocking=True):
|
||||
item = None
|
||||
queue_item = None
|
||||
|
||||
with self.condition:
|
||||
while (queue_item is None and not self.is_closed):
|
||||
if len(self.pqueue):
|
||||
queue_item = self.pqueue.get()
|
||||
elif blocking:
|
||||
self.condition.wait()
|
||||
elif queue_item is None:
|
||||
break
|
||||
|
||||
if (not self.is_closed and queue_item is not None):
|
||||
connection = self.db_engine.connect()
|
||||
|
||||
try:
|
||||
QUERY = """select user_id, prj_id, priority, \
|
||||
retry_count, creation_time, last_update, data from `%s`""" % self.name
|
||||
QUERY += " where id=%s"
|
||||
|
||||
result = connection.execute(QUERY, [queue_item.getId()])
|
||||
|
||||
row = result.fetchone()
|
||||
|
||||
item = QueueItem(queue_item.getId(), row[0], row[1],
|
||||
row[2], row[3], row[4], row[5],
|
||||
json.loads(row[6]))
|
||||
except SQLAlchemyError as ex:
|
||||
raise Exception(ex.message)
|
||||
finally:
|
||||
connection.close()
|
||||
|
||||
self.condition.notifyAll()
|
||||
|
||||
return item
|
||||
|
||||
def deleteItem(self, queue_item):
|
||||
if not queue_item:
|
||||
return
|
||||
|
||||
with self.condition:
|
||||
connection = self.db_engine.connect()
|
||||
trans = connection.begin()
|
||||
|
||||
try:
|
||||
QUERY = "delete from `%s`" % self.name
|
||||
QUERY += " where id=%s"
|
||||
|
||||
connection.execute(QUERY, [queue_item.getId()])
|
||||
|
||||
trans.commit()
|
||||
except SQLAlchemyError as ex:
|
||||
trans.rollback()
|
||||
|
||||
raise Exception(ex.message)
|
||||
finally:
|
||||
connection.close()
|
||||
self.condition.notifyAll()
|
||||
|
||||
def updateItem(self, queue_item):
|
||||
if not queue_item:
|
||||
return
|
||||
|
||||
with self.condition:
|
||||
connection = self.db_engine.connect()
|
||||
trans = connection.begin()
|
||||
|
||||
try:
|
||||
queue_item.setLastUpdate(datetime.now())
|
||||
|
||||
QUERY = "update `%s`" % self.name
|
||||
QUERY += " set priority=%s, retry_count=%s, " \
|
||||
"last_update=%s where id=%s"
|
||||
|
||||
connection.execute(QUERY, [queue_item.getPriority(),
|
||||
queue_item.getRetryCount(),
|
||||
queue_item.getLastUpdate(),
|
||||
queue_item.getId()])
|
||||
|
||||
trans.commit()
|
||||
except SQLAlchemyError as ex:
|
||||
trans.rollback()
|
||||
|
||||
raise Exception(ex.message)
|
||||
finally:
|
||||
connection.close()
|
||||
|
||||
self.pqueue.put(queue_item.getPriority(), queue_item)
|
||||
self.condition.notifyAll()
|
||||
|
||||
def updatePriority(self):
|
||||
if self.fairshare_manager is None:
|
||||
return
|
||||
|
||||
with self.condition:
|
||||
queue_items = []
|
||||
|
||||
connection = self.db_engine.connect()
|
||||
|
||||
while len(self.pqueue) > 0:
|
||||
queue_item = self.pqueue.get()
|
||||
priority = queue_item.getPriority()
|
||||
|
||||
try:
|
||||
priority = self.fairshare_manager.execute(
|
||||
"CALCULATE_PRIORITY",
|
||||
user_id=queue_item.getUserId(),
|
||||
prj_id=queue_item.getProjectId(),
|
||||
timestamp=queue_item.getCreationTime(),
|
||||
retry=queue_item.getRetryCount())
|
||||
|
||||
queue_item.setPriority(priority)
|
||||
except Exception as ex:
|
||||
continue
|
||||
finally:
|
||||
queue_items.append(queue_item)
|
||||
|
||||
trans = connection.begin()
|
||||
|
||||
try:
|
||||
queue_item.setLastUpdate(datetime.now())
|
||||
|
||||
QUERY = "update `%s`" % self.name
|
||||
QUERY += " set priority=%s, last_update=%s where id=%s"
|
||||
|
||||
connection.execute(QUERY, [queue_item.getPriority(),
|
||||
queue_item.getLastUpdate(),
|
||||
queue_item.getId()])
|
||||
|
||||
trans.commit()
|
||||
except SQLAlchemyError as ex:
|
||||
trans.rollback()
|
||||
raise Exception(ex.message)
|
||||
|
||||
connection.close()
|
||||
|
||||
if len(queue_items) > 0:
|
||||
for queue_item in queue_items:
|
||||
self.pqueue.put(queue_item.getPriority(), queue_item)
|
||||
|
||||
del queue_items
|
||||
|
||||
self.condition.notifyAll()
|
||||
|
||||
def toDict(self):
|
||||
queue = {}
|
||||
queue["name"] = self.name
|
||||
queue["size"] = self.getSize()
|
||||
|
||||
if self.is_closed:
|
||||
queue["status"] = "OFF"
|
||||
else:
|
||||
queue["status"] = "ON"
|
||||
|
||||
return queue
|
548
synergy_scheduler_manager/common/quota.py
Normal file
548
synergy_scheduler_manager/common/quota.py
Normal file
@ -0,0 +1,548 @@
|
||||
import logging
|
||||
import threading
|
||||
|
||||
from datetime import datetime
|
||||
from synergy.common.serializer import SynergyObject
|
||||
|
||||
|
||||
__author__ = "Lisa Zangrando"
|
||||
__email__ = "lisa.zangrando[AT]pd.infn.it"
|
||||
__copyright__ = """Copyright (c) 2015 INFN - INDIGO-DataCloud
|
||||
All Rights Reserved
|
||||
|
||||
Licensed under the Apache License, Version 2.0;
|
||||
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."""
|
||||
|
||||
|
||||
LOG = logging.getLogger("quota")
|
||||
|
||||
|
||||
class Quota(SynergyObject):
|
||||
|
||||
def __init__(self):
|
||||
super(Quota, self).__init__()
|
||||
|
||||
private = {}
|
||||
private["servers"] = {"active": [], "building": [], "error": []}
|
||||
private["resources"] = {
|
||||
"memory": {"used": float(0), "size": float(0)},
|
||||
"vcpus": {"used": float(0), "size": float(0)},
|
||||
"instances": {"used": float(0), "size": float(0)}}
|
||||
|
||||
shared = {}
|
||||
shared["servers"] = {"active": [], "building": [], "error": []}
|
||||
shared["resources"] = {
|
||||
"memory": {"used": float(0), "size": float(0)},
|
||||
"vcpus": {"used": float(0), "size": float(0)},
|
||||
"instances": {"used": float(0), "size": float(0)}}
|
||||
|
||||
self.set("shared", shared)
|
||||
self.set("private", private)
|
||||
self.condition = threading.Condition()
|
||||
|
||||
def getType(self):
|
||||
return self.get("type")
|
||||
|
||||
def setType(self, type):
|
||||
self.set("type", type)
|
||||
|
||||
def getServers(self, status, private=True):
|
||||
if private:
|
||||
servers = self.get("private")["servers"]
|
||||
else:
|
||||
servers = self.get("shared")["servers"]
|
||||
|
||||
if status not in servers:
|
||||
raise Exception("wrong status %r" % status)
|
||||
|
||||
return servers[status]
|
||||
|
||||
def reset(self):
|
||||
with self.condition:
|
||||
for resource in self.get("private")["resources"].values():
|
||||
resource["used"] = 0
|
||||
|
||||
self.condition.notifyAll()
|
||||
|
||||
def getSize(self, resource, private=True):
|
||||
if private:
|
||||
resources = self.get("private")["resources"]
|
||||
else:
|
||||
resources = self.get("shared")["resources"]
|
||||
|
||||
if resource not in resources:
|
||||
raise Exception("wrong resource %r" % resource)
|
||||
|
||||
return resources[resource]["size"]
|
||||
|
||||
def setSize(self, resource, value=0, private=True):
|
||||
if private:
|
||||
resources = self.get("private")["resources"]
|
||||
else:
|
||||
resources = self.get("shared")["resources"]
|
||||
|
||||
if resource not in resources:
|
||||
raise Exception("wrong resource %r" % resource)
|
||||
|
||||
with self.condition:
|
||||
resources[resource]["size"] = value
|
||||
self.condition.notifyAll()
|
||||
|
||||
def getUsage(self, resource, private=True):
|
||||
if private:
|
||||
resources = self.get("private")["resources"]
|
||||
else:
|
||||
resources = self.get("shared")["resources"]
|
||||
|
||||
if resource not in resources:
|
||||
raise Exception("wrong resource %r" % resource)
|
||||
|
||||
return resources[resource]["used"]
|
||||
|
||||
def setUsage(self, resource, value=0, private=True):
|
||||
if private:
|
||||
resources = self.get("private")["resources"]
|
||||
else:
|
||||
resources = self.get("shared")["resources"]
|
||||
|
||||
if resource not in resources:
|
||||
raise Exception("wrong resource %r" % resource)
|
||||
|
||||
with self.condition:
|
||||
resources[resource]["used"] = value
|
||||
self.condition.notifyAll()
|
||||
|
||||
def allocate(self, server, blocking=True):
|
||||
server_id = server.getId()
|
||||
state = server.getState()
|
||||
flavor = server.getFlavor()
|
||||
vcpus = flavor.getVCPUs()
|
||||
memory = flavor.getMemory()
|
||||
found = False
|
||||
|
||||
if server.isEphemeral():
|
||||
if SharedQuota.allocate(server, blocking):
|
||||
LOG.info(">> SharedQuota.allocate OK")
|
||||
shared = self.get("shared")
|
||||
servers = shared["servers"]
|
||||
resources = shared["resources"]
|
||||
|
||||
with self.condition:
|
||||
resources["vcpus"]["used"] += vcpus
|
||||
resources["memory"]["used"] += memory
|
||||
resources["instances"]["used"] += 1
|
||||
|
||||
servers["active"].append(server_id)
|
||||
|
||||
self.condition.notifyAll()
|
||||
return True
|
||||
else:
|
||||
LOG.info(">> SharedQuota.allocate NO")
|
||||
return False
|
||||
|
||||
private = self.get("private")
|
||||
servers = private["servers"]
|
||||
resources = private["resources"]
|
||||
|
||||
if vcpus > resources["vcpus"]["size"] or \
|
||||
memory > resources["memory"]["size"]:
|
||||
raise Exception("the required resources for server %r "
|
||||
"exceed the quota size" % server_id)
|
||||
|
||||
with self.condition:
|
||||
if server_id in servers["active"]:
|
||||
raise Exception("resources for server %r already allocated"
|
||||
% server_id)
|
||||
elif server_id in servers["building"]:
|
||||
raise Exception("resources for server %r waiting "
|
||||
"to be allocated" % server_id)
|
||||
elif state:
|
||||
resources["vcpus"]["used"] += vcpus
|
||||
resources["memory"]["used"] += memory
|
||||
resources["instances"]["used"] += 1
|
||||
|
||||
servers[state].append(server_id)
|
||||
|
||||
found = True
|
||||
elif not blocking:
|
||||
servers["building"].append(server_id)
|
||||
|
||||
while (not found and server_id in servers["building"]):
|
||||
vcpus_size = resources["vcpus"]["size"]
|
||||
vcpus_used = resources["vcpus"]["used"]
|
||||
memory_size = resources["memory"]["size"]
|
||||
memory_used = resources["memory"]["used"]
|
||||
|
||||
LOG.debug("allocating server_id=%s vcpus=%s "
|
||||
"memory=%s [vcpus in use %s of %s; "
|
||||
"memory in use %s of %s]"
|
||||
% (server_id,
|
||||
vcpus,
|
||||
memory,
|
||||
vcpus_used,
|
||||
vcpus_size,
|
||||
memory_used,
|
||||
memory_size))
|
||||
|
||||
if (vcpus_size - vcpus_used >= vcpus) and \
|
||||
(memory_size - memory_used >= memory):
|
||||
found = True
|
||||
|
||||
resources["vcpus"]["used"] += vcpus
|
||||
resources["memory"]["used"] += memory
|
||||
resources["instances"]["used"] += 1
|
||||
|
||||
servers["active"].append(server_id)
|
||||
servers["building"].remove(server_id)
|
||||
|
||||
LOG.info("allocated server_id=%s vcpus=%s memory"
|
||||
"=%s [vcpus in use %s of %s; "
|
||||
"memory in use %s of %s]"
|
||||
% (server_id,
|
||||
vcpus,
|
||||
memory,
|
||||
resources["vcpus"]["used"],
|
||||
resources["vcpus"]["size"],
|
||||
resources["memory"]["used"],
|
||||
resources["memory"]["size"]))
|
||||
elif blocking:
|
||||
LOG.info("allocate wait!!!")
|
||||
self.condition.wait()
|
||||
else:
|
||||
break
|
||||
|
||||
self.condition.notifyAll()
|
||||
|
||||
if not found:
|
||||
servers["building"].remove(server_id)
|
||||
|
||||
return found
|
||||
|
||||
def release(self, server):
|
||||
server_id = server.getId()
|
||||
flavor = server.getFlavor()
|
||||
vcpus = flavor.getVCPUs()
|
||||
memory = flavor.getMemory()
|
||||
|
||||
if SharedQuota.release(server):
|
||||
shared = self.get("shared")
|
||||
servers = shared["servers"]
|
||||
resources = shared["resources"]
|
||||
|
||||
with self.condition:
|
||||
if server_id in servers["building"]:
|
||||
servers["building"].remove(server_id)
|
||||
elif server_id in servers["active"]:
|
||||
resources["vcpus"]["used"] -= vcpus
|
||||
resources["memory"]["used"] -= memory
|
||||
resources["instances"]["used"] -= 1
|
||||
|
||||
if server_id in servers["active"]:
|
||||
servers["active"].remove(server_id)
|
||||
else:
|
||||
servers["error"].remove(server_id)
|
||||
|
||||
self.condition.notifyAll()
|
||||
return True
|
||||
|
||||
private = self.get("private")
|
||||
servers = private["servers"]
|
||||
resources = private["resources"]
|
||||
found = False
|
||||
with self.condition:
|
||||
LOG.debug("releasing server_id=%s vcpus=%s memory=%s "
|
||||
"[vcpu in use %s of %s; memory in use %s of %s]"
|
||||
% (server_id,
|
||||
vcpus,
|
||||
memory,
|
||||
resources["vcpus"]["used"],
|
||||
resources["vcpus"]["size"],
|
||||
resources["memory"]["used"],
|
||||
resources["memory"]["size"]))
|
||||
|
||||
if server_id in servers["building"]:
|
||||
servers["building"].remove(server_id)
|
||||
found = True
|
||||
elif server_id in servers["active"]:
|
||||
if resources["vcpus"]["used"] - vcpus < 0:
|
||||
resources["vcpus"]["used"] = 0
|
||||
else:
|
||||
resources["vcpus"]["used"] -= vcpus
|
||||
|
||||
if resources["memory"]["used"] - memory < 0:
|
||||
resources["memory"]["used"] = 0
|
||||
else:
|
||||
resources["memory"]["used"] -= memory
|
||||
|
||||
resources["instances"]["used"] -= 1
|
||||
|
||||
if server_id in servers["active"]:
|
||||
servers["active"].remove(server_id)
|
||||
else:
|
||||
servers["error"].remove(server_id)
|
||||
|
||||
LOG.info("released server_id=%s vcpus=%s memory=%s "
|
||||
"[vcpu in use %s of %s; memory in use %s of %s]"
|
||||
% (server_id,
|
||||
vcpus,
|
||||
memory,
|
||||
resources["vcpus"]["used"],
|
||||
resources["vcpus"]["size"],
|
||||
resources["memory"]["used"],
|
||||
resources["memory"]["size"]))
|
||||
found = True
|
||||
else:
|
||||
LOG.debug("release: instance %r not found!" % (server_id))
|
||||
|
||||
self.condition.notifyAll()
|
||||
return found
|
||||
|
||||
|
||||
class SharedQuota(SynergyObject):
|
||||
resources = {}
|
||||
resources["memory"] = {"used": float(0), "size": float(0)}
|
||||
resources["vcpus"] = {"used": float(0), "size": float(0)}
|
||||
resources["instances"] = {"used": float(0), "size": float(-1)}
|
||||
servers = {"active": [], "building": [], "error": []}
|
||||
condition = threading.Condition()
|
||||
lastAllocationTime = datetime.now()
|
||||
lastReleaseTime = datetime.now()
|
||||
enabled = False
|
||||
|
||||
def __init__(self):
|
||||
super(SharedQuota, self).__init__()
|
||||
|
||||
self.set("servers", SharedQuota.servers)
|
||||
self.set("resources", SharedQuota.resources)
|
||||
self.set("enabled", SharedQuota.enabled)
|
||||
self.set("lastAllocationTime", SharedQuota.lastAllocationTime)
|
||||
self.set("lastReleaseTime", SharedQuota.lastReleaseTime)
|
||||
|
||||
@classmethod
|
||||
def isEnabled(cls):
|
||||
return cls.enabled
|
||||
|
||||
@classmethod
|
||||
def enable(cls):
|
||||
with cls.condition:
|
||||
cls.enabled = True
|
||||
cls.condition.notifyAll()
|
||||
|
||||
@classmethod
|
||||
def disable(cls):
|
||||
with cls.condition:
|
||||
cls.enabled = False
|
||||
cls.condition.notifyAll()
|
||||
|
||||
@classmethod
|
||||
def getSize(cls, resource):
|
||||
if resource not in cls.resources:
|
||||
raise Exception("wrong resource %r" % resource)
|
||||
|
||||
return cls.resources[resource]["size"]
|
||||
|
||||
@classmethod
|
||||
def setSize(cls, resource, value):
|
||||
if resource not in cls.resources:
|
||||
raise Exception("wrong resource %r" % resource)
|
||||
|
||||
with cls.condition:
|
||||
cls.resources[resource]["size"] = value
|
||||
cls.condition.notifyAll()
|
||||
|
||||
@classmethod
|
||||
def getUsage(cls, resource):
|
||||
if resource not in cls.resources:
|
||||
raise Exception("wrong resource %r" % resource)
|
||||
|
||||
return cls.resources[resource]["used"]
|
||||
|
||||
@classmethod
|
||||
def setUsage(cls, resource, value=0):
|
||||
if resource not in cls.resources:
|
||||
raise Exception("wrong resource %r" % resource)
|
||||
|
||||
with cls.condition:
|
||||
cls.resources[resource]["used"] = value
|
||||
cls.condition.notifyAll()
|
||||
|
||||
@classmethod
|
||||
def getLastAllocationTime(cls):
|
||||
return cls.lastAllocationTime
|
||||
|
||||
@classmethod
|
||||
def getLastReleaseTime(cls):
|
||||
return cls.lastReleaseTime
|
||||
|
||||
@classmethod
|
||||
def wait(cls):
|
||||
with cls.condition:
|
||||
cls.condition.wait()
|
||||
|
||||
@classmethod
|
||||
def allocate(cls, server, blocking=True):
|
||||
server_id = server.getId()
|
||||
state = server.getState()
|
||||
flavor = server.getFlavor()
|
||||
vcpus = flavor.getVCPUs()
|
||||
memory = flavor.getMemory()
|
||||
found = False
|
||||
|
||||
if vcpus > cls.resources["vcpus"]["size"] or \
|
||||
memory > cls.resources["memory"]["size"]:
|
||||
raise Exception("the required resources for server %r "
|
||||
"exceed the quota size" % server_id)
|
||||
|
||||
with cls.condition:
|
||||
if server_id in cls.servers["active"]:
|
||||
raise Exception("resources for server %r already allocated"
|
||||
% server_id)
|
||||
elif server_id in cls.servers["building"]:
|
||||
raise Exception("resources for server %r already waiting "
|
||||
"to be allocated" % server_id)
|
||||
elif state:
|
||||
cls.resources["vcpus"]["used"] += vcpus
|
||||
cls.resources["memory"]["used"] += memory
|
||||
cls.resources["instances"]["used"] += 1
|
||||
|
||||
cls.servers[state].append(server_id)
|
||||
|
||||
found = True
|
||||
else:
|
||||
cls.servers["building"].append(server_id)
|
||||
|
||||
while (cls.enabled and not found and
|
||||
server_id in cls.servers["building"]):
|
||||
vcpus_size = cls.resources["vcpus"]["size"]
|
||||
vcpus_used = cls.resources["vcpus"]["used"]
|
||||
memory_size = cls.resources["memory"]["size"]
|
||||
memory_used = cls.resources["memory"]["used"]
|
||||
|
||||
LOG.debug("allocating server_id=%s vcpus=%s "
|
||||
"memory=%s [vcpus in use %s of %s; "
|
||||
"memory in use %s of %s]"
|
||||
% (server_id,
|
||||
vcpus,
|
||||
memory,
|
||||
vcpus_used,
|
||||
vcpus_size,
|
||||
memory_used,
|
||||
memory_size))
|
||||
|
||||
if (vcpus_size - vcpus_used >= vcpus) and \
|
||||
(memory_size - memory_used >= memory):
|
||||
found = True
|
||||
|
||||
cls.resources["vcpus"]["used"] += vcpus
|
||||
cls.resources["memory"]["used"] += memory
|
||||
cls.resources["instances"]["used"] += 1
|
||||
|
||||
cls.servers["active"].append(server_id)
|
||||
cls.servers["building"].remove(server_id)
|
||||
|
||||
LOG.info("allocated server_id=%s vcpus=%s memory"
|
||||
"=%s [vcpus in use %s of %s; "
|
||||
"memory in use %s of %s]"
|
||||
% (server_id,
|
||||
vcpus,
|
||||
memory,
|
||||
cls.resources["vcpus"]["used"],
|
||||
cls.resources["vcpus"]["size"],
|
||||
cls.resources["memory"]["used"],
|
||||
cls.resources["memory"]["size"]))
|
||||
|
||||
cls.lastAllocationTime = datetime.now()
|
||||
elif blocking:
|
||||
LOG.info("allocate wait!!!")
|
||||
cls.condition.wait()
|
||||
else:
|
||||
break
|
||||
|
||||
cls.condition.notifyAll()
|
||||
|
||||
if not found:
|
||||
cls.servers["building"].remove(server_id)
|
||||
|
||||
return found
|
||||
|
||||
@classmethod
|
||||
def release(cls, server):
|
||||
server_id = server.getId()
|
||||
flavor = server.getFlavor()
|
||||
vcpus = flavor.getVCPUs()
|
||||
memory = flavor.getMemory()
|
||||
found = False
|
||||
|
||||
with cls.condition:
|
||||
LOG.debug("releasing server_id=%s vcpus=%s memory=%s "
|
||||
"[vcpu in use %s of %s; memory in use %s of %s]"
|
||||
% (server_id,
|
||||
vcpus,
|
||||
memory,
|
||||
cls.resources["vcpus"]["used"],
|
||||
cls.resources["vcpus"]["size"],
|
||||
cls.resources["memory"]["used"],
|
||||
cls.resources["memory"]["size"]))
|
||||
|
||||
if server_id in cls.servers["building"]:
|
||||
cls.servers["building"].remove(server_id)
|
||||
found = True
|
||||
elif server_id in cls.servers["active"] or \
|
||||
server_id in cls.servers["error"]:
|
||||
if cls.resources["vcpus"]["used"] - vcpus < 0:
|
||||
cls.resources["vcpus"]["used"] = 0
|
||||
else:
|
||||
cls.resources["vcpus"]["used"] -= vcpus
|
||||
|
||||
if cls.resources["memory"]["used"] - memory < 0:
|
||||
cls.resources["memory"]["used"] = 0
|
||||
else:
|
||||
cls.resources["memory"]["used"] -= memory
|
||||
|
||||
if server_id in cls.servers["active"]:
|
||||
cls.servers["active"].remove(server_id)
|
||||
else:
|
||||
cls.servers["error"].remove(server_id)
|
||||
|
||||
cls.resources["instances"]["used"] -= 1
|
||||
|
||||
LOG.info("released server_id=%s vcpus=%s memory=%s "
|
||||
"[vcpu in use %s of %s; memory in use %s of %s]"
|
||||
% (server_id,
|
||||
vcpus,
|
||||
memory,
|
||||
cls.resources["vcpus"]["used"],
|
||||
cls.resources["vcpus"]["size"],
|
||||
cls.resources["memory"]["used"],
|
||||
cls.resources["memory"]["size"]))
|
||||
|
||||
cls.lastReleaseTime = datetime.now()
|
||||
found = True
|
||||
else:
|
||||
LOG.debug("release: instance %r not found!" % (server_id))
|
||||
|
||||
cls.condition.notifyAll()
|
||||
return found
|
||||
|
||||
@classmethod
|
||||
def deserialize(cls, entity):
|
||||
quota = super(SharedQuota, cls).deserialize(entity)
|
||||
|
||||
cls.resources = entity["resources"]
|
||||
cls.enabled = entity["enabled"]
|
||||
cls.lastAllocationTime = datetime.strptime(
|
||||
entity["lastAllocationTime"], "%Y-%m-%dT%H:%M:%S.%f")
|
||||
cls.lastReleaseTime = datetime.strptime(
|
||||
entity["lastReleaseTime"], "%Y-%m-%dT%H:%M:%S.%f")
|
||||
|
||||
return quota
|
185
synergy_scheduler_manager/common/request.py
Normal file
185
synergy_scheduler_manager/common/request.py
Normal file
@ -0,0 +1,185 @@
|
||||
import utils
|
||||
|
||||
from datetime import datetime
|
||||
from flavor import Flavor
|
||||
from server import Server
|
||||
|
||||
__author__ = "Lisa Zangrando"
|
||||
__email__ = "lisa.zangrando[AT]pd.infn.it"
|
||||
__copyright__ = """Copyright (c) 2015 INFN - INDIGO-DataCloud
|
||||
All Rights Reserved
|
||||
|
||||
Licensed under the Apache License, Version 2.0;
|
||||
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 Request(object):
|
||||
|
||||
def __init__(self):
|
||||
self.context = None
|
||||
self.instance = None
|
||||
self.image = None
|
||||
self.filter_properties = None
|
||||
self.admin_password = None
|
||||
self.injected_files = None
|
||||
self.requested_networks = None
|
||||
self.security_groups = None
|
||||
self.block_device_mapping = None
|
||||
self.legacy_bdm = None
|
||||
|
||||
def getAdminPassword(self):
|
||||
return self.admin_password
|
||||
|
||||
def getId(self):
|
||||
if self.instance:
|
||||
return self.instance["nova_object.data"]["uuid"]
|
||||
|
||||
return None
|
||||
|
||||
def getInstance(self):
|
||||
return self.instance
|
||||
|
||||
def getServer(self):
|
||||
server = None
|
||||
|
||||
if self.instance:
|
||||
instance_data = self.instance["nova_object.data"]
|
||||
flavor_data = instance_data["flavor"]["nova_object.data"]
|
||||
|
||||
flavor = Flavor()
|
||||
flavor.setId(flavor_data["flavorid"])
|
||||
flavor.setName(flavor_data["name"])
|
||||
flavor.setMemory(flavor_data["memory_mb"])
|
||||
flavor.setVCPUs(flavor_data["vcpus"])
|
||||
flavor.setStorage(flavor_data["root_gb"])
|
||||
|
||||
server = Server()
|
||||
server.setFlavor(flavor)
|
||||
server.setId(instance_data["uuid"])
|
||||
server.setUserId(instance_data["user_id"])
|
||||
server.setProjectId(instance_data["project_id"])
|
||||
server.setCreatedAt(instance_data["created_at"])
|
||||
server.setMetadata(instance_data["metadata"])
|
||||
server.setKeyName(instance_data["key_name"])
|
||||
|
||||
if "user_data" in instance_data:
|
||||
user_data = instance_data["user_data"]
|
||||
if user_data:
|
||||
server.setUserData(utils.decodeBase64(user_data))
|
||||
|
||||
return server
|
||||
|
||||
def getImage(self):
|
||||
return self.image
|
||||
|
||||
def getUserId(self):
|
||||
if self.instance:
|
||||
return self.instance["nova_object.data"]["user_id"]
|
||||
|
||||
return None
|
||||
|
||||
def getProjectId(self):
|
||||
if self.instance:
|
||||
return self.instance["nova_object.data"]["project_id"]
|
||||
|
||||
return None
|
||||
|
||||
def getContext(self):
|
||||
return self.context
|
||||
|
||||
def getCreatedAt(self):
|
||||
if self.instance:
|
||||
created_at = self.instance["nova_object.data"]["created_at"]
|
||||
timestamp = datetime.strptime(created_at, "%Y-%m-%dT%H:%M:%SZ")
|
||||
return timestamp
|
||||
|
||||
return 0
|
||||
|
||||
def getMetadata(self):
|
||||
if self.instance:
|
||||
return self.instance["nova_object.data"]["metadata"]
|
||||
|
||||
return None
|
||||
|
||||
def getRetry(self):
|
||||
if self.filter_properties:
|
||||
return self.filter_properties.get("retry", None)
|
||||
|
||||
return None
|
||||
|
||||
def getFilterProperties(self):
|
||||
return self.filter_properties
|
||||
|
||||
def getInjectedFiles(self):
|
||||
return self.injected_files
|
||||
|
||||
def getRequestedNetworks(self):
|
||||
return self.requested_networks
|
||||
|
||||
def getSecurityGroups(self):
|
||||
return self.security_groups
|
||||
|
||||
def getBlockDeviceMapping(self):
|
||||
return self.block_device_mapping
|
||||
|
||||
def getLegacyBDM(self):
|
||||
return self.legacy_bdm
|
||||
|
||||
def toDict(self):
|
||||
request = {}
|
||||
request['context'] = self.context
|
||||
request['instance'] = self.instance
|
||||
request['image'] = self.image
|
||||
request['filter_properties'] = self.filter_properties
|
||||
request['admin_password'] = self.admin_password
|
||||
request['injected_files'] = self.injected_files
|
||||
request['requested_networks'] = self.requested_networks
|
||||
request['security_groups'] = self.security_groups
|
||||
request['block_device_mapping'] = self.block_device_mapping
|
||||
request['legacy_bdm'] = self.legacy_bdm
|
||||
|
||||
return request
|
||||
|
||||
@classmethod
|
||||
def fromDict(cls, request_dict):
|
||||
request = Request()
|
||||
request.context = request_dict['context']
|
||||
request.instance = request_dict['instance']
|
||||
request.image = request_dict['image']
|
||||
request.filter_properties = request_dict['filter_properties']
|
||||
request.admin_password = request_dict['admin_password']
|
||||
request.injected_files = request_dict['injected_files']
|
||||
request.requested_networks = request_dict['requested_networks']
|
||||
request.security_groups = request_dict['security_groups']
|
||||
request.block_device_mapping = request_dict['block_device_mapping']
|
||||
request.legacy_bdm = request_dict['legacy_bdm']
|
||||
|
||||
return request
|
||||
|
||||
@classmethod
|
||||
def build(cls, context, instance, image, filter_properties,
|
||||
admin_password, injected_files, requested_networks,
|
||||
security_groups, block_device_mapping=None, legacy_bdm=True):
|
||||
request = Request()
|
||||
request.context = context
|
||||
request.instance = instance
|
||||
request.image = image
|
||||
request.filter_properties = filter_properties
|
||||
request.admin_password = admin_password
|
||||
request.injected_files = injected_files
|
||||
request.requested_networks = requested_networks
|
||||
request.security_groups = security_groups
|
||||
request.block_device_mapping = block_device_mapping
|
||||
request.legacy_bdm = legacy_bdm
|
||||
|
||||
return request
|
25
synergy_scheduler_manager/common/role.py
Normal file
25
synergy_scheduler_manager/common/role.py
Normal file
@ -0,0 +1,25 @@
|
||||
from synergy.common.serializer import SynergyObject
|
||||
|
||||
__author__ = "Lisa Zangrando"
|
||||
__email__ = "lisa.zangrando[AT]pd.infn.it"
|
||||
__copyright__ = """Copyright (c) 2015 INFN - INDIGO-DataCloud
|
||||
All Rights Reserved
|
||||
|
||||
Licensed under the Apache License, Version 2.0;
|
||||
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 Role(SynergyObject):
|
||||
|
||||
def __init__(self):
|
||||
super(Role, self).__init__()
|
136
synergy_scheduler_manager/common/server.py
Normal file
136
synergy_scheduler_manager/common/server.py
Normal file
@ -0,0 +1,136 @@
|
||||
import synergy.common.utils as utils
|
||||
|
||||
from datetime import datetime
|
||||
from synergy.common.serializer import SynergyObject
|
||||
|
||||
|
||||
__author__ = "Lisa Zangrando"
|
||||
__email__ = "lisa.zangrando[AT]pd.infn.it"
|
||||
__copyright__ = """Copyright (c) 2015 INFN - INDIGO-DataCloud
|
||||
All Rights Reserved
|
||||
|
||||
Licensed under the Apache License, Version 2.0;
|
||||
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 Server(SynergyObject):
|
||||
|
||||
def __init__(self):
|
||||
super(Server, self).__init__()
|
||||
self.setType("permanent")
|
||||
|
||||
def __getDateTime(self, date):
|
||||
if not date:
|
||||
return None
|
||||
elif isinstance(date, basestring):
|
||||
return datetime.strptime(date, "%Y-%m-%dT%H:%M:%SZ")
|
||||
elif isinstance(date, datetime):
|
||||
return date
|
||||
else:
|
||||
raise Exception("not valid date format")
|
||||
|
||||
def getType(self):
|
||||
return self.get("type")
|
||||
|
||||
def setType(self, type):
|
||||
self.set("type", type)
|
||||
|
||||
def getState(self):
|
||||
return self.get("state")
|
||||
|
||||
def setState(self, state):
|
||||
self.set("state", state)
|
||||
|
||||
def getFlavor(self):
|
||||
return self.get("flavor")
|
||||
|
||||
def setFlavor(self, flavor):
|
||||
self.set("flavor", flavor)
|
||||
|
||||
def getKeyName(self):
|
||||
return self.get("key_name")
|
||||
|
||||
def setKeyName(self, key_name):
|
||||
self.set("key_name", key_name)
|
||||
|
||||
def getMetadata(self):
|
||||
return self.get("metadata")
|
||||
|
||||
def setMetadata(self, metadata):
|
||||
self.set("metadata", metadata)
|
||||
|
||||
if "quota" in metadata and metadata["quota"] == "shared":
|
||||
self.setType("ephemeral")
|
||||
else:
|
||||
self.setType("permanent")
|
||||
|
||||
def getUserData(self):
|
||||
return self.get("userdata")
|
||||
|
||||
def setUserData(self, userdata):
|
||||
self.set("userdata", userdata)
|
||||
|
||||
if userdata:
|
||||
try:
|
||||
quota = utils.getConfigParameter(userdata, "quota", "synergy")
|
||||
|
||||
if quota is None or quota == "private":
|
||||
self.setType("permanent")
|
||||
elif quota == "shared":
|
||||
self.setType("ephemeral")
|
||||
else:
|
||||
self.setType("permanent")
|
||||
except Exception:
|
||||
self.setType("permanent")
|
||||
|
||||
def getUserId(self):
|
||||
return self.get("user_id")
|
||||
|
||||
def setUserId(self, user_id):
|
||||
self.set("user_id", user_id)
|
||||
|
||||
def getProjectId(self):
|
||||
return self.get("project_id")
|
||||
|
||||
def setProjectId(self, project_id):
|
||||
self.set("project_id", project_id)
|
||||
|
||||
def getCreatedAt(self):
|
||||
return self.get("created_at")
|
||||
|
||||
def setCreatedAt(self, created_at):
|
||||
self.set("created_at", self.__getDateTime(created_at))
|
||||
|
||||
def getLaunchedAt(self):
|
||||
return self.get("launched_at")
|
||||
|
||||
def setLaunchedAt(self, launched_at):
|
||||
self.set("launched_at", self.__getDateTime(launched_at))
|
||||
|
||||
def getUpdatedAt(self):
|
||||
return self.get("updated_at")
|
||||
|
||||
def setUpdatedAt(self, updated_at):
|
||||
self.set("updated_at", self.__getDateTime(updated_at))
|
||||
|
||||
def getTerminatedAt(self):
|
||||
return self.get("terminated_at")
|
||||
|
||||
def setTerminatedAt(self, terminated_at):
|
||||
self.set("terminated_at", self.__getDateTime(terminated_at))
|
||||
|
||||
def isEphemeral(self):
|
||||
return self.get("type") == "ephemeral"
|
||||
|
||||
def isPermanent(self):
|
||||
return self.get("type") == "permanent"
|
60
synergy_scheduler_manager/common/service.py
Normal file
60
synergy_scheduler_manager/common/service.py
Normal file
@ -0,0 +1,60 @@
|
||||
from synergy.common.serializer import SynergyObject
|
||||
|
||||
|
||||
__author__ = "Lisa Zangrando"
|
||||
__email__ = "lisa.zangrando[AT]pd.infn.it"
|
||||
__copyright__ = """Copyright (c) 2015 INFN - INDIGO-DataCloud
|
||||
All Rights Reserved
|
||||
|
||||
Licensed under the Apache License, Version 2.0;
|
||||
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 Service(SynergyObject):
|
||||
|
||||
def __init__(self):
|
||||
super(Service, self).__init__()
|
||||
|
||||
self.set("enabled", False)
|
||||
self.set("endpoints", [])
|
||||
|
||||
def getType(self):
|
||||
return self.get("type")
|
||||
|
||||
def setType(self, type):
|
||||
self.set("type", type)
|
||||
|
||||
def getEndpoints(self):
|
||||
return self.get("endpoints")
|
||||
|
||||
def getEndpoint(self, interface):
|
||||
for endpoint in self.get("endpoints"):
|
||||
if endpoint.getInterface() == interface:
|
||||
return endpoint
|
||||
|
||||
return None
|
||||
|
||||
def getDescription(self):
|
||||
return self.get("description")
|
||||
|
||||
def setDescription(self, description):
|
||||
self.set("description", description)
|
||||
|
||||
def getStatus(self):
|
||||
return self.get("status")
|
||||
|
||||
def setStatus(self, status):
|
||||
self.set("status", status)
|
||||
|
||||
def isEnabled(self):
|
||||
return self.get("status") == "enabled"
|
48
synergy_scheduler_manager/common/share.py
Normal file
48
synergy_scheduler_manager/common/share.py
Normal file
@ -0,0 +1,48 @@
|
||||
from synergy.common.serializer import SynergyObject
|
||||
|
||||
|
||||
__author__ = "Lisa Zangrando"
|
||||
__email__ = "lisa.zangrando[AT]pd.infn.it"
|
||||
__copyright__ = """Copyright (c) 2015 INFN - INDIGO-DataCloud
|
||||
All Rights Reserved
|
||||
|
||||
Licensed under the Apache License, Version 2.0;
|
||||
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 Share(SynergyObject):
|
||||
|
||||
def __init__(self):
|
||||
super(Share, self).__init__()
|
||||
|
||||
self.set("value", float(0))
|
||||
self.set("sibling_value", float(0))
|
||||
self.set("normalized_value", float(0))
|
||||
|
||||
def getValue(self):
|
||||
return self.get("value")
|
||||
|
||||
def setValue(self, value):
|
||||
self.set("value", value)
|
||||
|
||||
def getSiblingValue(self):
|
||||
return self.get("sibling_value")
|
||||
|
||||
def setSiblingValue(self, value):
|
||||
self.set("sibling_value", value)
|
||||
|
||||
def getNormalizedValue(self):
|
||||
return self.get("normalized_value")
|
||||
|
||||
def setNormalizedValue(self, value):
|
||||
self.set("normalized_value", value)
|
184
synergy_scheduler_manager/common/token.py
Normal file
184
synergy_scheduler_manager/common/token.py
Normal file
@ -0,0 +1,184 @@
|
||||
import json
|
||||
import os.path
|
||||
|
||||
from datetime import datetime
|
||||
from endpoint import Endpoint
|
||||
from project import Project
|
||||
from role import Role
|
||||
from service import Service
|
||||
from synergy.common.serializer import SynergyObject
|
||||
from synergy_scheduler_manager.common.user import User
|
||||
|
||||
|
||||
__author__ = "Lisa Zangrando"
|
||||
__email__ = "lisa.zangrando[AT]pd.infn.it"
|
||||
__copyright__ = """Copyright (c) 2015 INFN - INDIGO-DataCloud
|
||||
All Rights Reserved
|
||||
|
||||
Licensed under the Apache License, Version 2.0;
|
||||
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 Token(SynergyObject):
|
||||
|
||||
def __init__(self):
|
||||
super(Token, self).__init__()
|
||||
|
||||
self.set("extras", {})
|
||||
self.set("roles", [])
|
||||
self.set("catalog", [])
|
||||
|
||||
@classmethod
|
||||
def parse(cls, id, data):
|
||||
token = Token()
|
||||
|
||||
token.setId(id)
|
||||
|
||||
data = data["token"]
|
||||
token.setCreation(datetime.strptime(data["issued_at"],
|
||||
"%Y-%m-%dT%H:%M:%S.%fZ"))
|
||||
|
||||
token.setExpiration(datetime.strptime(data["expires_at"],
|
||||
"%Y-%m-%dT%H:%M:%S.%fZ"))
|
||||
|
||||
project = Project()
|
||||
project.setId(data["project"]["id"])
|
||||
project.setName(data["project"]["name"])
|
||||
|
||||
token.setProject(project)
|
||||
|
||||
user = User()
|
||||
user.setId(data["user"]["id"])
|
||||
user.setName(data["user"]["name"])
|
||||
user.setProjectId(data["project"]["id"])
|
||||
|
||||
token.setUser(user)
|
||||
|
||||
token.getExtras().update(data["extras"])
|
||||
|
||||
for info in data["roles"]:
|
||||
role = Role()
|
||||
role.setId(info["id"])
|
||||
role.setName(info["name"])
|
||||
|
||||
token.getRoles().append(role)
|
||||
|
||||
for service_info in data["catalog"]:
|
||||
service = Service()
|
||||
service.setId(service_info["id"])
|
||||
service.setType(service_info["type"])
|
||||
service.setName(service_info["name"])
|
||||
|
||||
for endpoint_info in service_info["endpoints"]:
|
||||
endpoint = Endpoint()
|
||||
endpoint.setId(endpoint_info["id"])
|
||||
endpoint.setInterface(endpoint_info["interface"])
|
||||
endpoint.setRegion(endpoint_info["region"])
|
||||
endpoint.setRegionId(endpoint_info["region_id"])
|
||||
endpoint.setURL(endpoint_info["url"])
|
||||
|
||||
service.getEndpoints().append(endpoint)
|
||||
|
||||
token.getServices().append(service)
|
||||
|
||||
return token
|
||||
|
||||
def getServices(self):
|
||||
return self.get("catalog")
|
||||
|
||||
def getService(self, name):
|
||||
for service in self.get("catalog"):
|
||||
if service.getName() == name:
|
||||
return service
|
||||
|
||||
return None
|
||||
|
||||
def getCreation(self):
|
||||
return self.get("issued_at")
|
||||
|
||||
def setCreation(self, issued_at):
|
||||
self.set("issued_at", issued_at)
|
||||
|
||||
def getExpiration(self):
|
||||
return self.get("expires_at")
|
||||
|
||||
def setExpiration(self, expires_at):
|
||||
self.set("expires_at", expires_at)
|
||||
|
||||
def getExtras(self):
|
||||
return self.get("extras")
|
||||
|
||||
def getProject(self):
|
||||
return self.get("project")
|
||||
|
||||
def setProject(self, project):
|
||||
self.set("project", project)
|
||||
|
||||
def getRoles(self):
|
||||
return self.get("roles")
|
||||
|
||||
def getUser(self):
|
||||
return self.get("user")
|
||||
|
||||
def setUser(self, user):
|
||||
self.set("user", user)
|
||||
|
||||
def isAdmin(self):
|
||||
for role in self.get("roles"):
|
||||
if role.getName() == "admin":
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def issuedAt(self):
|
||||
return self.get("issued_at")
|
||||
|
||||
def isExpired(self):
|
||||
return self.getExpiration() < datetime.utcnow()
|
||||
|
||||
def save(self, filename):
|
||||
# save to file
|
||||
with open(filename, 'w') as f:
|
||||
json.dump(self.serialize(), f)
|
||||
|
||||
@classmethod
|
||||
def load(cls, filename):
|
||||
if not os.path.isfile(filename):
|
||||
return None
|
||||
|
||||
# load from file:
|
||||
with open(filename, 'r') as f:
|
||||
try:
|
||||
data = json.load(f)
|
||||
return Token.deserialize(data)
|
||||
# if the file is empty the ValueError will be thrown
|
||||
except ValueError as ex:
|
||||
raise ex
|
||||
|
||||
def isotime(self, at=None, subsecond=False):
|
||||
"""Stringify time in ISO 8601 format."""
|
||||
if not at:
|
||||
at = datetime.utcnow()
|
||||
|
||||
if not subsecond:
|
||||
st = at.strftime('%Y-%m-%dT%H:%M:%S')
|
||||
else:
|
||||
st = at.strftime('%Y-%m-%dT%H:%M:%S.%f')
|
||||
|
||||
if at.tzinfo:
|
||||
tz = at.tzinfo.tzname(None)
|
||||
else:
|
||||
tz = 'UTC'
|
||||
|
||||
st += ('Z' if tz == 'UTC' else tz)
|
||||
return st
|
156
synergy_scheduler_manager/common/trust.py
Normal file
156
synergy_scheduler_manager/common/trust.py
Normal file
@ -0,0 +1,156 @@
|
||||
import json
|
||||
import requests
|
||||
|
||||
from datetime import datetime
|
||||
from token import Token
|
||||
|
||||
__author__ = "Lisa Zangrando"
|
||||
__email__ = "lisa.zangrando[AT]pd.infn.it"
|
||||
__copyright__ = """Copyright (c) 2015 INFN - INDIGO-DataCloud
|
||||
All Rights Reserved
|
||||
|
||||
Licensed under the Apache License, Version 2.0;
|
||||
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 Trust(object):
|
||||
|
||||
def __init__(self, data):
|
||||
self.id = data["id"]
|
||||
self.impersonations = data["impersonation"]
|
||||
self.trustor_user_id = data["trustor_user_id"]
|
||||
self.trustee_user_id = data["trustee_user_id"]
|
||||
self.links = data.get("links", [])
|
||||
self.roles = data.get("roles", [])
|
||||
self.remaining_uses = data["remaining_uses"]
|
||||
self.expires_at = None
|
||||
self.keystone_url = None
|
||||
|
||||
if data["expires_at"] is not None:
|
||||
self.expires_at = datetime.strptime(data["expires_at"],
|
||||
"%Y-%m-%dT%H:%M:%S.%fZ")
|
||||
self.project_id = data["project_id"]
|
||||
|
||||
def getId(self):
|
||||
return self.id
|
||||
|
||||
def isImpersonations(self):
|
||||
return self.impersonations
|
||||
|
||||
def getRolesLinks(self):
|
||||
return self.roles_links
|
||||
|
||||
def getTrustorUserId(self):
|
||||
return self.trustor_user_id
|
||||
|
||||
def getTrusteeUserId(self):
|
||||
return self.trustee_user_id
|
||||
|
||||
def getlinks(self):
|
||||
return self.links
|
||||
|
||||
def getProjectId(self):
|
||||
return self.project_id
|
||||
|
||||
def getRoles(self):
|
||||
return self.roles
|
||||
|
||||
def getRemainingUses(self):
|
||||
return self.remaining_uses
|
||||
|
||||
def getExpiration(self):
|
||||
return self.expires_at
|
||||
|
||||
def isExpired(self):
|
||||
if self.getExpiration() is None:
|
||||
return False
|
||||
|
||||
return self.getExpiration() < datetime.utcnow()
|
||||
|
||||
def getToken(self, token_id):
|
||||
headers = {"Content-Type": "application/json",
|
||||
"Accept": "application/json",
|
||||
"User-Agent": "synergy"}
|
||||
data = {}
|
||||
data["auth"] = {"identity": {"methods": ["token"],
|
||||
"token": {"id": token_id}},
|
||||
"scope": {"OS-TRUST:trust": {"id": self.getId()}}}
|
||||
|
||||
response = requests.post(url=self.keystone_url + "/auth/tokens",
|
||||
headers=headers,
|
||||
data=json.dumps(data))
|
||||
|
||||
if response.status_code != requests.codes.ok:
|
||||
response.raise_for_status()
|
||||
|
||||
if not response.text:
|
||||
raise Exception("authentication failed!")
|
||||
|
||||
token_subject = response.headers["X-Subject-Token"]
|
||||
token_data = response.json()
|
||||
|
||||
return Token.parse(token_subject, token_data)
|
||||
|
||||
@staticmethod
|
||||
def makeTrust(trustee_user_id, token, expires_at=None, impersonation=True):
|
||||
if token.isExpired():
|
||||
raise Exception("token expired!")
|
||||
|
||||
headers = {"Content-Type": "application/json",
|
||||
"Accept": "application/json",
|
||||
"User-Agent": "synergy",
|
||||
"X-Auth-Token": token.getId()}
|
||||
|
||||
project_id = token.getProject().getId()
|
||||
roles = token.getRoles()
|
||||
roles_data = []
|
||||
|
||||
for role in roles:
|
||||
roles_data.append({"id": role.getId(), "name": role.getName()})
|
||||
|
||||
data = {}
|
||||
data["trust"] = {"impersonation": impersonation,
|
||||
"project_id": project_id,
|
||||
"roles": roles_data,
|
||||
"trustee_user_id": trustee_user_id,
|
||||
"trustor_user_id": token.getUser().getId()}
|
||||
|
||||
if expires_at is not None:
|
||||
data["trust"]["expires_at"] = token.isotime(expires_at, True)
|
||||
|
||||
service = token.getService("keystone")
|
||||
if not service:
|
||||
raise Exception("keystone service not found!")
|
||||
|
||||
endpoint = service.getEndpoint("admin")
|
||||
if not endpoint:
|
||||
raise Exception("keystone endpoint not found!")
|
||||
|
||||
endpoint_url = endpoint.getURL()
|
||||
|
||||
response = requests.post(url=endpoint_url + "/OS-TRUST/trusts",
|
||||
headers=headers,
|
||||
data=json.dumps(data))
|
||||
|
||||
if response.status_code != requests.codes.ok:
|
||||
response.raise_for_status()
|
||||
|
||||
if not response.text:
|
||||
raise Exception("trust token failed!")
|
||||
|
||||
response = response.json()
|
||||
|
||||
trust = Trust(response["trust"])
|
||||
trust.keystone_url = endpoint_url
|
||||
|
||||
return trust
|
82
synergy_scheduler_manager/common/user.py
Normal file
82
synergy_scheduler_manager/common/user.py
Normal file
@ -0,0 +1,82 @@
|
||||
from priority import Priority
|
||||
from share import Share
|
||||
from synergy.common.serializer import SynergyObject
|
||||
|
||||
|
||||
__author__ = "Lisa Zangrando"
|
||||
__email__ = "lisa.zangrando[AT]pd.infn.it"
|
||||
__copyright__ = """Copyright (c) 2015 INFN - INDIGO-DataCloud
|
||||
All Rights Reserved
|
||||
|
||||
Licensed under the Apache License, Version 2.0;
|
||||
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 User(SynergyObject):
|
||||
|
||||
def __init__(self):
|
||||
super(User, self).__init__()
|
||||
|
||||
self.set("data", {})
|
||||
self.set("priority", Priority())
|
||||
self.set("share", Share())
|
||||
self.set("role", None)
|
||||
self.set("enabled", False)
|
||||
|
||||
def getData(self):
|
||||
return self.get("data")
|
||||
|
||||
def getProjectId(self):
|
||||
return self.get("project_id")
|
||||
|
||||
def setProjectId(self, project_id):
|
||||
self.set("project_id", project_id)
|
||||
|
||||
def getPriority(self):
|
||||
return self.get("priority")
|
||||
|
||||
def getRole(self):
|
||||
return self.get("role")
|
||||
|
||||
def setRole(self, role):
|
||||
self.set("role", role)
|
||||
|
||||
def getShare(self):
|
||||
return self.get("share")
|
||||
|
||||
def isEnabled(self):
|
||||
return self.get("enabled")
|
||||
|
||||
def setEnabled(self, enabled=True):
|
||||
self.set("enabled", enabled)
|
||||
|
||||
|
||||
def main():
|
||||
user = User()
|
||||
user.setId("22222222")
|
||||
user.setName("LISA")
|
||||
user.setProjectId("pippo")
|
||||
data = user.getData()
|
||||
data["a"] = "b"
|
||||
share = user.getShare()
|
||||
share.setValue("10")
|
||||
|
||||
ser = user.serialize()
|
||||
print(ser)
|
||||
|
||||
user1 = SynergyObject.deserialize(ser)
|
||||
print(user1.serialize())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
48
synergy_scheduler_manager/common/utils.py
Normal file
48
synergy_scheduler_manager/common/utils.py
Normal file
@ -0,0 +1,48 @@
|
||||
import base64
|
||||
import binascii
|
||||
import ConfigParser
|
||||
import io
|
||||
|
||||
__author__ = "Lisa Zangrando"
|
||||
__email__ = "lisa.zangrando[AT]pd.infn.it"
|
||||
__copyright__ = """Copyright (c) 2015 INFN - INDIGO-DataCloud
|
||||
All Rights Reserved
|
||||
|
||||
Licensed under the Apache License, Version 2.0;
|
||||
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."""
|
||||
|
||||
|
||||
def encodeBase64(s):
|
||||
if not s:
|
||||
return None
|
||||
|
||||
try:
|
||||
return base64.encodestring(s)
|
||||
except binascii.Error:
|
||||
raise binascii.Error
|
||||
|
||||
|
||||
def decodeBase64(s):
|
||||
if not s:
|
||||
return None
|
||||
|
||||
try:
|
||||
return base64.decodestring(s)
|
||||
except binascii.Error:
|
||||
raise binascii.Error
|
||||
|
||||
|
||||
def getConfigParameter(data, key, section="DEFAULT"):
|
||||
config = ConfigParser.RawConfigParser(allow_no_value=True)
|
||||
config.readfp(io.BytesIO(data))
|
||||
return config.get(section, key)
|
125
synergy_scheduler_manager/tests/unit/test_block_device.py
Normal file
125
synergy_scheduler_manager/tests/unit/test_block_device.py
Normal file
@ -0,0 +1,125 @@
|
||||
# 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.
|
||||
|
||||
from synergy_scheduler_manager.common.block_device import BlockDeviceMapping
|
||||
from synergy_scheduler_manager.tests.unit import base
|
||||
|
||||
|
||||
class TestBlockDeviceMapping(base.TestCase):
|
||||
def setUp(self):
|
||||
super(TestBlockDeviceMapping, self).setUp()
|
||||
self.bdp = BlockDeviceMapping('id')
|
||||
|
||||
def test_set_get_Id(self):
|
||||
self.assertEqual('id', self.bdp.getId())
|
||||
|
||||
def test_set_get_ImageId(self):
|
||||
self.bdp.setImageId('im_id')
|
||||
self.assertEqual('im_id', self.bdp.getImageId())
|
||||
|
||||
def test_set_get_InstaceId(self):
|
||||
self.bdp.setInstanceId('inst_id')
|
||||
self.assertEqual('inst_id', self.bdp.getInstanceId())
|
||||
|
||||
def test_set_get_SnapshotId(self):
|
||||
self.bdp.setSnapshotId('snap_id')
|
||||
self.assertEqual('snap_id', self.bdp.getSnapshotId())
|
||||
|
||||
def test_set_get_VolumeId(self):
|
||||
self.bdp.setVolumeId('vol_id')
|
||||
self.assertEqual('vol_id', self.bdp.getVolumeId())
|
||||
|
||||
def test_set_get_VolumeSize(self):
|
||||
self.bdp.setVolumeSize('vol_size')
|
||||
self.assertEqual('vol_size', self.bdp.getVolumeSize())
|
||||
|
||||
def test_set_get_BootIndex(self):
|
||||
self.bdp.setBootIndex('boot_index')
|
||||
self.assertEqual('boot_index', self.bdp.getBootIndex())
|
||||
|
||||
def test_set_get_CreatedAt(self):
|
||||
self.bdp.setCreatedAt('now')
|
||||
self.assertEqual('now', self.bdp.getCreatedAt())
|
||||
|
||||
def test_set_get_UpdatedAt(self):
|
||||
self.bdp.setUpdatedAt('now')
|
||||
self.assertEqual('now', self.bdp.getUpdatedAt())
|
||||
|
||||
def test_set_get_DeletedAt(self):
|
||||
self.bdp.setDeletedAt('now')
|
||||
self.assertEqual('now', self.bdp.getDeletedAt())
|
||||
|
||||
def test_set_get_DeviceName(self):
|
||||
self.bdp.setDeviceName('name')
|
||||
self.assertEqual('name', self.bdp.getDeviceName())
|
||||
|
||||
def test_set_get_NoDevice(self):
|
||||
self.bdp.setNoDevice('no_dev')
|
||||
self.assertEqual('no_dev', self.bdp.getNoDevice())
|
||||
|
||||
def test_set_get_ConnectionInfo(self):
|
||||
self.bdp.setConnectionInfo('con_info')
|
||||
self.assertEqual('con_info', self.bdp.getConnectionInfo())
|
||||
|
||||
def test_set_get_DestinationType(self):
|
||||
self.bdp.setDestinationType('dest_type')
|
||||
self.assertEqual('dest_type', self.bdp.getDestinationType())
|
||||
|
||||
def test_set_get_SourceType(self):
|
||||
self.bdp.setSourceType('source_type')
|
||||
self.assertEqual('source_type', self.bdp.getSourceType())
|
||||
|
||||
def test_set_get_DiskBus(self):
|
||||
self.bdp.setDiskBus('disk_bus')
|
||||
self.assertEqual('disk_bus', self.bdp.getDiskBus())
|
||||
|
||||
def test_set_get_GuestFormat(self):
|
||||
self.bdp.setGuestFormat('guest_format')
|
||||
self.assertEqual('guest_format', self.bdp.getGuestFormat())
|
||||
|
||||
def test_DeleteOnTermination(self):
|
||||
self.bdp.setDeleteOnTermination('del_term')
|
||||
self.assertEqual('del_term', self.bdp.isDeleteOnTermination())
|
||||
|
||||
def test_Deleted(self):
|
||||
self.bdp.setDeleted('deleted')
|
||||
self.assertEqual('deleted', self.bdp.isDeleted())
|
||||
|
||||
def test_serialize(self):
|
||||
res = self.bdp.serialize()
|
||||
expected = {'boot_index': None,
|
||||
'connection_info': None,
|
||||
'created_at': None,
|
||||
'delete_on_termination': None,
|
||||
'deleted': None,
|
||||
'deleted_at': None,
|
||||
'destination_type': None,
|
||||
'device_name': None,
|
||||
'device_type': None,
|
||||
'disk_bus': None,
|
||||
'guest_format': None,
|
||||
'id': 'id',
|
||||
'image_id': None,
|
||||
'instance_uuid': None,
|
||||
'no_device': None,
|
||||
'snapshot_id': None,
|
||||
'source_type': None,
|
||||
'updated_at': None,
|
||||
'volume_id': None,
|
||||
'volume_size': None
|
||||
}
|
||||
|
||||
self.assertEqual('1.15', res['nova_object.version'])
|
||||
self.assertEqual('nova', res['nova_object.namespace'])
|
||||
self.assertEqual(["device_name"], res["nova_object.changes"])
|
||||
self.assertEqual("BlockDeviceMapping", res["nova_object.name"])
|
||||
self.assertEqual(expected, res["nova_object.data"])
|
32
synergy_scheduler_manager/tests/unit/test_compute.py
Normal file
32
synergy_scheduler_manager/tests/unit/test_compute.py
Normal file
@ -0,0 +1,32 @@
|
||||
# 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.
|
||||
|
||||
from synergy_scheduler_manager.common.compute import Compute
|
||||
from synergy_scheduler_manager.tests.unit import base
|
||||
|
||||
|
||||
class TestCompute(base.TestCase):
|
||||
def setUp(self):
|
||||
super(TestCompute, self).setUp()
|
||||
self.comp = Compute()
|
||||
|
||||
def test_set_get_Host(self):
|
||||
self.comp.setHost('host')
|
||||
self.assertEqual('host', self.comp.getHost())
|
||||
|
||||
def test_set_get_NodeName(self):
|
||||
self.comp.setNodeName('node_name')
|
||||
self.assertEqual('node_name', self.comp.getNodeName())
|
||||
|
||||
def test_set_get_Limits(self):
|
||||
self.comp.setLimits('limits')
|
||||
self.assertEqual('limits', self.comp.getLimits())
|
44
synergy_scheduler_manager/tests/unit/test_endpoint.py
Executable file
44
synergy_scheduler_manager/tests/unit/test_endpoint.py
Executable file
@ -0,0 +1,44 @@
|
||||
# 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.
|
||||
|
||||
from synergy_scheduler_manager.common.endpoint import Endpoint
|
||||
from synergy_scheduler_manager.tests.unit import base
|
||||
|
||||
|
||||
class TestEndpoint(base.TestCase):
|
||||
def setUp(self):
|
||||
super(TestEndpoint, self).setUp()
|
||||
self.endp = Endpoint()
|
||||
|
||||
def test_set_get_interface(self):
|
||||
self.endp.setInterface('pippo')
|
||||
self.assertEqual('pippo', self.endp.getInterface())
|
||||
|
||||
def test_set__get_region(self):
|
||||
self.endp.setRegion('region')
|
||||
self.assertEqual('region', self.endp.getRegion())
|
||||
|
||||
def test_set_get_region_id(self):
|
||||
self.endp.setRegionId('region_id')
|
||||
self.assertEqual('region_id', self.endp.getRegionId())
|
||||
|
||||
def test_set_get_service_id(self):
|
||||
self.endp.setServiceId('service_id')
|
||||
self.assertEqual('service_id', self.endp.getServiceId())
|
||||
|
||||
def test_set_get_URL(self):
|
||||
self.endp.setURL('URL')
|
||||
self.assertEqual('URL', self.endp.getURL())
|
||||
|
||||
def test_set_isenable(self):
|
||||
self.endp.setEnabled('true')
|
||||
self.assertEqual('true', self.endp.isEnabled())
|
32
synergy_scheduler_manager/tests/unit/test_flavor.py
Executable file
32
synergy_scheduler_manager/tests/unit/test_flavor.py
Executable file
@ -0,0 +1,32 @@
|
||||
# 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.
|
||||
|
||||
from synergy_scheduler_manager.common.flavor import Flavor
|
||||
from synergy_scheduler_manager.tests.unit import base
|
||||
|
||||
|
||||
class TestFlavor(base.TestCase):
|
||||
def setUp(self):
|
||||
super(TestFlavor, self).setUp()
|
||||
self.flav = Flavor()
|
||||
|
||||
def test_set_get_VCPUs(self):
|
||||
self.flav.setVCPUs(2)
|
||||
self.assertEqual(2, self.flav.getVCPUs())
|
||||
|
||||
def test_set__get_Memory(self):
|
||||
self.flav.setMemory('memory')
|
||||
self.assertEqual('memory', self.flav.getMemory())
|
||||
|
||||
def test_set_get_Storage(self):
|
||||
self.flav.setMemory('storage')
|
||||
self.assertEqual('storage', self.flav.getMemory())
|
54
synergy_scheduler_manager/tests/unit/test_hypervisor.py
Normal file
54
synergy_scheduler_manager/tests/unit/test_hypervisor.py
Normal file
@ -0,0 +1,54 @@
|
||||
# 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.
|
||||
|
||||
from synergy_scheduler_manager.common.hypervisor import Hypervisor
|
||||
from synergy_scheduler_manager.tests.unit import base
|
||||
|
||||
|
||||
class TestHypervisor(base.TestCase):
|
||||
def setUp(self):
|
||||
super(TestHypervisor, self).setUp()
|
||||
self.hyp = Hypervisor()
|
||||
|
||||
def test_set_get_IP(self):
|
||||
self.hyp.setIP('ip')
|
||||
self.assertEqual('ip', self.hyp.getIP())
|
||||
|
||||
def test_set_get_State(self):
|
||||
self.hyp.setState('state')
|
||||
self.assertEqual('state', self.hyp.getState())
|
||||
|
||||
def test_set_get_Workload(self):
|
||||
self.assertEqual(0, self.hyp.getWorkload())
|
||||
self.hyp.setWorkload(8)
|
||||
self.assertEqual(8, self.hyp.getWorkload())
|
||||
|
||||
def test_set_get_VMs(self):
|
||||
self.assertEqual(0, self.hyp.getVMs())
|
||||
self.hyp.setVMs(3)
|
||||
self.assertEqual(3, self.hyp.getVMs())
|
||||
|
||||
def test_set_get_VCPUs(self):
|
||||
self.assertEqual(0, self.hyp.getVCPUs(False))
|
||||
self.assertEqual(0, self.hyp.getVCPUs(True))
|
||||
self.hyp.setVCPUs(3, False)
|
||||
self.hyp.setVCPUs(8, True)
|
||||
self.assertEqual(3, self.hyp.getVCPUs(False))
|
||||
self.assertEqual(8, self.hyp.getVCPUs(True))
|
||||
|
||||
def test_set_get_Memory(self):
|
||||
self.assertEqual(0, self.hyp.getMemory(False))
|
||||
self.assertEqual(0, self.hyp.getMemory(True))
|
||||
self.hyp.setMemory(1, False)
|
||||
self.hyp.setMemory(2, True)
|
||||
self.assertEqual(1, self.hyp.getMemory(False))
|
||||
self.assertEqual(2, self.hyp.getMemory(True))
|
39
synergy_scheduler_manager/tests/unit/test_priority.py
Normal file
39
synergy_scheduler_manager/tests/unit/test_priority.py
Normal file
@ -0,0 +1,39 @@
|
||||
# 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.
|
||||
|
||||
from datetime import datetime
|
||||
from synergy_scheduler_manager.common.priority import Priority
|
||||
from synergy_scheduler_manager.tests.unit import base
|
||||
|
||||
|
||||
class TestPriority(base.TestCase):
|
||||
def setUp(self):
|
||||
super(TestPriority, self).setUp()
|
||||
self.priority = Priority()
|
||||
|
||||
def test_set_get_Value(self):
|
||||
self.priority.setValue(1)
|
||||
self.assertEqual(1, self.priority.getValue())
|
||||
|
||||
def test_set_get_LastUpdate(self):
|
||||
self.assertNotEqual(datetime.utcnow(), self.priority.getLastUpdate())
|
||||
|
||||
def test_set_get_FairShare(self):
|
||||
self.assertEqual(0.00, self.priority.getFairShare('vcpus'))
|
||||
self.assertEqual(0.0, self.priority.getFairShare('memory'))
|
||||
self.assertEqual(0.0, self.priority.getFairShare('disk'))
|
||||
self.priority.setFairShare('vcpus', 2)
|
||||
self.assertEqual(2, self.priority.getFairShare('vcpus'))
|
||||
self.priority.setFairShare('memory', 5.6)
|
||||
self.assertEqual(5.6, self.priority.getFairShare('memory'))
|
||||
self.priority.setFairShare('disk', 0.1)
|
||||
self.assertEqual(0.1, self.priority.getFairShare('disk'))
|
71
synergy_scheduler_manager/tests/unit/test_project.py
Normal file
71
synergy_scheduler_manager/tests/unit/test_project.py
Normal file
@ -0,0 +1,71 @@
|
||||
# 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.
|
||||
|
||||
from synergy_scheduler_manager.common.project import Project
|
||||
from synergy_scheduler_manager.common.user import User
|
||||
from synergy_scheduler_manager.tests.unit import base
|
||||
|
||||
|
||||
class TestProject(base.TestCase):
|
||||
def setUp(self):
|
||||
super(TestProject, self).setUp()
|
||||
self.prj = Project()
|
||||
|
||||
def test_set_get_Data(self):
|
||||
self.assertEqual({}, self.prj.getData())
|
||||
|
||||
def test_get_Quota(self):
|
||||
sq = self.prj.getQuota()
|
||||
sq.setSize('memory', 1024, True)
|
||||
sq.setSize('vcpus', 100.00, True)
|
||||
sq.setSize('instances', 10, True)
|
||||
|
||||
self.assertEqual(1024, sq.getSize('memory'))
|
||||
self.assertEqual(100.0, sq.getSize('vcpus'))
|
||||
self.assertEqual(10, sq.getSize('instances'))
|
||||
|
||||
def test_get_Share(self):
|
||||
share = self.prj.getShare()
|
||||
self.assertEqual(0.0, share.getValue())
|
||||
self.assertEqual(0.00, share.getSiblingValue())
|
||||
self.assertEqual(0.000, share.getNormalizedValue())
|
||||
|
||||
def test_set_get_TTL(self):
|
||||
self.prj.setTTL(0.2)
|
||||
self.assertEqual(0.2, self.prj.getTTL())
|
||||
|
||||
def test_set_is_Enable(self):
|
||||
self.prj.setEnabled('True')
|
||||
self.assertEqual('True', self.prj.isEnabled())
|
||||
|
||||
def test_get_add_User(self):
|
||||
user1 = User()
|
||||
user1.setId('id1')
|
||||
user1.setName('name1')
|
||||
self.prj.addUser(user1)
|
||||
|
||||
user2 = User()
|
||||
user2.setId('id2')
|
||||
user2.setName('name2')
|
||||
self.prj.addUser(user2)
|
||||
|
||||
self.assertEqual('id1', self.prj.getUser('id1').getId())
|
||||
self.assertEqual('name1', self.prj.getUser('id1').getName())
|
||||
self.assertEqual('id2', self.prj.getUser('id2').getId())
|
||||
self.assertEqual('name2', self.prj.getUser('id2').getName())
|
||||
|
||||
def test_get_Users(self):
|
||||
user = User()
|
||||
user.setId('id1')
|
||||
user.setName('name')
|
||||
self.prj.addUser(user)
|
||||
self.assertEqual('name', self.prj.getUser('id1').getName())
|
242
synergy_scheduler_manager/tests/unit/test_queue.py
Normal file
242
synergy_scheduler_manager/tests/unit/test_queue.py
Normal file
@ -0,0 +1,242 @@
|
||||
# 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.
|
||||
import heapq
|
||||
from mock import call
|
||||
from mock import create_autospec
|
||||
from sqlalchemy.engine.base import Engine
|
||||
from synergy_scheduler_manager.common.queue import PriorityQueue
|
||||
from synergy_scheduler_manager.common.queue import QueueDB
|
||||
from synergy_scheduler_manager.common.queue import QueueItem
|
||||
from synergy_scheduler_manager.tests.unit import base
|
||||
|
||||
|
||||
class TestQueueItem(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestQueueItem, self).setUp()
|
||||
self.qitem = QueueItem(id=1,
|
||||
user_id=100,
|
||||
prj_id=1,
|
||||
priority=1000,
|
||||
retry_count=1,
|
||||
creation_time='now',
|
||||
last_update='now',
|
||||
data=1)
|
||||
|
||||
def test_get_set_id(self):
|
||||
self.assertEqual(1, self.qitem.getId())
|
||||
self.qitem.setId(8)
|
||||
self.assertEqual(8, self.qitem.getId())
|
||||
|
||||
def test_get_set_userid(self):
|
||||
self.assertEqual(100, self.qitem.getUserId())
|
||||
|
||||
self.qitem.setUserId(13)
|
||||
self.assertEqual(13, self.qitem.getUserId())
|
||||
|
||||
def test_get_set_projectid(self):
|
||||
self.assertEqual(1, self.qitem.getProjectId())
|
||||
|
||||
self.qitem.setProjectId(12)
|
||||
self.assertEqual(12, self.qitem.getProjectId())
|
||||
|
||||
def test_get_set_priority(self):
|
||||
self.assertEqual(1000, self.qitem.getPriority())
|
||||
|
||||
self.qitem.setPriority(10)
|
||||
self.assertEqual(10, self.qitem.getPriority())
|
||||
|
||||
def test_retry_count(self):
|
||||
self.assertEqual(1, self.qitem.getRetryCount())
|
||||
|
||||
self.qitem.setRetryCount(10)
|
||||
self.assertEqual(10, self.qitem.getRetryCount())
|
||||
|
||||
self.qitem.incRetryCount()
|
||||
self.assertEqual(11, self.qitem.getRetryCount())
|
||||
|
||||
def test_get_set_creation_time(self):
|
||||
self.assertEqual("now", self.qitem.getCreationTime())
|
||||
|
||||
self.qitem.setCreationTime("later")
|
||||
self.assertEqual("later", self.qitem.getCreationTime())
|
||||
|
||||
def test_get_set_last_update(self):
|
||||
self.assertEqual("now", self.qitem.getLastUpdate())
|
||||
|
||||
self.qitem.setLastUpdate("later")
|
||||
self.assertEqual("later", self.qitem.getLastUpdate())
|
||||
|
||||
def test_get_set_data(self):
|
||||
self.assertEqual(1, self.qitem.getData())
|
||||
|
||||
self.qitem.setData(2)
|
||||
self.assertEqual(2, self.qitem.getData())
|
||||
|
||||
|
||||
class TestPriorityQueue(base.TestCase):
|
||||
def setUp(self):
|
||||
super(TestPriorityQueue, self).setUp()
|
||||
self.pq = PriorityQueue()
|
||||
|
||||
def test_len(self):
|
||||
self.pq.put(1, "a")
|
||||
self.pq.put(3, "b")
|
||||
self.pq.put(10, "c")
|
||||
self.assertEqual(3, self.pq.__len__())
|
||||
|
||||
def test_iter(self):
|
||||
self.pq.put(1, "a")
|
||||
self.pq.put(3, "b")
|
||||
self.pq.put(10, "c")
|
||||
self.assertEqual('c', self.pq.__iter__().get())
|
||||
self.assertEqual('b', self.pq.__iter__().get())
|
||||
self.assertEqual('a', self.pq.__iter__().get())
|
||||
|
||||
def test_put_get(self):
|
||||
self.pq.put(1, "a")
|
||||
self.pq.put(3, "b")
|
||||
self.pq.put(10, "c")
|
||||
|
||||
self.assertEqual("c", self.pq.get())
|
||||
self.assertEqual("b", self.pq.get())
|
||||
self.assertEqual("a", self.pq.get())
|
||||
|
||||
def test_size(self):
|
||||
self.pq.put(1, "a")
|
||||
self.pq.put(3, "b")
|
||||
self.pq.put(10, "c")
|
||||
self.assertEqual(3, self.pq.size())
|
||||
|
||||
def test_items(self):
|
||||
self.pq.put(1, "a")
|
||||
self.pq.put(3, "b")
|
||||
self.pq.put(10, "c")
|
||||
self.assertEqual('c', self.pq.items()[0][2])
|
||||
|
||||
def test_smallest(self):
|
||||
self.pq.put(1, "a")
|
||||
self.pq.put(3, "b")
|
||||
self.pq.put(10, "c")
|
||||
self.assertEqual('c', self.pq.smallest(1)[0][2])
|
||||
|
||||
def test_largest(self):
|
||||
self.pq.put(1, "a")
|
||||
self.pq.put(3, "b")
|
||||
self.pq.put(10, "c")
|
||||
self.assertEqual('a', self.pq.largest(1)[0][2])
|
||||
|
||||
|
||||
class TestQueueDB(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestQueueDB, self).setUp()
|
||||
|
||||
# Create a Queue that mocks database interaction
|
||||
self.db_engine_mock = create_autospec(Engine)
|
||||
self.q = QueueDB(name="test", db_engine=self.db_engine_mock)
|
||||
|
||||
def test_get_name(self):
|
||||
self.assertEqual('test', self.q.getName())
|
||||
|
||||
def test_close(self):
|
||||
self.q.close()
|
||||
self.assertEqual(True, self.q.isClosed())
|
||||
|
||||
def test_insert_item(self):
|
||||
|
||||
self.q.insertItem(user_id=1, prj_id=2, priority=10, data="mydata")
|
||||
|
||||
# Check the db call of the item insert
|
||||
insert_call = call.connect().execute(
|
||||
'insert into `test` (user_id, prj_id, priority, data) '
|
||||
'values(%s, %s, %s, %s)', [1, 2, 10, '"mydata"'])
|
||||
self.assertIn(insert_call, self.db_engine_mock.mock_calls)
|
||||
|
||||
# Check the item existence and values in the in-memory queue
|
||||
priority, index, item = heapq.heappop(self.q.pqueue._heap)
|
||||
self.assertEqual(-10, priority)
|
||||
self.assertEqual(0, index)
|
||||
self.assertEqual(1, item.user_id)
|
||||
self.assertEqual(2, item.prj_id)
|
||||
self.assertEqual(10, item.priority)
|
||||
self.assertEqual(0, item.retry_count)
|
||||
self.assertIsNone(item.data) # TODO(vincent): should it be "mydata"?
|
||||
|
||||
def test_get_size(self):
|
||||
execute_mock = self.db_engine_mock.connect().execute
|
||||
execute_call = call('select count(*) from `test`')
|
||||
|
||||
fetchone_mock = execute_mock().fetchone
|
||||
fetchone_mock.return_value = [3]
|
||||
|
||||
# Check that getSize() uses the correct sqlalchemy method
|
||||
self.assertEqual(3, self.q.getSize())
|
||||
|
||||
# Check that getSize() uses the correct SQL statement
|
||||
self.assertEqual(execute_call, execute_mock.call_args)
|
||||
|
||||
def test_get_item(self):
|
||||
# Insert the item and mock its DB insertion
|
||||
execute_mock = self.db_engine_mock.connect().execute
|
||||
execute_mock().lastrowid = 123
|
||||
self.q.insertItem(user_id=1, prj_id=2, priority=10, data="mydata")
|
||||
|
||||
# Mock the DB select by returning the same things we inserted before
|
||||
select_mock = self.db_engine_mock.connect().execute
|
||||
select_call = call("select user_id, prj_id, priority, retry_count, "
|
||||
"creation_time, last_update, data from `test` "
|
||||
"where id=%s", [123])
|
||||
fetchone_mock = select_mock().fetchone
|
||||
fetchone_mock.return_value = [1, 2, 10, 0, "now", "now", '"mydata"']
|
||||
|
||||
item = self.q.getItem()
|
||||
self.assertEqual(select_call, select_mock.call_args)
|
||||
self.assertEqual(123, item.id)
|
||||
self.assertEqual(1, item.user_id)
|
||||
self.assertEqual(2, item.prj_id)
|
||||
self.assertEqual(10, item.priority)
|
||||
self.assertEqual(0, item.retry_count)
|
||||
self.assertEqual("now", item.creation_time)
|
||||
self.assertEqual("now", item.last_update)
|
||||
self.assertEqual("mydata", item.data)
|
||||
|
||||
def test_delete_item(self):
|
||||
# Mock QueueItem to be deleted
|
||||
qitem = create_autospec(QueueItem)
|
||||
qitem.getId.return_value = 123
|
||||
|
||||
# Mock the DB delete
|
||||
execute_mock = self.db_engine_mock.connect().execute
|
||||
execute_call = call("delete from `test` where id=%s", [123])
|
||||
|
||||
self.q.deleteItem(qitem)
|
||||
self.assertEqual(execute_call, execute_mock.call_args)
|
||||
|
||||
def test_update_item(self):
|
||||
# Mock QueueItem to be updated
|
||||
qitem = create_autospec(QueueItem)
|
||||
qitem.getPriority.return_value = 10
|
||||
qitem.getRetryCount.return_value = 20
|
||||
qitem.getLastUpdate.return_value = "right_now"
|
||||
qitem.getId.return_value = 123
|
||||
|
||||
# Mock the DB update
|
||||
execute_mock = self.db_engine_mock.connect().execute
|
||||
execute_call = call("update `test` set priority=%s, retry_count=%s, "
|
||||
"last_update=%s where id=%s",
|
||||
[10, 20, "right_now", 123])
|
||||
|
||||
# Check the DB call and that the new QueueItem is in the queue
|
||||
self.q.updateItem(qitem)
|
||||
self.assertEqual(execute_call, execute_mock.call_args)
|
||||
self.assertIn((-10, 0, qitem), self.q.pqueue._heap)
|
200
synergy_scheduler_manager/tests/unit/test_quota.py
Normal file
200
synergy_scheduler_manager/tests/unit/test_quota.py
Normal file
@ -0,0 +1,200 @@
|
||||
# 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.
|
||||
|
||||
from synergy_scheduler_manager.common.flavor import Flavor
|
||||
from synergy_scheduler_manager.common.quota import Quota
|
||||
from synergy_scheduler_manager.common.quota import SharedQuota
|
||||
from synergy_scheduler_manager.common.server import Server
|
||||
from synergy_scheduler_manager.tests.unit import base
|
||||
|
||||
|
||||
class TestQuota(base.TestCase):
|
||||
def setUp(self):
|
||||
super(TestQuota, self).setUp()
|
||||
self.quota = Quota()
|
||||
|
||||
def test_get_set_Type(self):
|
||||
self.quota.setType('Type')
|
||||
self.assertEqual('Type', self.quota.getType())
|
||||
|
||||
def test_get_Servers(self):
|
||||
self.assertEqual([], self.quota.getServers('active', private=True))
|
||||
self.assertEqual([], self.quota.getServers('building', private=True))
|
||||
self.assertEqual([], self.quota.getServers('error', private=True))
|
||||
|
||||
self.assertEqual([], self.quota.getServers('active', private=False))
|
||||
self.assertEqual([], self.quota.getServers('building', private=False))
|
||||
self.assertEqual([], self.quota.getServers('error', private=False))
|
||||
|
||||
def test_Reset(self):
|
||||
self.quota.reset()
|
||||
self.assertEqual(0.0, self.quota.get('private')[
|
||||
'resources']['memory']['used'])
|
||||
self.assertEqual(0.0, self.quota.get('private')[
|
||||
'resources']['memory']['used'])
|
||||
self.assertEqual(0.0, self.quota.get('private')[
|
||||
'resources']['memory']['used'])
|
||||
|
||||
def test_set_get_Size(self):
|
||||
self.quota.setSize('memory', 1024, private=True)
|
||||
self.quota.setSize('vcpus', 100.00, private=True)
|
||||
self.quota.setSize('instances', 10, private=True)
|
||||
|
||||
self.assertEqual(1024, self.quota.getSize('memory', private=True))
|
||||
self.assertEqual(100.0, self.quota.getSize('vcpus', private=True))
|
||||
self.assertEqual(10, self.quota.getSize('instances', private=True))
|
||||
|
||||
self.quota.setSize('memory', 1, private=False)
|
||||
self.quota.setSize('vcpus', 11, private=False)
|
||||
self.quota.setSize('instances', 111, private=False)
|
||||
|
||||
self.assertEqual(1, self.quota.getSize('memory', private=False))
|
||||
self.assertEqual(11, self.quota.getSize('vcpus', private=False))
|
||||
self.assertEqual(111, self.quota.getSize('instances', private=False))
|
||||
|
||||
def test_set_get_Usage(self):
|
||||
self.quota.setUsage('memory', 1024, private=True)
|
||||
self.quota.setUsage('vcpus', 100.00, private=True)
|
||||
self.quota.setUsage('instances', 10, private=True)
|
||||
|
||||
self.assertEqual(1024, self.quota.getUsage('memory', private=True))
|
||||
self.assertEqual(100.0, self.quota.getUsage('vcpus', private=True))
|
||||
self.assertEqual(10, self.quota.getUsage('instances', private=True))
|
||||
|
||||
self.quota.setUsage('memory', 1024, private=False)
|
||||
self.quota.setUsage('vcpus', 100.00, private=False)
|
||||
self.quota.setUsage('instances', 10, private=False)
|
||||
|
||||
self.assertEqual(1024, self.quota.getUsage('memory', private=False))
|
||||
self.assertEqual(100.0, self.quota.getUsage('vcpus', private=False))
|
||||
self.assertEqual(10, self.quota.getUsage('instances', private=False))
|
||||
|
||||
self.quota.reset()
|
||||
self.assertEqual(0, self.quota.getUsage('memory', private=True))
|
||||
self.assertEqual(0, self.quota.getUsage('vcpus', private=True))
|
||||
self.assertEqual(0, self.quota.getUsage('instances', private=True))
|
||||
|
||||
def test_Allocate(self):
|
||||
self.quota.setSize("vcpus", 10, private=True)
|
||||
self.quota.setSize("memory", 2048, private=True)
|
||||
|
||||
flavor = Flavor()
|
||||
flavor.setVCPUs(3)
|
||||
flavor.setMemory(1024)
|
||||
|
||||
server = Server()
|
||||
server.setId("test_id")
|
||||
server.setFlavor(flavor)
|
||||
found = self.quota.allocate(server, blocking=False)
|
||||
self.assertEqual(3, self.quota.getUsage('vcpus', private=True))
|
||||
self.assertEqual(1024, self.quota.getUsage('memory', private=True))
|
||||
self.assertEqual(True, found)
|
||||
|
||||
def test_release(self):
|
||||
self.quota.setSize("vcpus", 10, private=True)
|
||||
self.quota.setSize("memory", 2048, private=True)
|
||||
|
||||
flavor = Flavor()
|
||||
flavor.setVCPUs(3)
|
||||
flavor.setMemory(1024)
|
||||
|
||||
server = Server()
|
||||
server.setId("test_id")
|
||||
server.setFlavor(flavor)
|
||||
self.quota.release(server)
|
||||
self.assertEqual(0, self.quota.getUsage('vcpus', True))
|
||||
self.assertEqual(0, self.quota.getUsage('memory', True))
|
||||
|
||||
|
||||
class TestSharedQuota(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestSharedQuota, self).setUp()
|
||||
self.quota = Quota()
|
||||
|
||||
def test_enabled_disable(self):
|
||||
SharedQuota.enable()
|
||||
self.assertEqual(True, SharedQuota.isEnabled())
|
||||
SharedQuota.disable()
|
||||
self.assertEqual(False, SharedQuota.isEnabled())
|
||||
|
||||
def test_set_get_Size(self):
|
||||
SharedQuota.setSize("vcpus", 1024)
|
||||
SharedQuota.setSize("memory", 2048)
|
||||
SharedQuota.setSize("instances", 10)
|
||||
|
||||
self.assertEqual(1024, SharedQuota.getSize('vcpus'))
|
||||
self.assertEqual(2048, SharedQuota.getSize('memory'))
|
||||
self.assertEqual(10, SharedQuota.getSize('instances'))
|
||||
|
||||
def test_set_get_Usage(self):
|
||||
SharedQuota.setUsage('memory', 1024)
|
||||
SharedQuota.setUsage('vcpus', 30)
|
||||
self.assertEqual(1024, SharedQuota.getUsage('memory'))
|
||||
self.assertEqual(30, SharedQuota.getUsage('vcpus'))
|
||||
|
||||
def test_Allocate_Release(self):
|
||||
SharedQuota.enable()
|
||||
SharedQuota.setSize("vcpus", 20)
|
||||
SharedQuota.setSize("memory", 4086)
|
||||
|
||||
self.quota.setSize("vcpus", 10)
|
||||
self.quota.setSize("memory", 2048)
|
||||
|
||||
flavor1 = Flavor()
|
||||
flavor1.setVCPUs(2)
|
||||
flavor1.setMemory(2)
|
||||
|
||||
server1 = Server()
|
||||
server1.setId("test_id1")
|
||||
server1.setType("ephemeral")
|
||||
|
||||
server1.setFlavor(flavor1)
|
||||
self.quota.allocate(server1, blocking=False)
|
||||
|
||||
self.assertEqual(2, SharedQuota.getUsage('memory'))
|
||||
self.assertEqual(2, SharedQuota.getUsage('vcpus'))
|
||||
self.assertEqual(0, self.quota.getUsage("memory", private=True))
|
||||
self.assertEqual(0, self.quota.getUsage("vcpus", private=True))
|
||||
|
||||
flavor2 = Flavor()
|
||||
flavor2.setVCPUs(3)
|
||||
flavor2.setMemory(3)
|
||||
|
||||
server2 = Server()
|
||||
server2.setId("test_id2")
|
||||
server2.setType("permanent")
|
||||
|
||||
server2.setFlavor(flavor2)
|
||||
|
||||
self.quota.allocate(server2, blocking=False)
|
||||
|
||||
self.assertEqual(2, SharedQuota.getUsage('memory'))
|
||||
self.assertEqual(2, SharedQuota.getUsage('vcpus'))
|
||||
self.assertEqual(3, self.quota.getUsage("memory", private=True))
|
||||
self.assertEqual(3, self.quota.getUsage("vcpus", private=True))
|
||||
|
||||
self.assertEqual(2, self.quota.getUsage("memory", private=False))
|
||||
self.assertEqual(2, self.quota.getUsage("vcpus", private=False))
|
||||
|
||||
self.quota.release(server1)
|
||||
|
||||
self.assertEqual(0, SharedQuota.getUsage('memory'))
|
||||
self.assertEqual(0, SharedQuota.getUsage('vcpus'))
|
||||
|
||||
self.assertEqual(0, self.quota.getUsage("vcpus", private=False))
|
||||
self.assertEqual(0, self.quota.getUsage("vcpus", private=False))
|
||||
|
||||
self.quota.release(server2)
|
||||
|
||||
self.assertEqual(0, self.quota.getUsage("vcpus", private=True))
|
||||
self.assertEqual(0, self.quota.getUsage("vcpus", private=True))
|
431
synergy_scheduler_manager/tests/unit/test_request.py
Normal file
431
synergy_scheduler_manager/tests/unit/test_request.py
Normal file
@ -0,0 +1,431 @@
|
||||
# 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.
|
||||
|
||||
from synergy_scheduler_manager.common.request import Request
|
||||
from synergy_scheduler_manager.tests.unit import base
|
||||
|
||||
|
||||
class TestRequest(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestRequest, self).setUp()
|
||||
|
||||
req_dict = {
|
||||
'legacy_bdm': True,
|
||||
'requested_networks': None,
|
||||
'injected_files': [],
|
||||
'block_device_mapping': None,
|
||||
'image': {
|
||||
u'status': u'active',
|
||||
u'created_at': u'2016-03-23T16:47:10.000000',
|
||||
u'name': u'cirros',
|
||||
u'deleted': False,
|
||||
u'container_format': u'bare',
|
||||
u'min_ram': 0,
|
||||
u'disk_format': u'qcow2',
|
||||
u'updated_at': u'2016-03-23T16:47:10.000000',
|
||||
u'properties': {},
|
||||
u'owner': u'1a6edd87f9ec41d8aa64c8f23d719c2a',
|
||||
u'checksum': u'ee1eca47dc88f4879d8a229cc70a07c6',
|
||||
u'min_disk': 0,
|
||||
u'is_public': True,
|
||||
u'deleted_at': None,
|
||||
u'id': u'5100f480-a40c-46cd-b8b6-ea2e5e7bf09e',
|
||||
u'size': 13287936},
|
||||
'filter_properties': {
|
||||
u'instance_type': {
|
||||
u'nova_object.version': u'1.1',
|
||||
u'nova_object.name': u'Flavor',
|
||||
u'nova_object.namespace': u'nova',
|
||||
u'nova_object.data': {
|
||||
u'memory_mb': 512,
|
||||
u'root_gb': 1,
|
||||
u'deleted_at': None,
|
||||
u'name': u'm1.tiny',
|
||||
u'deleted': False,
|
||||
u'created_at': None,
|
||||
u'ephemeral_gb': 0,
|
||||
u'updated_at': None,
|
||||
u'disabled': False,
|
||||
u'vcpus': 1,
|
||||
u'extra_specs': {},
|
||||
u'swap': 0,
|
||||
u'rxtx_factor': 1.0,
|
||||
u'is_public': True,
|
||||
u'flavorid': u'1',
|
||||
u'vcpu_weight': 0,
|
||||
u'id': 2}},
|
||||
u'scheduler_hints': {}},
|
||||
'instance': {
|
||||
u'nova_object.version': u'2.0',
|
||||
u'nova_object.name': u'Instance',
|
||||
u'nova_object.namespace': u'nova',
|
||||
u'nova_object.data': {
|
||||
u'vm_state': u'building',
|
||||
u'pci_requests': {
|
||||
u'nova_object.version': u'1.1',
|
||||
u'nova_object.name': u'InstancePCIRequests',
|
||||
u'nova_object.namespace': u'nova',
|
||||
u'nova_object.data': {
|
||||
u'instance_uuid': u'e3a7770a-8875e2ccc68b',
|
||||
u'requests': []}},
|
||||
u'availability_zone': None,
|
||||
u'terminated_at': None,
|
||||
u'ephemeral_gb': 0,
|
||||
u'instance_type_id': 2,
|
||||
u'user_data': None,
|
||||
u'numa_topology': None,
|
||||
u'cleaned': False,
|
||||
u'vm_mode': None,
|
||||
u'flavor': {
|
||||
u'nova_object.version': u'1.1',
|
||||
u'nova_object.name': u'Flavor',
|
||||
u'nova_object.namespace': u'nova',
|
||||
u'nova_object.data': {
|
||||
u'memory_mb': 512,
|
||||
u'root_gb': 1,
|
||||
u'deleted_at': None,
|
||||
u'name': u'm1.tiny',
|
||||
u'deleted': False,
|
||||
u'created_at': None,
|
||||
u'ephemeral_gb': 0,
|
||||
u'updated_at': None,
|
||||
u'disabled': False,
|
||||
u'vcpus': 1,
|
||||
u'extra_specs': {},
|
||||
u'swap': 0,
|
||||
u'rxtx_factor': 1.0,
|
||||
u'is_public': True,
|
||||
u'flavorid': u'1',
|
||||
u'vcpu_weight': 0,
|
||||
u'id': 2}},
|
||||
u'deleted_at': None,
|
||||
u'reservation_id': u'r-s9v032d0',
|
||||
u'id': 830,
|
||||
u'security_groups': {
|
||||
u'nova_object.version': u'1.0',
|
||||
u'nova_object.name': u'SecurityGroupList',
|
||||
u'nova_object.namespace': u'nova',
|
||||
u'nova_object.data': {
|
||||
u'objects': []}},
|
||||
u'disable_terminate': False,
|
||||
u'root_device_name': None,
|
||||
u'display_name': u'user_b1',
|
||||
u'uuid': u'e3a7770a-dbf6-4b63-8f9a-8875e2ccc68b',
|
||||
u'default_swap_device': None,
|
||||
u'info_cache': {
|
||||
u'nova_object.version': u'1.5',
|
||||
u'nova_object.name': u'InstanceInfoCache',
|
||||
u'nova_object.namespace': u'nova',
|
||||
u'nova_object.data': {
|
||||
u'instance_uuid': u'e3a7-8875e2ccc68b',
|
||||
u'deleted': False,
|
||||
u'created_at': u'2016-09-02T14:01:39Z',
|
||||
u'updated_at': None,
|
||||
u'network_info': u'[]',
|
||||
u'deleted_at': None}},
|
||||
u'hostname': u'user-b1',
|
||||
u'launched_on': None,
|
||||
u'display_description': u'user_b1',
|
||||
u'key_data': None,
|
||||
u'deleted': False,
|
||||
u'power_state': 0,
|
||||
u'key_name': None,
|
||||
u'default_ephemeral_device': None,
|
||||
u'progress': 0,
|
||||
u'project_id': u'd20ac1ffa60841a78a865da63b2399de',
|
||||
u'launched_at': None,
|
||||
u'metadata': {
|
||||
u'quota': u'dynamic',
|
||||
u'persistent': u'False'},
|
||||
u'node': None,
|
||||
u'ramdisk_id': u'',
|
||||
u'access_ip_v6': None,
|
||||
u'access_ip_v4': None,
|
||||
u'kernel_id': u'',
|
||||
u'old_flavor': None,
|
||||
u'updated_at': None,
|
||||
u'host': None,
|
||||
u'root_gb': 1,
|
||||
u'user_id': u'4cb9f71a47914d0c8b78a471fd8f7015',
|
||||
u'system_metadata': {
|
||||
u'image_min_disk': u'1',
|
||||
u'image_min_ram': u'0',
|
||||
u'image_disk_format': u'qcow2',
|
||||
u'image_base_image_ref': u'5100f480-a25e7bf09e',
|
||||
u'image_container_format': u'bare'},
|
||||
u'task_state': u'scheduling',
|
||||
u'shutdown_terminate': False,
|
||||
u'cell_name': None,
|
||||
u'ephemeral_key_uuid': None,
|
||||
u'locked': False,
|
||||
u'created_at': u'2016-09-02T14:01:39Z',
|
||||
u'locked_by': None,
|
||||
u'launch_index': 0,
|
||||
u'memory_mb': 512,
|
||||
u'vcpus': 1,
|
||||
u'image_ref': u'a40c-46cd-b8b6-ea2e5e7bf09e',
|
||||
u'architecture': None,
|
||||
u'auto_disk_config': False,
|
||||
u'os_type': None,
|
||||
u'config_drive': u'',
|
||||
u'new_flavor': None}},
|
||||
'admin_password': u'URijD456Cezi',
|
||||
'context': {
|
||||
u'domain': None,
|
||||
u'project_domain': None,
|
||||
u'auth_token': u'f9d8458ef4ae454dad75f4636304079c',
|
||||
u'resource_uuid': None,
|
||||
u'read_only': False,
|
||||
u'user_id': u'4cb9f71a47914d0c8b78a471fd8f7015',
|
||||
u'user_identity': u'fa60841a78a865da63b2399de - - -',
|
||||
u'tenant': u'd20ac1ffa60841a78a865da63b2399de',
|
||||
u'instance_lock_checked': False,
|
||||
u'project_id': u'd20ac1ffa60841a78a865da63b2399de',
|
||||
u'user_name': u'user_b1',
|
||||
u'project_name': u'prj_b',
|
||||
u'timestamp': u'2016-09-02T14:01:39.284558',
|
||||
u'remote_address': u'10.64.31.19',
|
||||
u'quota_class': None,
|
||||
u'is_admin': False,
|
||||
u'user': u'4cb9f71a47914d0c8b78a471fd8f7015',
|
||||
u'service_catalog': [],
|
||||
u'read_deleted': u'no',
|
||||
u'show_deleted': False,
|
||||
u'roles': [u'user'],
|
||||
u'request_id': u'req-69c9e7e6-62b2fee1d6e8',
|
||||
u'user_domain': None},
|
||||
'security_groups': [u'default']}
|
||||
|
||||
self.req = Request.fromDict(req_dict)
|
||||
|
||||
def test_get_AdminPassword(self):
|
||||
self.assertEqual(u'URijD456Cezi', self.req.getAdminPassword())
|
||||
|
||||
def test_get_Id(self):
|
||||
self.assertEqual(
|
||||
u'e3a7770a-dbf6-4b63-8f9a-8875e2ccc68b',
|
||||
self.req.getId())
|
||||
|
||||
def test_get_Instance(self):
|
||||
ist = {
|
||||
u'nova_object.data': {
|
||||
u'access_ip_v4': None,
|
||||
u'access_ip_v6': None,
|
||||
u'architecture': None,
|
||||
u'auto_disk_config': False,
|
||||
u'availability_zone': None,
|
||||
u'cell_name': None,
|
||||
u'cleaned': False,
|
||||
u'config_drive': u'',
|
||||
u'created_at': u'2016-09-02T14:01:39Z',
|
||||
u'default_ephemeral_device': None,
|
||||
u'default_swap_device': None,
|
||||
u'deleted': False,
|
||||
u'deleted_at': None,
|
||||
u'disable_terminate': False,
|
||||
u'display_description': u'user_b1',
|
||||
u'display_name': u'user_b1',
|
||||
u'ephemeral_gb': 0,
|
||||
u'ephemeral_key_uuid': None,
|
||||
u'flavor': {
|
||||
u'nova_object.data': {
|
||||
u'created_at': None,
|
||||
u'deleted': False,
|
||||
u'deleted_at': None,
|
||||
u'disabled': False,
|
||||
u'ephemeral_gb': 0,
|
||||
u'extra_specs': {},
|
||||
u'flavorid': u'1',
|
||||
u'id': 2,
|
||||
u'is_public': True,
|
||||
u'memory_mb': 512,
|
||||
u'name': u'm1.tiny',
|
||||
u'root_gb': 1,
|
||||
u'rxtx_factor': 1.0,
|
||||
u'swap': 0,
|
||||
u'updated_at': None,
|
||||
u'vcpu_weight': 0,
|
||||
u'vcpus': 1},
|
||||
u'nova_object.name': u'Flavor',
|
||||
u'nova_object.namespace': u'nova',
|
||||
u'nova_object.version': u'1.1'},
|
||||
u'host': None,
|
||||
u'hostname': u'user-b1',
|
||||
u'id': 830,
|
||||
u'image_ref': u'a40c-46cd-b8b6-ea2e5e7bf09e',
|
||||
u'info_cache': {
|
||||
u'nova_object.data': {
|
||||
u'created_at': u'2016-09-02T14:01:39Z',
|
||||
u'deleted': False,
|
||||
u'deleted_at': None,
|
||||
u'instance_uuid': u'e3a7-8875e2ccc68b',
|
||||
u'network_info': u'[]',
|
||||
u'updated_at': None},
|
||||
u'nova_object.name': u'InstanceInfoCache',
|
||||
u'nova_object.namespace': u'nova',
|
||||
u'nova_object.version': u'1.5'},
|
||||
u'instance_type_id': 2,
|
||||
u'kernel_id': u'',
|
||||
u'key_data': None,
|
||||
u'key_name': None,
|
||||
u'launch_index': 0,
|
||||
u'launched_at': None,
|
||||
u'launched_on': None,
|
||||
u'locked': False,
|
||||
u'locked_by': None,
|
||||
u'memory_mb': 512,
|
||||
u'metadata': {
|
||||
u'persistent': u'False',
|
||||
u'quota': u'dynamic'},
|
||||
u'new_flavor': None,
|
||||
u'node': None,
|
||||
u'numa_topology': None,
|
||||
u'old_flavor': None,
|
||||
u'os_type': None,
|
||||
u'pci_requests': {
|
||||
u'nova_object.data': {
|
||||
u'instance_uuid': u'e3a7770a-8875e2ccc68b',
|
||||
u'requests': []},
|
||||
u'nova_object.name': u'InstancePCIRequests',
|
||||
u'nova_object.namespace': u'nova',
|
||||
u'nova_object.version': u'1.1'},
|
||||
u'power_state': 0,
|
||||
u'progress': 0,
|
||||
u'project_id': u'd20ac1ffa60841a78a865da63b2399de',
|
||||
u'ramdisk_id': u'',
|
||||
u'reservation_id': u'r-s9v032d0',
|
||||
u'root_device_name': None,
|
||||
u'root_gb': 1,
|
||||
u'security_groups': {
|
||||
u'nova_object.data': {
|
||||
u'objects': []},
|
||||
u'nova_object.name': u'SecurityGroupList',
|
||||
u'nova_object.namespace': u'nova',
|
||||
u'nova_object.version': u'1.0'},
|
||||
u'shutdown_terminate': False,
|
||||
u'system_metadata': {
|
||||
u'image_base_image_ref': u'5100f480-a25e7bf09e',
|
||||
u'image_container_format': u'bare',
|
||||
u'image_disk_format': u'qcow2',
|
||||
u'image_min_disk': u'1',
|
||||
u'image_min_ram': u'0'},
|
||||
u'task_state': u'scheduling',
|
||||
u'terminated_at': None,
|
||||
u'updated_at': None,
|
||||
u'user_data': None,
|
||||
u'user_id': u'4cb9f71a47914d0c8b78a471fd8f7015',
|
||||
u'uuid': u'e3a7770a-dbf6-4b63-8f9a-8875e2ccc68b',
|
||||
u'vcpus': 1,
|
||||
u'vm_mode': None,
|
||||
u'vm_state': u'building'},
|
||||
u'nova_object.name': u'Instance',
|
||||
u'nova_object.namespace': u'nova',
|
||||
u'nova_object.version': u'2.0'}
|
||||
|
||||
self.assertEqual(ist, self.req.getInstance())
|
||||
|
||||
def test_get_Image(self):
|
||||
im = {u'checksum': u'ee1eca47dc88f4879d8a229cc70a07c6',
|
||||
u'container_format': u'bare',
|
||||
u'created_at': u'2016-03-23T16:47:10.000000',
|
||||
u'deleted': False,
|
||||
u'deleted_at': None,
|
||||
u'disk_format': u'qcow2',
|
||||
u'id': u'5100f480-a40c-46cd-b8b6-ea2e5e7bf09e',
|
||||
u'is_public': True,
|
||||
u'min_disk': 0,
|
||||
u'min_ram': 0,
|
||||
u'name': u'cirros',
|
||||
u'owner': u'1a6edd87f9ec41d8aa64c8f23d719c2a',
|
||||
u'properties': {},
|
||||
u'size': 13287936,
|
||||
u'status': u'active',
|
||||
u'updated_at': u'2016-03-23T16:47:10.000000'}
|
||||
|
||||
self.assertEqual(im, self.req.getImage())
|
||||
|
||||
def test_get_Context(self):
|
||||
cont = {u'auth_token': u'f9d8458ef4ae454dad75f4636304079c',
|
||||
u'domain': None,
|
||||
u'instance_lock_checked': False,
|
||||
u'is_admin': False,
|
||||
u'project_domain': None,
|
||||
u'project_id': u'd20ac1ffa60841a78a865da63b2399de',
|
||||
u'project_name': u'prj_b',
|
||||
u'quota_class': None,
|
||||
u'read_deleted': u'no',
|
||||
u'read_only': False,
|
||||
u'remote_address': u'10.64.31.19',
|
||||
u'request_id': u'req-69c9e7e6-62b2fee1d6e8',
|
||||
u'resource_uuid': None,
|
||||
u'roles': [u'user'],
|
||||
u'service_catalog': [],
|
||||
u'show_deleted': False,
|
||||
u'tenant': u'd20ac1ffa60841a78a865da63b2399de',
|
||||
u'timestamp': u'2016-09-02T14:01:39.284558',
|
||||
u'user': u'4cb9f71a47914d0c8b78a471fd8f7015',
|
||||
u'user_domain': None,
|
||||
u'user_id': u'4cb9f71a47914d0c8b78a471fd8f7015',
|
||||
u'user_identity': u'fa60841a78a865da63b2399de - - -',
|
||||
u'user_name': u'user_b1'}
|
||||
|
||||
self.assertEqual(cont, self.req.getContext())
|
||||
|
||||
def test_get_FilterProperties(self):
|
||||
filt = {u'instance_type': {
|
||||
u'nova_object.data': {u'created_at': None,
|
||||
u'deleted': False,
|
||||
u'deleted_at': None,
|
||||
u'disabled': False,
|
||||
u'ephemeral_gb': 0,
|
||||
u'extra_specs': {},
|
||||
u'flavorid': u'1',
|
||||
u'id': 2,
|
||||
u'is_public': True,
|
||||
u'memory_mb': 512,
|
||||
u'name': u'm1.tiny',
|
||||
u'root_gb': 1,
|
||||
u'rxtx_factor': 1.0,
|
||||
u'swap': 0,
|
||||
u'updated_at': None,
|
||||
u'vcpu_weight': 0,
|
||||
u'vcpus': 1},
|
||||
u'nova_object.name': u'Flavor',
|
||||
u'nova_object.namespace': u'nova',
|
||||
u'nova_object.version': u'1.1'},
|
||||
u'scheduler_hints': {}}
|
||||
|
||||
self.assertEqual(filt, self.req.getFilterProperties())
|
||||
|
||||
def test_get_InjectedFiles(self):
|
||||
self.assertEqual([], self.req.getInjectedFiles())
|
||||
|
||||
def test_get_RequestedNetworks(self):
|
||||
self.assertEqual(None, self.req.getRequestedNetworks())
|
||||
|
||||
def test_get_SecurityGroups(self):
|
||||
self.assertEqual([u'default'], self.req.getSecurityGroups())
|
||||
|
||||
def test_get_BlockDeviceMapping(self):
|
||||
self.assertEqual(None, self.req.getBlockDeviceMapping())
|
||||
|
||||
def test_get_LegacyBDM(self):
|
||||
self.assertEqual(True, self.req.getLegacyBDM())
|
||||
|
||||
def test_get_Server(self):
|
||||
prjId = self.req.getServer().getProjectId()
|
||||
self.assertEqual('d20ac1ffa60841a78a865da63b2399de', prjId)
|
||||
|
||||
def test_from_to_Dict(self):
|
||||
rq_dict = self.req.toDict()
|
||||
self.assertEqual(True, rq_dict['legacy_bdm'])
|
79
synergy_scheduler_manager/tests/unit/test_server.py
Normal file
79
synergy_scheduler_manager/tests/unit/test_server.py
Normal file
@ -0,0 +1,79 @@
|
||||
# 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.
|
||||
|
||||
from datetime import datetime
|
||||
from synergy_scheduler_manager.common.server import Server
|
||||
from synergy_scheduler_manager.tests.unit import base
|
||||
|
||||
|
||||
class TestServer(base.TestCase):
|
||||
def setUp(self):
|
||||
super(TestServer, self).setUp()
|
||||
self.server = Server()
|
||||
|
||||
def test_set_get_Type(self):
|
||||
self.server.setType('type')
|
||||
self.assertEqual('type', self.server.getType())
|
||||
|
||||
def test_set_get_State(self):
|
||||
self.server.setState('state')
|
||||
self.assertEqual('state', self.server.getState())
|
||||
|
||||
def test_set_get_Flavor(self):
|
||||
self.server.setFlavor('flavor')
|
||||
self.assertEqual('flavor', self.server.getFlavor())
|
||||
|
||||
def test_set_get_KeyName(self):
|
||||
self.server.setKeyName('keyname')
|
||||
self.assertEqual('keyname', self.server.getKeyName())
|
||||
|
||||
def test_set_get_Metadata(self):
|
||||
self.server.setMetadata('metadata')
|
||||
self.assertEqual('metadata', self.server.getMetadata())
|
||||
|
||||
def test_set_get_UserId(self):
|
||||
self.server.setUserId('user_id')
|
||||
self.assertEqual('user_id', self.server.getUserId())
|
||||
|
||||
def test_set_get_ProjectId(self):
|
||||
self.server.setProjectId('project_id')
|
||||
self.assertEqual('project_id', self.server.getProjectId())
|
||||
|
||||
def test_set_get_CreatedAt(self):
|
||||
self.server.setCreatedAt('2015-02-10T13:00:10Z')
|
||||
str_date = '2015-02-10T13:00:10Z'
|
||||
datetime_date = datetime.strptime(str_date, "%Y-%m-%dT%H:%M:%SZ")
|
||||
self.assertEqual(datetime_date, self.server.getCreatedAt())
|
||||
|
||||
def test_set_get_LaunchedAt(self):
|
||||
self.server.setLaunchedAt('2015-02-10T13:00:10Z')
|
||||
str_date = '2015-02-10T13:00:10Z'
|
||||
datetime_date = datetime.strptime(str_date, "%Y-%m-%dT%H:%M:%SZ")
|
||||
self.assertEqual(datetime_date, self.server.getLaunchedAt())
|
||||
|
||||
def test_set_get_UpdatedAt(self):
|
||||
self.server.setUpdatedAt('2015-02-10T13:00:10Z')
|
||||
str_date = '2015-02-10T13:00:10Z'
|
||||
datetime_date = datetime.strptime(str_date, "%Y-%m-%dT%H:%M:%SZ")
|
||||
self.assertEqual(datetime_date, self.server.getUpdatedAt())
|
||||
|
||||
def test_set_get_TerminatedAt(self):
|
||||
self.server.setTerminatedAt('2015-02-10T13:00:10Z')
|
||||
str_date = '2015-02-10T13:00:10Z'
|
||||
datetime_date = datetime.strptime(str_date, "%Y-%m-%dT%H:%M:%SZ")
|
||||
self.assertEqual(datetime_date, self.server.getTerminatedAt())
|
||||
|
||||
def test_is_Ephemeral(self):
|
||||
self.assertEqual(False, self.server.isEphemeral())
|
||||
|
||||
def test_is_Permanent(self):
|
||||
self.assertEqual(True, self.server.isPermanent())
|
41
synergy_scheduler_manager/tests/unit/test_service.py
Normal file
41
synergy_scheduler_manager/tests/unit/test_service.py
Normal file
@ -0,0 +1,41 @@
|
||||
# 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.
|
||||
|
||||
from synergy_scheduler_manager.common.service import Service
|
||||
from synergy_scheduler_manager.tests.unit import base
|
||||
|
||||
|
||||
class TestService(base.TestCase):
|
||||
def setUp(self):
|
||||
super(TestService, self).setUp()
|
||||
self.service = Service()
|
||||
|
||||
def test_set_get_Type(self):
|
||||
self.service.setType('type')
|
||||
self.assertEqual('type', self.service.getType())
|
||||
|
||||
def test_get_Endpoints(self):
|
||||
self.assertEqual([], self.service.getEndpoints())
|
||||
|
||||
def test_get_Endpoint(self):
|
||||
self.assertEqual(None, self.service.getEndpoint('interface'))
|
||||
|
||||
def test_set_get_Description(self):
|
||||
self.service.setDescription('description')
|
||||
self.assertEqual('description', self.service.getDescription())
|
||||
|
||||
def test_set_get_Status(self):
|
||||
self.service.setStatus('enabled')
|
||||
self.assertEqual('enabled', self.service.getStatus())
|
||||
|
||||
def test_isEnable(self):
|
||||
self.assertEqual(False, self.service.isEnabled())
|
32
synergy_scheduler_manager/tests/unit/test_share.py
Normal file
32
synergy_scheduler_manager/tests/unit/test_share.py
Normal file
@ -0,0 +1,32 @@
|
||||
# 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.
|
||||
|
||||
from synergy_scheduler_manager.common.user import Share
|
||||
from synergy_scheduler_manager.tests.unit import base
|
||||
|
||||
|
||||
class TestShare(base.TestCase):
|
||||
def setUp(self):
|
||||
super(TestShare, self).setUp()
|
||||
self.share = Share()
|
||||
|
||||
def test_set_get_Value(self):
|
||||
self.share.setValue('value')
|
||||
self.assertEqual('value', self.share.getValue())
|
||||
|
||||
def test_set_get_SiblingValue(self):
|
||||
self.share.setSiblingValue('sibling_value')
|
||||
self.assertEqual('sibling_value', self.share.getSiblingValue())
|
||||
|
||||
def test_set_get_NormalizedValue(self):
|
||||
self.share.setNormalizedValue('normalized_value')
|
||||
self.assertEqual('normalized_value', self.share.getNormalizedValue())
|
186
synergy_scheduler_manager/tests/unit/test_token.py
Normal file
186
synergy_scheduler_manager/tests/unit/test_token.py
Normal file
@ -0,0 +1,186 @@
|
||||
# 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.
|
||||
|
||||
from datetime import datetime
|
||||
from synergy_scheduler_manager.common.project import Project
|
||||
from synergy_scheduler_manager.common.token import Token
|
||||
from synergy_scheduler_manager.common.user import User
|
||||
from synergy_scheduler_manager.tests.unit import base
|
||||
|
||||
|
||||
class TestToken(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestToken, self).setUp()
|
||||
self.token = Token()
|
||||
|
||||
def test_get_Services(self):
|
||||
self.assertEqual([], self.token.getServices())
|
||||
|
||||
def test_set_get_Creation(self):
|
||||
self.token.setCreation('issue_at')
|
||||
self.assertEqual('issue_at', self.token.getCreation())
|
||||
|
||||
def test_set_get_Expiration(self):
|
||||
self.token.setExpiration('expires_at')
|
||||
self.assertEqual('expires_at', self.token.getExpiration())
|
||||
|
||||
def test_set_get_Extras(self):
|
||||
self.assertEqual({}, self.token.getExtras())
|
||||
|
||||
def test_set_get_Project(self):
|
||||
prj = Project()
|
||||
self.token.setProject(prj)
|
||||
self.assertEqual(0.0, self.token.getProject().getTTL())
|
||||
|
||||
def test_get_Roles(self):
|
||||
self.assertEqual({}, self.token.getExtras())
|
||||
|
||||
def test_set_get_User(self):
|
||||
user = User()
|
||||
self.token.setUser(user)
|
||||
self.assertEqual({}, self.token.getUser().getData())
|
||||
|
||||
def test_isAdmin(self):
|
||||
self.assertEqual(False, self.token.isAdmin())
|
||||
|
||||
def test_issuedAt(self):
|
||||
self.token.setCreation('now')
|
||||
self.assertEqual('now', self.token.issuedAt())
|
||||
|
||||
def test_isExpired(self):
|
||||
str_date = '2015-02-10T13:00:10Z'
|
||||
datetime_date = datetime.strptime(
|
||||
str_date, "%Y-%m-%dT%H:%M:%SZ")
|
||||
self.token.setExpiration(datetime_date)
|
||||
self.assertEqual(True, self.token.isExpired())
|
||||
|
||||
def test_parse(self):
|
||||
tok = {
|
||||
u'token': {
|
||||
u'methods': [u'password'],
|
||||
u'roles': [{u'id': u'1efd5e18c8414086889ac93d8b11c411',
|
||||
u'name': u'admin'}],
|
||||
u'expires_at': u'2016-09-02T12:07:45.814651Z',
|
||||
u'project': {u'domain': {u'id': u'default',
|
||||
u'name': u'Default'},
|
||||
u'id': u'1a6edd87f9ec41d8aa64c8f23d719c2a',
|
||||
u'name': u'admin'},
|
||||
u'catalog': [{
|
||||
u'endpoints': [{
|
||||
u'url': u'http://10.64.31.19:8774/v2/1a6edd8a',
|
||||
u'interface': u'internal',
|
||||
u'region': u'RegionOne',
|
||||
u'region_id': u'RegionOne',
|
||||
u'id': u'ac178ac5b9f34647b9fce954966470c9'},
|
||||
{u'url': u'http://10.64.31.19:8774/v2/1a6edd2a',
|
||||
u'interface': u'admin',
|
||||
u'region': u'RegionOne',
|
||||
u'region_id': u'RegionOne',
|
||||
u'id': u'b81a3518d24d433495985a31740a5b84'},
|
||||
{u'url': u'http://10.64.31.19:8774/v2/1a6ec2a',
|
||||
u'interface': u'public',
|
||||
u'region': u'RegionOne',
|
||||
u'region_id': u'RegionOne',
|
||||
u'id': u'db03d5f72d89461582d4d87e7f82302a'}],
|
||||
u'type': u'compute',
|
||||
u'id': u'27dd094445aa42a9b05ca08c1f094d28',
|
||||
u'name': u'nova'},
|
||||
{
|
||||
u'endpoints': [{
|
||||
u'url': u'http://10.64.31.19:9292',
|
||||
u'interface': u'internal',
|
||||
u'region': u'RegionOne',
|
||||
u'region_id': u'RegionOne',
|
||||
u'id': u'2f5458cf516147ffa1be04fabfbec9f8'},
|
||||
{u'url': u'http://10.64.31.19:9292',
|
||||
u'interface': u'admin',
|
||||
u'region': u'RegionOne',
|
||||
u'region_id': u'RegionOne',
|
||||
u'id': u'468db3a59f644d5d8cea849a'},
|
||||
{u'url': u'http://10.64.31.19:9292',
|
||||
u'interface': u'public',
|
||||
u'region': u'RegionOne',
|
||||
u'region_id': u'RegionOne',
|
||||
u'id': u'a13689dba17c432aa4c1f5b'}],
|
||||
u'type': u'image',
|
||||
u'id': u'6d80825e9f4544ea9a2d0a2d952b2e7c',
|
||||
u'name': u'glance'},
|
||||
{u'endpoints': [{u'url': u'http://10.64.31.19:9696',
|
||||
u'interface': u'admin',
|
||||
u'region': u'RegionOne',
|
||||
u'region_id': u'RegionOne',
|
||||
u'id': u'567ed76f7161484f9c2556'},
|
||||
{u'url': u'http://10.64.31.19:9696',
|
||||
u'interface': u'internal',
|
||||
u'region': u'RegionOne',
|
||||
u'region_id': u'RegionOne',
|
||||
u'id': u'90373f0a87bc41cc99095'},
|
||||
{u'url': u'http://10.64.31.19:9696',
|
||||
u'interface': u'public',
|
||||
u'region': u'RegionOne',
|
||||
u'region_id': u'RegionOne',
|
||||
u'id': u'a95ad02ab '}],
|
||||
u'type': u'network',
|
||||
u'id': u'8f4c00132ccb422cbc0b6139266ad1df',
|
||||
u'name': u'neutron'},
|
||||
{u'endpoints': [{u'url': u'http://10.64.31.19:50v3',
|
||||
u'interface': u'internal',
|
||||
u'region': u'RegionOne',
|
||||
u'region_id': u'RegionOne',
|
||||
u'id': u'494ccc932f0a6f8a86e629'},
|
||||
{u'url': u'http://10.64.31.19:5/v3',
|
||||
u'interface': u'public',
|
||||
u'region': u'RegionOne',
|
||||
u'region_id': u'RegionOne',
|
||||
u'id': u'5503912c691c2b25e1855f9'},
|
||||
{u'url': u'http://10.64.31.19357/v3',
|
||||
u'interface': u'admin',
|
||||
u'region': u'RegionOne',
|
||||
u'region_id': u'RegionOne',
|
||||
u'id': u'6d54bb99a2994ea8f527'}],
|
||||
u'type': u'identity',
|
||||
u'id': u'af19f5adf97c4f3fb1aa9d4fe499dd9',
|
||||
u'name': u'keystone'},
|
||||
{u'endpoints': [{u'url': u'http://10.64.31.19:8051',
|
||||
u'interface': u'public',
|
||||
u'region': u'RegionOne',
|
||||
u'region_id': u'RegionOne',
|
||||
u'id': u'68d6e8128cf84037138a3d'},
|
||||
{u'url': u'http://10.64.31.19:8051',
|
||||
u'interface': u'admin',
|
||||
u'region': u'RegionOne',
|
||||
u'region_id': u'RegionOne',
|
||||
u'id': u'bc0bb63fd58044387a0e61b'},
|
||||
{u'url': u'http://10.64.31.19:8051',
|
||||
u'interface': u'internal',
|
||||
u'region': u'RegionOne',
|
||||
u'region_id': u'RegionOne',
|
||||
u'id': u'f1bc92a85cc80bac0d'}],
|
||||
u'type': u'management',
|
||||
u'id': u'b1c0d32b48934ac380f6a231dce448f0',
|
||||
u'name': u'synergy'}],
|
||||
u'extras': {},
|
||||
u'user': {u'domain': {u'id': u'default',
|
||||
u'name': u'Default'},
|
||||
u'id': u'9364456de70b46e59ba4dbd74498ccb0',
|
||||
u'name': u'admin'},
|
||||
u'audit_ids': [u'2XDA6g5nQeuuSg-vvhPzfw'],
|
||||
u'issued_at': u'2016-09-02T11:57:45.814689Z'}}
|
||||
|
||||
self.tk = Token.parse('tok_id', tok)
|
||||
self.assertEqual({}, self.tk.getExtras())
|
||||
|
||||
str_date = '2016-09-02T12:07:45.814651Z'
|
||||
datetime_date = datetime.strptime(str_date,
|
||||
"%Y-%m-%dT%H:%M:%S.%fZ")
|
||||
self.assertEqual(datetime_date, self.tk.getExpiration())
|
63
synergy_scheduler_manager/tests/unit/test_trust.py
Normal file
63
synergy_scheduler_manager/tests/unit/test_trust.py
Normal file
@ -0,0 +1,63 @@
|
||||
# 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.
|
||||
|
||||
from synergy_scheduler_manager.common.trust import Trust
|
||||
|
||||
from synergy_scheduler_manager.tests.unit import base
|
||||
|
||||
|
||||
class TestTrust(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestTrust, self).setUp()
|
||||
# fake data
|
||||
data = {"id": "id", "trustor_user_id": "trustor_user_id",
|
||||
"impersonation": "impersonation",
|
||||
"trustee_user_id": "trustee_user_id",
|
||||
"links": [],
|
||||
"roles": [],
|
||||
"remaining_uses": "remaining_uses",
|
||||
"expires_at": None,
|
||||
"keystone_url": None,
|
||||
"project_id": "project_id"
|
||||
}
|
||||
self.trust = Trust(data)
|
||||
|
||||
def test_get_Id(self):
|
||||
self.assertEqual('id', self.trust.getId())
|
||||
|
||||
def test_isImpersonations(self):
|
||||
self.assertEqual('impersonation', self.trust.isImpersonations())
|
||||
|
||||
def getRolesLinks(self):
|
||||
pass
|
||||
|
||||
def test_get_trustorUserId(self):
|
||||
self.assertEqual('trustor_user_id', self.trust.getTrustorUserId())
|
||||
|
||||
def test_get_trusteeUserId(self):
|
||||
self.assertEqual('trustee_user_id', self.trust.getTrusteeUserId())
|
||||
|
||||
def test_get_roles(self):
|
||||
self.assertEqual([], self.trust.getRoles())
|
||||
|
||||
def test_get_links(self):
|
||||
self.assertEqual([], self.trust.getlinks())
|
||||
|
||||
def test_get_remainingUses(self):
|
||||
self.assertEqual("remaining_uses", self.trust.getRemainingUses())
|
||||
|
||||
def test_get_expiration(self):
|
||||
self.assertEqual(None, self.trust.getExpiration())
|
||||
|
||||
def test_isExpired(self):
|
||||
self.assertEqual(False, self.trust.isExpired())
|
51
synergy_scheduler_manager/tests/unit/test_user.py
Normal file
51
synergy_scheduler_manager/tests/unit/test_user.py
Normal file
@ -0,0 +1,51 @@
|
||||
# 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.
|
||||
from datetime import datetime
|
||||
from synergy_scheduler_manager.common.user import User
|
||||
from synergy_scheduler_manager.tests.unit import base
|
||||
|
||||
|
||||
class TestUser(base.TestCase):
|
||||
def setUp(self):
|
||||
super(TestUser, self).setUp()
|
||||
self.user = User()
|
||||
|
||||
def test_get_Data(self):
|
||||
data = self.user.getData()
|
||||
data['data'] = 'data'
|
||||
self.assertEqual('data', data['data'])
|
||||
|
||||
def test_set_get_ProjectId(self):
|
||||
self.user.setProjectId('project_id')
|
||||
self.assertEqual('project_id', self.user.getProjectId())
|
||||
|
||||
def test_set_get_Role(self):
|
||||
self.user.setRole('role')
|
||||
self.assertEqual('role', self.user.getRole())
|
||||
|
||||
def test_get_Priority(self):
|
||||
priority = self.user.getPriority()
|
||||
self.assertEqual(0, priority.getValue())
|
||||
self.assertNotEqual(datetime.utcnow(), priority.getLastUpdate())
|
||||
self.assertEqual(0.0, priority.getFairShare('vcpus'))
|
||||
self.assertEqual(0.0, priority.getFairShare('memory'))
|
||||
self.assertEqual(0.0, priority.getFairShare('disk'))
|
||||
|
||||
def test_get_Share(self):
|
||||
share = self.user.getShare()
|
||||
self.assertEqual(0.0, share.getValue())
|
||||
self.assertEqual(0.00, share.getSiblingValue())
|
||||
self.assertEqual(0.000, share.getNormalizedValue())
|
||||
|
||||
def test_set_isenable(self):
|
||||
self.user.setEnabled('true')
|
||||
self.assertEqual('true', self.user.isEnabled())
|
Loading…
x
Reference in New Issue
Block a user