python-openstackclient/openstackclient/tests/unit/compute/v2/fakes.py

1752 lines
53 KiB
Python

# Copyright 2013 Nebula Inc.
#
# 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 copy
import random
from unittest import mock
import uuid
from novaclient import api_versions
from openstack.compute.v2 import flavor as _flavor
from openstackclient.api import compute_v2
from openstackclient.tests.unit import fakes
from openstackclient.tests.unit.identity.v2_0 import fakes as identity_fakes
from openstackclient.tests.unit.image.v2 import fakes as image_fakes
from openstackclient.tests.unit.network.v2 import fakes as network_fakes
from openstackclient.tests.unit import utils
from openstackclient.tests.unit.volume.v2 import fakes as volume_fakes
floating_ip_num = 100
fix_ip_num = 100
injected_file_num = 100
injected_file_size_num = 10240
injected_path_size_num = 255
key_pair_num = 100
core_num = 20
ram_num = 51200
instance_num = 10
property_num = 128
secgroup_rule_num = 20
secgroup_num = 10
servgroup_num = 10
servgroup_members_num = 10
project_name = 'project_test'
QUOTA = {
'project': project_name,
'floating-ips': floating_ip_num,
'fix-ips': fix_ip_num,
'injected-files': injected_file_num,
'injected-file-size': injected_file_size_num,
'injected-path-size': injected_path_size_num,
'key-pairs': key_pair_num,
'cores': core_num,
'ram': ram_num,
'instances': instance_num,
'properties': property_num,
'secgroup_rules': secgroup_rule_num,
'secgroups': secgroup_num,
'server-groups': servgroup_num,
'server-group-members': servgroup_members_num
}
QUOTA_columns = tuple(sorted(QUOTA))
QUOTA_data = tuple(QUOTA[x] for x in sorted(QUOTA))
class FakeAggregate(object):
"""Fake one aggregate."""
@staticmethod
def create_one_aggregate(attrs=None):
"""Create a fake aggregate.
:param Dictionary attrs:
A dictionary with all attributes
:return:
A FakeResource object, with id and other attributes
"""
attrs = attrs or {}
# Set default attribute
aggregate_info = {
"name": "aggregate-name-" + uuid.uuid4().hex,
"availability_zone": "ag_zone",
"hosts": [],
"id": "aggregate-id-" + uuid.uuid4().hex,
"metadata": {
"availability_zone": "ag_zone",
"key1": "value1",
}
}
# Overwrite default attributes.
aggregate_info.update(attrs)
aggregate = fakes.FakeResource(
info=copy.deepcopy(aggregate_info),
loaded=True)
return aggregate
@staticmethod
def create_aggregates(attrs=None, count=2):
"""Create multiple fake aggregates.
:param Dictionary attrs:
A dictionary with all attributes
:param int count:
The number of aggregates to fake
:return:
A list of FakeResource objects faking the aggregates
"""
aggregates = []
for i in range(0, count):
aggregates.append(FakeAggregate.create_one_aggregate(attrs))
return aggregates
@staticmethod
def get_aggregates(aggregates=None, count=2):
"""Get an iterable MagicMock object with a list of faked aggregates.
If aggregates list is provided, then initialize the Mock object
with the list. Otherwise create one.
:param List aggregates:
A list of FakeResource objects faking aggregates
:param int count:
The number of aggregates to fake
:return:
An iterable Mock object with side_effect set to a list of faked
aggregates
"""
if aggregates is None:
aggregates = FakeAggregate.create_aggregates(count)
return mock.Mock(side_effect=aggregates)
class FakeComputev2Client(object):
def __init__(self, **kwargs):
self.agents = mock.Mock()
self.agents.resource_class = fakes.FakeResource(None, {})
self.aggregates = mock.Mock()
self.aggregates.resource_class = fakes.FakeResource(None, {})
self.availability_zones = mock.Mock()
self.availability_zones.resource_class = fakes.FakeResource(None, {})
self.images = mock.Mock()
self.images.resource_class = fakes.FakeResource(None, {})
self.limits = mock.Mock()
self.limits.resource_class = fakes.FakeResource(None, {})
self.servers = mock.Mock()
self.servers.resource_class = fakes.FakeResource(None, {})
self.services = mock.Mock()
self.services.resource_class = fakes.FakeResource(None, {})
self.extensions = mock.Mock()
self.extensions.resource_class = fakes.FakeResource(None, {})
self.flavors = mock.Mock()
self.flavor_access = mock.Mock()
self.flavor_access.resource_class = fakes.FakeResource(None, {})
self.quotas = mock.Mock()
self.quotas.resource_class = fakes.FakeResource(None, {})
self.quota_classes = mock.Mock()
self.quota_classes.resource_class = fakes.FakeResource(None, {})
self.usage = mock.Mock()
self.usage.resource_class = fakes.FakeResource(None, {})
self.volumes = mock.Mock()
self.volumes.resource_class = fakes.FakeResource(None, {})
self.hypervisors = mock.Mock()
self.hypervisors.resource_class = fakes.FakeResource(None, {})
self.hypervisors_stats = mock.Mock()
self.hypervisors_stats.resource_class = fakes.FakeResource(None, {})
self.keypairs = mock.Mock()
self.keypairs.resource_class = fakes.FakeResource(None, {})
self.hosts = mock.Mock()
self.hosts.resource_class = fakes.FakeResource(None, {})
self.server_groups = mock.Mock()
self.server_groups.resource_class = fakes.FakeResource(None, {})
self.server_migrations = mock.Mock()
self.server_migrations.resource_class = fakes.FakeResource(None, {})
self.instance_action = mock.Mock()
self.instance_action.resource_class = fakes.FakeResource(None, {})
self.migrations = mock.Mock()
self.migrations.resource_class = fakes.FakeResource(None, {})
self.auth_token = kwargs['token']
self.management_url = kwargs['endpoint']
self.api_version = api_versions.APIVersion('2.1')
class TestComputev2(utils.TestCommand):
def setUp(self):
super(TestComputev2, self).setUp()
self.app.client_manager.compute = FakeComputev2Client(
endpoint=fakes.AUTH_URL,
token=fakes.AUTH_TOKEN,
)
self.app.client_manager.compute.api = compute_v2.APIv2(
session=self.app.client_manager.session,
endpoint=fakes.AUTH_URL,
)
self.app.client_manager.identity = identity_fakes.FakeIdentityv2Client(
endpoint=fakes.AUTH_URL,
token=fakes.AUTH_TOKEN,
)
self.app.client_manager.image = image_fakes.FakeImagev2Client(
endpoint=fakes.AUTH_URL,
token=fakes.AUTH_TOKEN,
)
self.app.client_manager.network = network_fakes.FakeNetworkV2Client(
endpoint=fakes.AUTH_URL,
token=fakes.AUTH_TOKEN,
)
self.app.client_manager.volume = volume_fakes.FakeVolumeClient(
endpoint=fakes.AUTH_URL,
token=fakes.AUTH_TOKEN,
)
class FakeAgent(object):
"""Fake one or more agent."""
@staticmethod
def create_one_agent(attrs=None):
"""Create a fake agent.
:param Dictionary attrs:
A dictionary with all attributes
:return:
A FakeResource object, with agent_id, os, and so on
"""
attrs = attrs or {}
# set default attributes.
agent_info = {
'agent_id': 'agent-id-' + uuid.uuid4().hex,
'os': 'agent-os-' + uuid.uuid4().hex,
'architecture': 'agent-architecture',
'version': '8.0',
'url': 'http://127.0.0.1',
'md5hash': 'agent-md5hash',
'hypervisor': 'hypervisor',
}
# Overwrite default attributes.
agent_info.update(attrs)
agent = fakes.FakeResource(info=copy.deepcopy(agent_info),
loaded=True)
return agent
@staticmethod
def create_agents(attrs=None, count=2):
"""Create multiple fake agents.
:param Dictionary attrs:
A dictionary with all attributes
:param int count:
The number of agents to fake
:return:
A list of FakeResource objects faking the agents
"""
agents = []
for i in range(0, count):
agents.append(FakeAgent.create_one_agent(attrs))
return agents
class FakeExtension(object):
"""Fake one or more extension."""
@staticmethod
def create_one_extension(attrs=None):
"""Create a fake extension.
:param Dictionary attrs:
A dictionary with all attributes
:return:
A FakeResource object with name, namespace, etc.
"""
attrs = attrs or {}
# Set default attributes.
extension_info = {
'name': 'name-' + uuid.uuid4().hex,
'namespace': (
'http://docs.openstack.org/compute/ext/multinic/api/v1.1'),
'description': 'description-' + uuid.uuid4().hex,
'updated': '2014-01-07T12:00:0-00:00',
'alias': 'NMN',
'links': ('[{"href":'
'"https://github.com/openstack/compute-api", "type":'
' "text/html", "rel": "describedby"}]')
}
# Overwrite default attributes.
extension_info.update(attrs)
extension = fakes.FakeResource(
info=copy.deepcopy(extension_info),
loaded=True)
return extension
class FakeHypervisor(object):
"""Fake one or more hypervisor."""
@staticmethod
def create_one_hypervisor(attrs=None):
"""Create a fake hypervisor.
:param Dictionary attrs:
A dictionary with all attributes
:return:
A FakeResource object, with id, hypervisor_hostname, and so on
"""
attrs = attrs or {}
# Set default attributes.
hypervisor_info = {
'id': 'hypervisor-id-' + uuid.uuid4().hex,
'hypervisor_hostname': 'hypervisor-hostname-' + uuid.uuid4().hex,
'status': 'enabled',
'host_ip': '192.168.0.10',
'cpu_info': {
'aaa': 'aaa',
},
'free_disk_gb': 50,
'hypervisor_version': 2004001,
'disk_available_least': 50,
'local_gb': 50,
'free_ram_mb': 1024,
'service': {
'host': 'aaa',
'disabled_reason': None,
'id': 1,
},
'vcpus_used': 0,
'hypervisor_type': 'QEMU',
'local_gb_used': 0,
'vcpus': 4,
'memory_mb_used': 512,
'memory_mb': 1024,
'current_workload': 0,
'state': 'up',
'running_vms': 0,
}
# Overwrite default attributes.
hypervisor_info.update(attrs)
hypervisor = fakes.FakeResource(info=copy.deepcopy(hypervisor_info),
loaded=True)
return hypervisor
@staticmethod
def create_hypervisors(attrs=None, count=2):
"""Create multiple fake hypervisors.
:param Dictionary attrs:
A dictionary with all attributes
:param int count:
The number of hypervisors to fake
:return:
A list of FakeResource objects faking the hypervisors
"""
hypervisors = []
for i in range(0, count):
hypervisors.append(FakeHypervisor.create_one_hypervisor(attrs))
return hypervisors
class FakeHypervisorStats(object):
"""Fake one or more hypervisor stats."""
@staticmethod
def create_one_hypervisor_stats(attrs=None):
"""Create a fake hypervisor stats.
:param Dictionary attrs:
A dictionary with all attributes
:return:
A FakeResource object, with count, current_workload, and so on
"""
attrs = attrs or {}
# Set default attributes.
stats_info = {
'count': 2,
'current_workload': 0,
'disk_available_least': 50,
'free_disk_gb': 100,
'free_ram_mb': 23000,
'local_gb': 100,
'local_gb_used': 0,
'memory_mb': 23800,
'memory_mb_used': 1400,
'running_vms': 3,
'vcpus': 8,
'vcpus_used': 3,
}
# Overwrite default attributes.
stats_info.update(attrs)
# Set default method.
hypervisor_stats_method = {'to_dict': stats_info}
hypervisor_stats = fakes.FakeResource(
info=copy.deepcopy(stats_info),
methods=copy.deepcopy(hypervisor_stats_method),
loaded=True)
return hypervisor_stats
@staticmethod
def create_hypervisors_stats(attrs=None, count=2):
"""Create multiple fake hypervisors stats.
:param Dictionary attrs:
A dictionary with all attributes
:param int count:
The number of hypervisors to fake
:return:
A list of FakeResource objects faking the hypervisors
"""
hypervisors = []
for i in range(0, count):
hypervisors.append(
FakeHypervisorStats.create_one_hypervisor_stats(attrs))
return hypervisors
class FakeSecurityGroup(object):
"""Fake one or more security groups."""
@staticmethod
def create_one_security_group(attrs=None):
"""Create a fake security group.
:param Dictionary attrs:
A dictionary with all attributes
:return:
A FakeResource object, with id, name, etc.
"""
attrs = attrs or {}
# Set default attributes.
security_group_attrs = {
'id': 'security-group-id-' + uuid.uuid4().hex,
'name': 'security-group-name-' + uuid.uuid4().hex,
'description': 'security-group-description-' + uuid.uuid4().hex,
'tenant_id': 'project-id-' + uuid.uuid4().hex,
'rules': [],
}
# Overwrite default attributes.
security_group_attrs.update(attrs)
return security_group_attrs
@staticmethod
def create_security_groups(attrs=None, count=2):
"""Create multiple fake security groups.
:param Dictionary attrs:
A dictionary with all attributes
:param int count:
The number of security groups to fake
:return:
A list of FakeResource objects faking the security groups
"""
security_groups = []
for i in range(0, count):
security_groups.append(
FakeSecurityGroup.create_one_security_group(attrs))
return security_groups
@staticmethod
def get_security_groups(security_groups=None, count=2):
"""Get an iterable MagicMock with a list of faked security groups.
If security groups list is provided, then initialize the Mock object
with the list. Otherwise create one.
:param List security_groups:
A list of FakeResource objects faking security groups
:param int count:
The number of security groups to fake
:return:
An iterable Mock object with side_effect set to a list of faked
security groups
"""
if security_groups is None:
security_groups = FakeSecurityGroup.create_security_groups(count)
return mock.Mock(side_effect=security_groups)
class FakeSecurityGroupRule(object):
"""Fake one or more security group rules."""
@staticmethod
def create_one_security_group_rule(attrs=None):
"""Create a fake security group rule.
:param Dictionary attrs:
A dictionary with all attributes
:return:
A FakeResource object, with id, etc.
"""
attrs = attrs or {}
# Set default attributes.
security_group_rule_attrs = {
'from_port': 0,
'group': {},
'id': 'security-group-rule-id-' + uuid.uuid4().hex,
'ip_protocol': 'tcp',
'ip_range': {'cidr': '0.0.0.0/0'},
'parent_group_id': 'security-group-id-' + uuid.uuid4().hex,
'to_port': 0,
}
# Overwrite default attributes.
security_group_rule_attrs.update(attrs)
return security_group_rule_attrs
@staticmethod
def create_security_group_rules(attrs=None, count=2):
"""Create multiple fake security group rules.
:param Dictionary attrs:
A dictionary with all attributes
:param int count:
The number of security group rules to fake
:return:
A list of FakeResource objects faking the security group rules
"""
security_group_rules = []
for i in range(0, count):
security_group_rules.append(
FakeSecurityGroupRule.create_one_security_group_rule(attrs))
return security_group_rules
class FakeServer(object):
"""Fake one or more compute servers."""
@staticmethod
def create_one_server(attrs=None, methods=None):
"""Create a fake server.
:param Dictionary attrs:
A dictionary with all attributes
:param Dictionary methods:
A dictionary with all methods
:return:
A FakeResource object, with id, name, metadata, and so on
"""
attrs = attrs or {}
methods = methods or {}
# Set default attributes.
server_info = {
'id': 'server-id-' + uuid.uuid4().hex,
'name': 'server-name-' + uuid.uuid4().hex,
'metadata': {},
'image': {
'id': 'image-id-' + uuid.uuid4().hex,
},
'flavor': {
'id': 'flavor-id-' + uuid.uuid4().hex,
},
'OS-EXT-STS:power_state': 1,
}
# Overwrite default attributes.
server_info.update(attrs)
server = fakes.FakeResource(info=copy.deepcopy(server_info),
methods=methods,
loaded=True)
return server
@staticmethod
def create_servers(attrs=None, methods=None, count=2):
"""Create multiple fake servers.
:param Dictionary attrs:
A dictionary with all attributes
:param Dictionary methods:
A dictionary with all methods
:param int count:
The number of servers to fake
:return:
A list of FakeResource objects faking the servers
"""
servers = []
for i in range(0, count):
servers.append(FakeServer.create_one_server(attrs, methods))
return servers
@staticmethod
def get_servers(servers=None, count=2):
"""Get an iterable MagicMock object with a list of faked servers.
If servers list is provided, then initialize the Mock object with the
list. Otherwise create one.
:param List servers:
A list of FakeResource objects faking servers
:param int count:
The number of servers to fake
:return:
An iterable Mock object with side_effect set to a list of faked
servers
"""
if servers is None:
servers = FakeServer.create_servers(count)
return mock.Mock(side_effect=servers)
class FakeServerEvent(object):
"""Fake one or more server event."""
@staticmethod
def create_one_server_event(attrs=None):
"""Create a fake server event.
:param attrs:
A dictionary with all attributes
:return:
A FakeResource object, with id and other attributes
"""
attrs = attrs or {}
# Set default attributes
server_event_info = {
"instance_uuid": "server-event-" + uuid.uuid4().hex,
"user_id": "user-id-" + uuid.uuid4().hex,
"start_time": "2017-02-27T07:47:13.000000",
"request_id": "req-" + uuid.uuid4().hex,
"action": "create",
"message": None,
"project_id": "project-id-" + uuid.uuid4().hex,
"events": [{
"finish_time": "2017-02-27T07:47:25.000000",
"start_time": "2017-02-27T07:47:15.000000",
"traceback": None,
"event": "compute__do_build_and_run_instance",
"result": "Success"
}]
}
# Overwrite default attributes
server_event_info.update(attrs)
server_event = fakes.FakeResource(
info=copy.deepcopy(server_event_info),
loaded=True,
)
return server_event
class FakeService(object):
"""Fake one or more services."""
@staticmethod
def create_one_service(attrs=None):
"""Create a fake service.
:param Dictionary attrs:
A dictionary with all attributes
:return:
A FakeResource object, with id, host, binary, and so on
"""
attrs = attrs or {}
# Set default attributes.
service_info = {
'id': 'id-' + uuid.uuid4().hex,
'host': 'host-' + uuid.uuid4().hex,
'binary': 'binary-' + uuid.uuid4().hex,
'status': 'enabled',
'zone': 'zone-' + uuid.uuid4().hex,
'state': 'state-' + uuid.uuid4().hex,
'updated_at': 'time-' + uuid.uuid4().hex,
'disabled_reason': 'earthquake',
# Introduced in API microversion 2.11
'forced_down': False,
}
# Overwrite default attributes.
service_info.update(attrs)
service = fakes.FakeResource(info=copy.deepcopy(service_info),
loaded=True)
return service
@staticmethod
def create_services(attrs=None, count=2):
"""Create multiple fake services.
:param Dictionary attrs:
A dictionary with all attributes
:param int count:
The number of services to fake
:return:
A list of FakeResource objects faking the services
"""
services = []
for i in range(0, count):
services.append(FakeService.create_one_service(attrs))
return services
class FakeFlavor(object):
"""Fake one or more flavors."""
@staticmethod
def create_one_flavor(attrs=None):
"""Create a fake flavor.
:param Dictionary attrs:
A dictionary with all attributes
:return:
A FakeResource object, with id, name, ram, vcpus, and so on
"""
attrs = attrs or {}
# Set default attributes.
flavor_info = {
'id': 'flavor-id-' + uuid.uuid4().hex,
'name': 'flavor-name-' + uuid.uuid4().hex,
'ram': 8192,
'vcpus': 4,
'disk': 128,
'swap': 0,
'rxtx_factor': 1.0,
'OS-FLV-DISABLED:disabled': False,
'os-flavor-access:is_public': True,
'description': 'description',
'OS-FLV-EXT-DATA:ephemeral': 0,
'extra_specs': {'property': 'value'},
}
# Overwrite default attributes.
flavor_info.update(attrs)
flavor = _flavor.Flavor(**flavor_info)
return flavor
@staticmethod
def create_flavors(attrs=None, count=2):
"""Create multiple fake flavors.
:param Dictionary attrs:
A dictionary with all attributes
:param int count:
The number of flavors to fake
:return:
A list of FakeResource objects faking the flavors
"""
flavors = []
for i in range(0, count):
flavors.append(FakeFlavor.create_one_flavor(attrs))
return flavors
@staticmethod
def get_flavors(flavors=None, count=2):
"""Get an iterable MagicMock object with a list of faked flavors.
If flavors list is provided, then initialize the Mock object with the
list. Otherwise create one.
:param List flavors:
A list of FakeResource objects faking flavors
:param int count:
The number of flavors to fake
:return:
An iterable Mock object with side_effect set to a list of faked
flavors
"""
if flavors is None:
flavors = FakeFlavor.create_flavors(count)
return mock.Mock(side_effect=flavors)
class FakeFlavorAccess(object):
"""Fake one or more flavor accesses."""
@staticmethod
def create_one_flavor_access(attrs=None):
"""Create a fake flavor access.
:param Dictionary attrs:
A dictionary with all attributes
:return:
A FakeResource object, with flavor_id, tenat_id
"""
attrs = attrs or {}
# Set default attributes.
flavor_access_info = {
'flavor_id': 'flavor-id-' + uuid.uuid4().hex,
'tenant_id': 'tenant-id-' + uuid.uuid4().hex,
}
# Overwrite default attributes.
flavor_access_info.update(attrs)
flavor_access = fakes.FakeResource(
info=copy.deepcopy(flavor_access_info), loaded=True)
return flavor_access
class FakeKeypair(object):
"""Fake one or more keypairs."""
@staticmethod
def create_one_keypair(attrs=None, no_pri=False):
"""Create a fake keypair
:param Dictionary attrs:
A dictionary with all attributes
:return:
A FakeResource object, name, fingerprint, and so on
"""
attrs = attrs or {}
# Set default attributes.
keypair_info = {
'name': 'keypair-name-' + uuid.uuid4().hex,
'type': 'ssh',
'fingerprint': 'dummy',
'public_key': 'dummy',
'user_id': 'user'
}
if not no_pri:
keypair_info['private_key'] = 'private_key'
# Overwrite default attributes.
keypair_info.update(attrs)
keypair = fakes.FakeResource(info=copy.deepcopy(keypair_info),
loaded=True)
return keypair
@staticmethod
def create_keypairs(attrs=None, count=2):
"""Create multiple fake keypairs.
:param Dictionary attrs:
A dictionary with all attributes
:param int count:
The number of keypairs to fake
:return:
A list of FakeResource objects faking the keypairs
"""
keypairs = []
for i in range(0, count):
keypairs.append(FakeKeypair.create_one_keypair(attrs))
return keypairs
@staticmethod
def get_keypairs(keypairs=None, count=2):
"""Get an iterable MagicMock object with a list of faked keypairs.
If keypairs list is provided, then initialize the Mock object with the
list. Otherwise create one.
:param List keypairs:
A list of FakeResource objects faking keypairs
:param int count:
The number of keypairs to fake
:return:
An iterable Mock object with side_effect set to a list of faked
keypairs
"""
if keypairs is None:
keypairs = FakeKeypair.create_keypairs(count)
return mock.Mock(side_effect=keypairs)
class FakeAvailabilityZone(object):
"""Fake one or more compute availability zones (AZs)."""
@staticmethod
def create_one_availability_zone(attrs=None):
"""Create a fake AZ.
:param Dictionary attrs:
A dictionary with all attributes
:return:
A FakeResource object with zoneName, zoneState, etc.
"""
attrs = attrs or {}
# Set default attributes.
host_name = uuid.uuid4().hex
service_name = uuid.uuid4().hex
service_updated_at = uuid.uuid4().hex
availability_zone = {
'zoneName': uuid.uuid4().hex,
'zoneState': {'available': True},
'hosts': {host_name: {service_name: {
'available': True,
'active': True,
'updated_at': service_updated_at,
}}},
}
# Overwrite default attributes.
availability_zone.update(attrs)
availability_zone = fakes.FakeResource(
info=copy.deepcopy(availability_zone),
loaded=True)
return availability_zone
@staticmethod
def create_availability_zones(attrs=None, count=2):
"""Create multiple fake AZs.
:param Dictionary attrs:
A dictionary with all attributes
:param int count:
The number of AZs to fake
:return:
A list of FakeResource objects faking the AZs
"""
availability_zones = []
for i in range(0, count):
availability_zone = \
FakeAvailabilityZone.create_one_availability_zone(attrs)
availability_zones.append(availability_zone)
return availability_zones
class FakeFloatingIP(object):
"""Fake one or more floating ip."""
@staticmethod
def create_one_floating_ip(attrs=None):
"""Create a fake floating ip.
:param Dictionary attrs:
A dictionary with all attributes
:return:
A FakeResource object, with id, ip, and so on
"""
attrs = attrs or {}
# Set default attributes.
floating_ip_attrs = {
'id': 'floating-ip-id-' + uuid.uuid4().hex,
'ip': '1.0.9.0',
'fixed_ip': '2.0.9.0',
'instance_id': 'server-id-' + uuid.uuid4().hex,
'pool': 'public',
}
# Overwrite default attributes.
floating_ip_attrs.update(attrs)
return floating_ip_attrs
@staticmethod
def create_floating_ips(attrs=None, count=2):
"""Create multiple fake floating ips.
:param Dictionary attrs:
A dictionary with all attributes
:param int count:
The number of floating ips to fake
:return:
A list of FakeResource objects faking the floating ips
"""
floating_ips = []
for i in range(0, count):
floating_ips.append(FakeFloatingIP.create_one_floating_ip(attrs))
return floating_ips
@staticmethod
def get_floating_ips(floating_ips=None, count=2):
"""Get an iterable MagicMock object with a list of faked floating ips.
If floating_ips list is provided, then initialize the Mock object
with the list. Otherwise create one.
:param List floating_ips:
A list of FakeResource objects faking floating ips
:param int count:
The number of floating ips to fake
:return:
An iterable Mock object with side_effect set to a list of faked
floating ips
"""
if floating_ips is None:
floating_ips = FakeFloatingIP.create_floating_ips(count)
return mock.Mock(side_effect=floating_ips)
class FakeFloatingIPPool(object):
"""Fake one or more floating ip pools."""
@staticmethod
def create_one_floating_ip_pool(attrs=None):
"""Create a fake floating ip pool.
:param Dictionary attrs:
A dictionary with all attributes
:return:
A FakeResource object, with name, etc
"""
if attrs is None:
attrs = {}
# Set default attributes.
floating_ip_pool_attrs = {
'name': 'floating-ip-pool-name-' + uuid.uuid4().hex,
}
# Overwrite default attributes.
floating_ip_pool_attrs.update(attrs)
return floating_ip_pool_attrs
@staticmethod
def create_floating_ip_pools(attrs=None, count=2):
"""Create multiple fake floating ip pools.
:param Dictionary attrs:
A dictionary with all attributes
:param int count:
The number of floating ip pools to fake
:return:
A list of FakeResource objects faking the floating ip pools
"""
floating_ip_pools = []
for i in range(0, count):
floating_ip_pools.append(
FakeFloatingIPPool.create_one_floating_ip_pool(attrs)
)
return floating_ip_pools
class FakeNetwork(object):
"""Fake one or more networks."""
@staticmethod
def create_one_network(attrs=None):
"""Create a fake network.
:param Dictionary attrs:
A dictionary with all attributes
:return:
A FakeResource object, with id, label, cidr and so on
"""
attrs = attrs or {}
# Set default attributes.
network_attrs = {
'bridge': 'br100',
'bridge_interface': None,
'broadcast': '10.0.0.255',
'cidr': '10.0.0.0/24',
'cidr_v6': None,
'created_at': '2016-02-11T11:17:37.000000',
'deleted': False,
'deleted_at': None,
'dhcp_server': '10.0.0.1',
'dhcp_start': '10.0.0.2',
'dns1': '8.8.4.4',
'dns2': None,
'enable_dhcp': True,
'gateway': '10.0.0.1',
'gateway_v6': None,
'host': None,
'id': 'network-id-' + uuid.uuid4().hex,
'injected': False,
'label': 'network-label-' + uuid.uuid4().hex,
'mtu': None,
'multi_host': False,
'netmask': '255.255.255.0',
'netmask_v6': None,
'priority': None,
'project_id': 'project-id-' + uuid.uuid4().hex,
'rxtx_base': None,
'share_address': False,
'updated_at': None,
'vlan': None,
'vpn_private_address': None,
'vpn_public_address': None,
'vpn_public_port': None,
}
# Overwrite default attributes.
network_attrs.update(attrs)
return network_attrs
@staticmethod
def create_networks(attrs=None, count=2):
"""Create multiple fake networks.
:param Dictionary attrs:
A dictionary with all attributes
:param int count:
The number of networks to fake
:return:
A list of FakeResource objects faking the networks
"""
networks = []
for i in range(0, count):
networks.append(FakeNetwork.create_one_network(attrs))
return networks
@staticmethod
def get_networks(networks=None, count=2):
"""Get an iterable MagicMock object with a list of faked networks.
If networks list is provided, then initialize the Mock object with the
list. Otherwise create one.
:param List networks:
A list of FakeResource objects faking networks
:param int count:
The number of networks to fake
:return:
An iterable Mock object with side_effect set to a list of faked
networks
"""
if networks is None:
networks = FakeNetwork.create_networks(count=count)
return mock.Mock(side_effect=networks)
class FakeHost(object):
"""Fake one host."""
@staticmethod
def create_one_host(attrs=None):
"""Create a fake host.
:param Dictionary attrs:
A dictionary with all attributes
:return:
A FakeResource object, with uuid and other attributes
"""
attrs = attrs or {}
# Set default attributes.
host_info = {
"service_id": 1,
"host": "host1",
"uuid": 'host-id-' + uuid.uuid4().hex,
"vcpus": 10,
"memory_mb": 100,
"local_gb": 100,
"vcpus_used": 5,
"memory_mb_used": 50,
"local_gb_used": 10,
"hypervisor_type": "xen",
"hypervisor_version": 1,
"hypervisor_hostname": "devstack1",
"free_ram_mb": 50,
"free_disk_gb": 50,
"current_workload": 10,
"running_vms": 1,
"cpu_info": "",
"disk_available_least": 1,
"host_ip": "10.10.10.10",
"supported_instances": "",
"metrics": "",
"pci_stats": "",
"extra_resources": "",
"stats": "",
"numa_topology": "",
"ram_allocation_ratio": 1.0,
"cpu_allocation_ratio": 1.0,
"zone": 'zone-' + uuid.uuid4().hex,
"host_name": 'name-' + uuid.uuid4().hex,
"service": 'service-' + uuid.uuid4().hex,
"cpu": 4,
"disk_gb": 100,
'project': 'project-' + uuid.uuid4().hex,
}
host_info.update(attrs)
return host_info
class FakeServerGroup(object):
"""Fake one server group"""
@staticmethod
def _create_one_server_group(attrs=None):
"""Create a fake server group
:param Dictionary attrs:
A dictionary with all attributes
:return:
A FakeResource object, with id and other attributes
"""
if attrs is None:
attrs = {}
# Set default attributes.
server_group_info = {
'id': 'server-group-id-' + uuid.uuid4().hex,
'members': [],
'metadata': {},
'name': 'server-group-name-' + uuid.uuid4().hex,
'project_id': 'server-group-project-id-' + uuid.uuid4().hex,
'user_id': 'server-group-user-id-' + uuid.uuid4().hex,
}
# Overwrite default attributes.
server_group_info.update(attrs)
server_group = fakes.FakeResource(
info=copy.deepcopy(server_group_info),
loaded=True)
return server_group
@staticmethod
def create_one_server_group(attrs=None):
"""Create a fake server group
:param Dictionary attrs:
A dictionary with all attributes
:return:
A FakeResource object, with id and other attributes
"""
if attrs is None:
attrs = {}
attrs.setdefault('policies', ['policy1', 'policy2'])
return FakeServerGroup._create_one_server_group(attrs)
class FakeServerGroupV264(object):
"""Fake one server group for API >= 2.64"""
@staticmethod
def create_one_server_group(attrs=None):
"""Create a fake server group
:param Dictionary attrs:
A dictionary with all attributes
:return:
A FakeResource object, with id and other attributes
"""
if attrs is None:
attrs = {}
attrs.setdefault('policy', 'policy1')
return FakeServerGroup._create_one_server_group(attrs)
class FakeUsage(object):
"""Fake one or more usage."""
@staticmethod
def create_one_usage(attrs=None):
"""Create a fake usage.
:param Dictionary attrs:
A dictionary with all attributes
:return:
A FakeResource object, with tenant_id and other attributes
"""
if attrs is None:
attrs = {}
# Set default attributes.
usage_info = {
'tenant_id': 'usage-tenant-id-' + uuid.uuid4().hex,
'total_memory_mb_usage': 512.0,
'total_vcpus_usage': 1.0,
'total_local_gb_usage': 1.0,
'server_usages': [
{
'ended_at': None,
'flavor': 'usage-flavor-' + uuid.uuid4().hex,
'hours': 1.0,
'local_gb': 1,
'memory_mb': 512,
'name': 'usage-name-' + uuid.uuid4().hex,
'instance_id': uuid.uuid4().hex,
'state': 'active',
'uptime': 3600,
'vcpus': 1
}
]
}
# Overwrite default attributes.
usage_info.update(attrs)
usage = fakes.FakeResource(info=copy.deepcopy(usage_info),
loaded=True)
return usage
@staticmethod
def create_usages(attrs=None, count=2):
"""Create multiple fake services.
:param Dictionary attrs:
A dictionary with all attributes
:param int count:
The number of services to fake
:return:
A list of FakeResource objects faking the services
"""
usages = []
for i in range(0, count):
usages.append(FakeUsage.create_one_usage(attrs))
return usages
class FakeQuota(object):
"""Fake quota"""
@staticmethod
def create_one_comp_quota(attrs=None):
"""Create one quota"""
attrs = attrs or {}
quota_attrs = {
'id': 'project-id-' + uuid.uuid4().hex,
'cores': 20,
'fixed_ips': 30,
'injected_files': 100,
'injected_file_content_bytes': 10240,
'injected_file_path_bytes': 255,
'instances': 50,
'key_pairs': 20,
'metadata_items': 10,
'ram': 51200,
'server_groups': 10,
'server_group_members': 10
}
quota_attrs.update(attrs)
quota = fakes.FakeResource(
info=copy.deepcopy(quota_attrs),
loaded=True)
quota.project_id = quota_attrs['id']
return quota
@staticmethod
def create_one_default_comp_quota(attrs=None):
"""Create one quota"""
attrs = attrs or {}
quota_attrs = {
'id': 'project-id-' + uuid.uuid4().hex,
'cores': 10,
'fixed_ips': 10,
'injected_files': 100,
'injected_file_content_bytes': 10240,
'injected_file_path_bytes': 255,
'instances': 20,
'key_pairs': 20,
'metadata_items': 10,
'ram': 51200,
'server_groups': 10,
'server_group_members': 10
}
quota_attrs.update(attrs)
quota = fakes.FakeResource(
info=copy.deepcopy(quota_attrs),
loaded=True)
quota.project_id = quota_attrs['id']
return quota
@staticmethod
def create_one_comp_detailed_quota(attrs=None):
"""Create one quota"""
attrs = attrs or {}
quota_attrs = {
'id': 'project-id-' + uuid.uuid4().hex,
'cores': {'reserved': 0, 'in_use': 0, 'limit': 20},
'fixed_ips': {'reserved': 0, 'in_use': 0, 'limit': 30},
'injected_files': {'reserved': 0, 'in_use': 0, 'limit': 100},
'injected_file_content_bytes': {
'reserved': 0, 'in_use': 0, 'limit': 10240},
'injected_file_path_bytes': {
'reserved': 0, 'in_use': 0, 'limit': 255},
'instances': {'reserved': 0, 'in_use': 0, 'limit': 50},
'key_pairs': {'reserved': 0, 'in_use': 0, 'limit': 20},
'metadata_items': {'reserved': 0, 'in_use': 0, 'limit': 10},
'ram': {'reserved': 0, 'in_use': 0, 'limit': 51200},
'server_groups': {'reserved': 0, 'in_use': 0, 'limit': 10},
'server_group_members': {'reserved': 0, 'in_use': 0, 'limit': 10}
}
quota_attrs.update(attrs)
quota = fakes.FakeResource(
info=copy.deepcopy(quota_attrs),
loaded=True)
quota.project_id = quota_attrs['id']
return quota
class FakeLimits(object):
"""Fake limits"""
def __init__(self, absolute_attrs=None, rate_attrs=None):
self.absolute_limits_attrs = {
'maxServerMeta': 128,
'maxTotalInstances': 10,
'maxPersonality': 5,
'totalServerGroupsUsed': 0,
'maxImageMeta': 128,
'maxPersonalitySize': 10240,
'maxTotalRAMSize': 51200,
'maxServerGroups': 10,
'maxSecurityGroupRules': 20,
'maxTotalKeypairs': 100,
'totalCoresUsed': 0,
'totalRAMUsed': 0,
'maxSecurityGroups': 10,
'totalFloatingIpsUsed': 0,
'totalInstancesUsed': 0,
'maxServerGroupMembers': 10,
'maxTotalFloatingIps': 10,
'totalSecurityGroupsUsed': 0,
'maxTotalCores': 20,
}
absolute_attrs = absolute_attrs or {}
self.absolute_limits_attrs.update(absolute_attrs)
self.rate_limits_attrs = [{
"uri": "*",
"limit": [
{
"value": 10,
"verb": "POST",
"remaining": 2,
"unit": "MINUTE",
"next-available": "2011-12-15T22:42:45Z"
},
{
"value": 10,
"verb": "PUT",
"remaining": 2,
"unit": "MINUTE",
"next-available": "2011-12-15T22:42:45Z"
},
{
"value": 100,
"verb": "DELETE",
"remaining": 100,
"unit": "MINUTE",
"next-available": "2011-12-15T22:42:45Z"
}
]
}]
@property
def absolute(self):
for (name, value) in self.absolute_limits_attrs.items():
yield FakeAbsoluteLimit(name, value)
def absolute_limits(self):
reference_data = []
for (name, value) in self.absolute_limits_attrs.items():
reference_data.append((name, value))
return reference_data
@property
def rate(self):
for group in self.rate_limits_attrs:
uri = group['uri']
for rate in group['limit']:
yield FakeRateLimit(rate['verb'], uri, rate['value'],
rate['remaining'], rate['unit'],
rate['next-available'])
def rate_limits(self):
reference_data = []
for group in self.rate_limits_attrs:
uri = group['uri']
for rate in group['limit']:
reference_data.append((rate['verb'], uri, rate['value'],
rate['remaining'], rate['unit'],
rate['next-available']))
return reference_data
class FakeAbsoluteLimit(object):
"""Data model that represents an absolute limit"""
def __init__(self, name, value):
self.name = name
self.value = value
class FakeRateLimit(object):
"""Data model that represents a flattened view of a single rate limit"""
def __init__(self, verb, uri, value, remain,
unit, next_available):
self.verb = verb
self.uri = uri
self.value = value
self.remain = remain
self.unit = unit
self.next_available = next_available
class FakeMigration(object):
"""Fake one or more migrations."""
@staticmethod
def create_one_migration(attrs=None, methods=None):
"""Create a fake migration.
:param Dictionary attrs:
A dictionary with all attributes
:param Dictionary methods:
A dictionary with all methods
:return:
A FakeResource object, with id, type, and so on
"""
attrs = attrs or {}
methods = methods or {}
# Set default attributes.
migration_info = {
"dest_host": "10.0.2.15",
"status": "migrating",
"migration_type": "migration",
"updated_at": "2017-01-31T08:03:25.000000",
"created_at": "2017-01-31T08:03:21.000000",
"dest_compute": "compute-" + uuid.uuid4().hex,
"id": random.randint(1, 999),
"source_node": "node-" + uuid.uuid4().hex,
"instance_uuid": uuid.uuid4().hex,
"dest_node": "node-" + uuid.uuid4().hex,
"source_compute": "compute-" + uuid.uuid4().hex,
"uuid": uuid.uuid4().hex,
"old_instance_type_id": uuid.uuid4().hex,
"new_instance_type_id": uuid.uuid4().hex,
"project_id": uuid.uuid4().hex,
"user_id": uuid.uuid4().hex
}
# Overwrite default attributes.
migration_info.update(attrs)
migration = fakes.FakeResource(info=copy.deepcopy(migration_info),
methods=methods,
loaded=True)
return migration
@staticmethod
def create_migrations(attrs=None, methods=None, count=2):
"""Create multiple fake migrations.
:param Dictionary attrs:
A dictionary with all attributes
:param Dictionary methods:
A dictionary with all methods
:param int count:
The number of migrations to fake
:return:
A list of FakeResource objects faking the migrations
"""
migrations = []
for i in range(0, count):
migrations.append(
FakeMigration.create_one_migration(
attrs, methods))
return migrations
class FakeServerMigration(object):
"""Fake one or more server migrations."""
@staticmethod
def create_one_server_migration(attrs=None, methods=None):
"""Create a fake server migration.
:param Dictionary attrs:
A dictionary with all attributes
:param Dictionary methods:
A dictionary with all methods
:return:
A FakeResource object, with id, type, and so on
"""
attrs = attrs or {}
methods = methods or {}
# Set default attributes.
migration_info = {
"created_at": "2016-01-29T13:42:02.000000",
"dest_compute": "compute2",
"dest_host": "1.2.3.4",
"dest_node": "node2",
"id": random.randint(1, 999),
"server_uuid": uuid.uuid4().hex,
"source_compute": "compute1",
"source_node": "node1",
"status": "running",
"memory_total_bytes": random.randint(1, 99999),
"memory_processed_bytes": random.randint(1, 99999),
"memory_remaining_bytes": random.randint(1, 99999),
"disk_total_bytes": random.randint(1, 99999),
"disk_processed_bytes": random.randint(1, 99999),
"disk_remaining_bytes": random.randint(1, 99999),
"updated_at": "2016-01-29T13:42:02.000000",
# added in 2.59
"uuid": uuid.uuid4().hex,
# added in 2.80
"user_id": uuid.uuid4().hex,
"project_id": uuid.uuid4().hex,
}
# Overwrite default attributes.
migration_info.update(attrs)
migration = fakes.FakeResource(
info=copy.deepcopy(migration_info),
methods=methods,
loaded=True)
return migration
class FakeVolumeAttachment(object):
"""Fake one or more volume attachments (BDMs)."""
@staticmethod
def create_one_volume_attachment(attrs=None, methods=None):
"""Create a fake volume attachment.
:param Dictionary attrs:
A dictionary with all attributes
:param Dictionary methods:
A dictionary with all methods
:return:
A FakeResource object, with id, device, and so on
"""
attrs = attrs or {}
methods = methods or {}
# Set default attributes.
volume_attachment_info = {
"id": uuid.uuid4().hex,
"device": "/dev/sdb",
"serverId": uuid.uuid4().hex,
"volumeId": uuid.uuid4().hex,
# introduced in API microversion 2.70
"tag": "foo",
# introduced in API microversion 2.79
"delete_on_termination": True,
# introduced in API microversion 2.89
"attachment_id": uuid.uuid4().hex,
"bdm_uuid": uuid.uuid4().hex
}
# Overwrite default attributes.
volume_attachment_info.update(attrs)
volume_attachment = fakes.FakeResource(
info=copy.deepcopy(volume_attachment_info),
methods=methods,
loaded=True)
return volume_attachment
@staticmethod
def create_volume_attachments(attrs=None, methods=None, count=2):
"""Create multiple fake volume attachments (BDMs).
:param Dictionary attrs:
A dictionary with all attributes
:param Dictionary methods:
A dictionary with all methods
:param int count:
The number of volume attachments to fake
:return:
A list of FakeResource objects faking the volume attachments.
"""
volume_attachments = []
for i in range(0, count):
volume_attachments.append(
FakeVolumeAttachment.create_one_volume_attachment(
attrs, methods))
return volume_attachments