Skip to content

Initial Blazar support #2048 #2049

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 123 additions & 0 deletions libcloud/compute/drivers/openstack.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ class OpenStackVolumeV3Connection(OpenStackBaseConnection):
service_region = "RegionOne"


class OpenStackReservationConnection(OpenStackBaseConnection):
service_type = "reservation"
service_name = "blazar"
service_region = "RegionOne"


class OpenStackNodeDriver(NodeDriver, OpenStackDriverMixin):
"""
Base OpenStack node driver. Should not be used directly.
Expand Down Expand Up @@ -2813,6 +2819,15 @@ def encode_data(self, data):
return json.dumps(data)


class OpenStack_2_ReservationConnection(OpenStackReservationConnection):
responseCls = OpenStack_1_1_Response
accept_format = "application/json"
default_content_type = "application/json; charset=UTF-8"

def encode_data(self, data):
return json.dumps(data)


class OpenStack_2_PortInterfaceState(Type):
"""
Standard states of OpenStack_2_PortInterfaceState
Expand Down Expand Up @@ -2873,6 +2888,10 @@ class OpenStack_2_NodeDriver(OpenStack_1_1_NodeDriver):
volumev3_connection = None
volume_connection = None

# Connection to the Blazar reservation API
reservation_connectionCls = OpenStack_2_ReservationConnection
reservation_connection = None

type = Provider.OPENSTACK

features = {"create_node": ["generates_password"]}
Expand Down Expand Up @@ -2929,6 +2948,16 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.network_connection = self.connection

# We run the init once to get the Blazar API connection
# and put that on the object under self.reservation_connection.
if original_ex_force_base_url or kwargs.get("ex_force_reservation_url"):
kwargs["ex_force_base_url"] = str(
kwargs.pop("ex_force_reservation_url", original_ex_force_base_url)
)
self.connectionCls = self.reservation_connectionCls
super().__init__(*args, **kwargs)
self.reservation_connection = self.connection

# We run the init once again to get the compute API connection
# and that's put under self.connection as normal.
self._ex_force_base_url = original_ex_force_base_url
Expand Down Expand Up @@ -4368,6 +4397,100 @@ def ex_detach_floating_ip_from_node(self, node, ip):
)
return resp.status == httplib.OK

def ex_list_leases(self):
"""
List leases

:rtype: ``list`` of :class:`OpenStack_2_Lease`
"""
return self._to_leases(self.reservation_connection.request("/leases").object)

def _to_leases(self, obj):
lease_elements = obj["leases"]
return [self._to_lease(lease) for lease in lease_elements]

def _to_lease(self, obj):
return OpenStack_2_Lease(
id=obj["id"],
name=obj["name"],
start=obj["start_date"],
end=obj["end_date"],
status=obj["status"],
reservations=obj["reservations"],
driver=self.reservation_connection.driver,
)

def ex_list_hosts(self):
"""
List leases

:rtype: ``list`` of :class:`OpenStack_2_Host`
"""
return self._to_hosts(self.reservation_connection.request("/os-hosts").object)

def _to_hosts(self, obj):
host_elements = obj["hosts"]
return [self._to_host(host) for host in host_elements]

def _to_host(self, obj):
return OpenStack_2_Host(
id=obj["id"],
hypervisor_hostname=obj["hypervisor_hostname"],
vcpus=obj["vcpus"],
memory_mb=obj["memory_mb"],
local_gb=obj["local_gb"],
service_name=obj["service_name"],
)


class OpenStack_2_Host:
"""
Host info.
"""

def __init__(self, id, hypervisor_hostname, vcpus, memory_mb, local_gb, service_name):
self.id = id
self.hypervisor_hostname = hypervisor_hostname
self.vcpus = vcpus
self.memory_mb = memory_mb
self.local_gb = local_gb
self.service_name = service_name

def __repr__(self):
return "<OpenStack_2_Host: id={}, hypervisor_hostname={}>".format(
self.id,
self.hypervisor_hostname,
)


class OpenStack_2_Lease:
"""
Lease info.
"""

PENDING = "PENDING"
ACTIVE = "ACTIVE"
TERMINATED = "TERMINATED"
DELETED = "DELETED"
CREATING = "CREATING"
UPDATING = "UPDATING"
DELETING = "DELETING"
ERROR = "ERROR"

def __init__(self, id, name, start, end, status, reservations, driver):
self.id = id
self.name = name
self.start = start
self.end = end
self.status = status
self.reservations = reservations
self.driver = driver

def __repr__(self):
return "<OpenStack_2_Lease: id={}, name={}, status={}>".format(
self.id, self.name, self.status
)


class OpenStack_1_1_FloatingIpPool:
"""
Expand Down
4 changes: 3 additions & 1 deletion libcloud/test/common/test_openstack_identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -833,7 +833,7 @@ def test_parsing_auth_v2(self):

catalog = OpenStackServiceCatalog(service_catalog=service_catalog, auth_version="2.0")
entries = catalog.get_entries()
self.assertEqual(len(entries), 10)
self.assertEqual(len(entries), 11)

entry = [e for e in entries if e.service_name == "cloudServers"][0]
self.assertEqual(entry.service_type, "compute")
Expand Down Expand Up @@ -904,6 +904,7 @@ def test_get_service_types(self):
"network",
"object-store",
"rax:object-cdn",
"reservation",
"volumev2",
"volumev3",
],
Expand All @@ -923,6 +924,7 @@ def test_get_service_names(self):
self.assertEqual(
service_names,
[
"blazar",
"cinderv2",
"cinderv3",
"cloudFiles",
Expand Down
14 changes: 14 additions & 0 deletions libcloud/test/compute/fixtures/openstack/_v2_0__auth.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,20 @@
"name": "cinderv3",
"type": "volumev3"
},
{
"endpoints": [
{
"region": "RegionOne",
"tenantId": "1337",
"publicURL": "https://test_endpoint.com/v1",
"versionInfo": "https://test_endpoint.com/v1/",
"versionList": "https://test_endpoint.com/",
"versionId": "1"
}
],
"name": "blazar",
"type": "reservation"
},
{
"endpoints": [
{
Expand Down
84 changes: 84 additions & 0 deletions libcloud/test/compute/fixtures/openstack_v1_1/_leases.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
{
"leases": [
{
"id": "6ee55c78-ac52-41a6-99af-2d2d73bcc466",
"name": "lease_foo",
"start_date": "2017-12-26T12:00:00.000000",
"end_date": "2017-12-27T12:00:00.000000",
"status":"PENDING",
"degraded": false,
"user_id": "5434f637520d4c17bbf254af034b0320",
"project_id": "aa45f56901ef45ee95e3d211097c0ea3",
"trust_id": "b442a580b9504ababf305bf2b4c49512",
"created_at": "2017-12-27 10:00:00",
"updated_at": null,
"reservations": [
{
"id": "087bc740-6d2d-410b-9d47-c7b2b55a9d36",
"lease_id": "6ee55c78-ac52-41a6-99af-2d2d73bcc466",
"status": "pending",
"missing_resources": false,
"resources_changed": false,
"resource_id": "5e6c0e6e-f1e6-490b-baaf-50deacbbe371",
"resource_type": "physical:host",
"min": 4,
"max": 6,
"hypervisor_properties": "[\">=\", \"$vcpus\", \"4\"]",
"resource_properties": "",
"before_end": "default",
"created_at": "2017-12-27 10:00:00",
"updated_at": null
},
{
"id": "ddc45423-f863-4e4e-8e7a-51d27cfec962",
"lease_id": "6ee55c78-ac52-41a6-99af-2d2d73bcc466",
"status": "pending",
"missing_resources": false,
"resources_changed": false,
"resource_id": "0b901727-cca2-43ed-bcc8-c21b0982dcb1",
"resource_type": "virtual:instance",
"amount": 4,
"vcpus": 2,
"memory_mb": 4096,
"disk_gb": 100,
"affinity": false,
"resource_properties": "",
"flavor_id": "ddc45423-f863-4e4e-8e7a-51d27cfec962",
"server_group_id": "33cdfc42-5a04-4fcc-b190-1abebaa056bb",
"aggregate_id": 11,
"created_at": "2017-12-27 10:00:00",
"updated_at": null
}
],
"events": [
{
"id": "188a8584-f832-4df9-9a4a-51e6364420ff",
"lease_id": "6ee55c78-ac52-41a6-99af-2d2d73bcc466",
"status": "UNDONE",
"event_type": "start_lease",
"time": "2017-12-26T12:00:00.000000",
"created_at": "2017-12-27 10:00:00",
"updated_at": null
},
{
"id": "277d6436-dfcb-4eae-ae5e-ac7fa9c2fd56",
"lease_id": "6ee55c78-ac52-41a6-99af-2d2d73bcc466",
"status": "UNDONE",
"event_type": "end_lease",
"time": "2017-12-27T12:00:00.000000",
"created_at": "2017-12-27 10:00:00",
"updated_at": null
},
{
"id": "f583af71-ca21-4b66-87de-52211d118029",
"lease_id": "6ee55c78-ac52-41a6-99af-2d2d73bcc466",
"status": "UNDONE",
"time": "2017-12-27T11:00:00.000000",
"event_type": "before_end_lease",
"created_at": "2017-12-27 10:00:00",
"updated_at": null
}
]
}
]
}
21 changes: 21 additions & 0 deletions libcloud/test/compute/fixtures/openstack_v1_1/_os_hosts.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"hosts": [
{
"id": "1",
"hypervisor_hostname": "compute-1",
"hypervisor_type": "QEMU",
"hypervisor_version": 2010001,
"vcpus": 4,
"cpu_info": "{'arch': 'x86_64', 'model': 'cpu64-rhel6', 'vendor': 'Intel'}",
"memory_mb": 8192,
"local_gb": 100,
"service_name": "compute-1",
"reservable": true,
"status": null,
"trust_id": "5f67f11215cf4c52906453a181bfcfea",
"created_at": "2017-12-27 10:00:00",
"updated_at": null,
"extra_capability_sample": "foo"
}
]
}
43 changes: 43 additions & 0 deletions libcloud/test/compute/test_openstack.py
Original file line number Diff line number Diff line change
Expand Up @@ -2005,6 +2005,11 @@ def setUp(self):
# normally authentication happens lazily, but we force it here
self.driver.volumev3_connection._populate_hosts_and_request_paths()

self.driver_klass.reservation_connectionCls.conn_class = OpenStack_2_0_MockHttp
self.driver_klass.reservation_connectionCls.auth_url = "https://auth.api.example.com"
# normally authentication happens lazily, but we force it here
self.driver.reservation_connection._populate_hosts_and_request_paths()

def test__paginated_request_single_page(self):
snapshots = self.driver._paginated_request(
"/snapshots/detail", "snapshots", self.driver._get_volume_connection()
Expand Down Expand Up @@ -2547,6 +2552,22 @@ def test_ex_delete_floating_ip(self):
ip = OpenStack_1_1_FloatingIpAddress("foo-bar-id", "42.42.42.42", None)
self.assertTrue(self.driver.ex_delete_floating_ip(ip))

def test_ex_list_leases(self):
leases = self.driver.ex_list_leases()
self.assertEqual(len(leases), 1)
self.assertEqual(leases[0].id, "6ee55c78-ac52-41a6-99af-2d2d73bcc466")
self.assertEqual(leases[0].name, "lease_foo")
self.assertEqual(leases[0].start, "2017-12-26T12:00:00.000000")
self.assertEqual(leases[0].end, "2017-12-27T12:00:00.000000")
self.assertEqual(leases[0].status, "PENDING")

def test_ex_list_hosts(self):
hosts = self.driver.ex_list_hosts()
self.assertEqual(len(hosts), 1)
self.assertEqual(hosts[0].id, "1")
self.assertEqual(hosts[0].hypervisor_hostname, "compute-1")
self.assertEqual(hosts[0].vcpus, 4)

def test_ex_attach_floating_ip_to_node(self):
image = NodeImage(id=11, name="Ubuntu 8.10 (intrepid)", driver=self.driver)
size = NodeSize(1, "256 slice", None, None, None, None, driver=self.driver)
Expand Down Expand Up @@ -4004,6 +4025,28 @@ def _v2_1337_servers_4242_os_interface(self, method, url, body, headers):
httplib.responses[httplib.OK],
)

def _v1_leases(self, method, url, body, headers):
if method == "GET":
body = self.fixtures.load("_leases.json")

return (
httplib.OK,
body,
self.json_content_headers,
httplib.responses[httplib.OK],
)

def _v1_os_hosts(self, method, url, body, headers):
if method == "GET":
body = self.fixtures.load("_os_hosts.json")

return (
httplib.OK,
body,
self.json_content_headers,
httplib.responses[httplib.OK],
)


# This exists because the nova compute url in devstack has v2 in there but the v1.1 fixtures
# work fine.
Expand Down
Loading