Skip to content

Commit

Permalink
Merge pull request #1284 from caphrim007/feature.add-vcmp-disk-to-sdk
Browse files Browse the repository at this point in the history
Adds vcmp disk api
  • Loading branch information
f5-rahm committed Sep 15, 2017
2 parents 9381eb5 + 38a6c0d commit 0492585
Show file tree
Hide file tree
Showing 5 changed files with 311 additions and 1 deletion.
4 changes: 4 additions & 0 deletions f5/bigip/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -1105,6 +1105,10 @@ def exists(self, **kwargs):
:raises: :exc:`requests.HTTPError`, Any HTTP error that was not status
code 404.
"""
return self._exists(**kwargs)

def _exists(self, **kwargs):
"""wrapped with exists, override that in a subclass to customize """
requests_params = self._handle_requests_params(kwargs)
self._check_load_parameters(**kwargs)
kwargs['uri_as_parts'] = True
Expand Down
6 changes: 5 additions & 1 deletion f5/bigip/tm/vcmp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,13 @@

from f5.bigip.resource import OrganizingCollection
from f5.bigip.tm.vcmp.guest import Guests
from f5.bigip.tm.vcmp.virtual_disk import Virtual_Disks


class Vcmp(OrganizingCollection):
def __init__(self, tm):
super(Vcmp, self).__init__(tm)
self._meta_data['allowed_lazy_attributes'] = [Guests]
self._meta_data['allowed_lazy_attributes'] = [
Guests,
Virtual_Disks
]
126 changes: 126 additions & 0 deletions f5/bigip/tm/vcmp/test/functional/test_virtual_disk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# Copyright 2016 F5 Networks 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 os
import pytest
import tempfile
import time

from f5.utils.responses.handlers import Stats


try:
vcmp_host = pytest.config.getoption('--vcmp-host')
except Exception as ex:
vcmp_host = None


@pytest.fixture
def software_images(vcmp_host):
collection = vcmp_host.tm.sys.software.images.get_collection()
result = sorted([x.name.split('/')[0] for x in collection])
return result


@pytest.fixture
def vcmp_guest(vcmp_host, software_images):
file = tempfile.NamedTemporaryFile()
name = os.path.basename(file.name)
resource = vcmp_host.tm.vcmp.guests.guest.create(
name=name,
initialImage=software_images[0],
state='provisioned',
managementGw='1.1.1.254',
managementIp='1.1.1.1/24',
managementNetwork='bridged'
)
yield resource


@pytest.mark.skipif(
vcmp_host is None,
reason='Provide --vcmp-host to run vcmp tests.'
)
class TestGuest(object):
def test_delete(self, vcmp_host, software_images):
file = tempfile.NamedTemporaryFile()
name = os.path.basename(file.name)
resource = vcmp_host.tm.vcmp.guests.guest.create(
name=name,
initialImage=software_images[0],
state='provisioned',
managementGw='1.1.1.254',
managementIp='1.1.1.1/24',
managementNetwork='bridged'
)
self._wait_for_provisioned(vcmp_host, resource.name)

disk = resource.virtualDisk
slots = resource.assignedSlots

resource.delete()

for slot in slots:
self._wait_for_virtual_disk_ready(vcmp_host, disk, slot)
vdisk = vcmp_host.tm.vcmp.virtual_disks.virtual_disk.load(
name=disk, slot=slot
)
vdisk.delete()

assert vcmp_host.tm.vcmp.guests.guest.exists(name=name) is False
for slot in slots:
exists = vcmp_host.tm.vcmp.virtual_disks.virtual_disk.exists(
name=disk, slot=slot
)
assert exists is False

def _wait_for_provisioned(self, vcmp_host, name):
resource = vcmp_host.tm.vcmp.guests.guest.load(name=name)
nops = 0
time.sleep(5)
while nops < 3:
try:
stats = Stats(resource.stats.load())
requested_state = stats.stat['requestedState']['description']
vm_status = stats.stat['vmStatus']['description']

if requested_state == 'provisioned' and vm_status == 'stopped':
nops += 1
else:
nops = 0
except Exception:
# This can be caused by restjavad restarting.
pass
time.sleep(10)

def _wait_for_virtual_disk_ready(self, vcmp_host, disk, slot):
resource = vcmp_host.tm.vcmp.virtual_disks.virtual_disk.load(
name=disk, slot=slot
)
nops = 0
time.sleep(5)
while nops < 3:
try:
stats = Stats(resource.stats.load())
status = stats.stat['status']['description']

if status == 'ready':
nops += 1
else:
nops = 0
except Exception:
# This can be caused by restjavad restarting.
pass
time.sleep(10)
44 changes: 44 additions & 0 deletions f5/bigip/tm/vcmp/test/unit/test_virtual_disk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Copyright 2017 F5 Networks 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 mock
import pytest

from f5.bigip.tm.vcmp.virtual_disk import Virtual_Disk
from f5.sdk_exception import UnsupportedMethod


@pytest.fixture
def FakeResource():
mo = mock.MagicMock()
return Virtual_Disk(mo)


def test_create(FakeResource):
with pytest.raises(UnsupportedMethod) as ex:
FakeResource.create()
assert "does not support the create method" in str(ex.value)


def test_update(FakeResource):
with pytest.raises(UnsupportedMethod) as ex:
FakeResource.update()
assert "does not support the update method" in str(ex.value)


def test_modify(FakeResource):
with pytest.raises(UnsupportedMethod) as ex:
FakeResource.modify()
assert "does not support the modify method" in str(ex.value)
132 changes: 132 additions & 0 deletions f5/bigip/tm/vcmp/virtual_disk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# coding=utf-8
#
# Copyright 2016 F5 Networks 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.
#

"""BIG-IP® Guest (vcmp) module
REST URI
``http://localhost/mgmt/tm/vcmp/virtual-disk/``
GUI Path
``Virtual Disk List``
REST Kind
``tm:vcmp:virtual-disk:*``
"""

from f5.bigip.resource import Collection
from f5.bigip.resource import Resource
from f5.sdk_exception import DisallowedCreationParameter
from f5.sdk_exception import DisallowedReadParameter
from f5.sdk_exception import F5SDKError
from f5.sdk_exception import UnsupportedMethod


class Virtual_Disks(Collection):
def __init__(self, vcmp):
super(Virtual_Disks, self).__init__(vcmp)
self._meta_data['allowed_lazy_attributes'] = [Virtual_Disk]
self._meta_data['required_json_kind'] = 'tm:vcmp:virtual-disk:virtual-diskcollectionstate'
self._meta_data['attribute_registry'] = {
'tm:vcmp:virtual-disk:virtual-diskstate': Virtual_Disk
}


class Virtual_Disk(Resource):
def __init__(self, collection):
super(Virtual_Disk, self).__init__(collection)
self._meta_data['required_json_kind'] = 'tm:vcmp:virtual-disk:virtual-diskstate'

def load(self, **kwargs):
"""Loads a given resource
Loads a given resource provided a 'name' and an optional 'slot'
parameter. The 'slot' parameter is not a required load parameter
because it is provided as an optional way of constructing the
correct 'name' of the vCMP resource.
:param kwargs:
:return:
"""
kwargs['transform_name'] = True
kwargs = self._mutate_name(kwargs)
return self._load(**kwargs)

def exists(self, **kwargs):
kwargs['transform_name'] = True
kwargs = self._mutate_name(kwargs)
return self._exists(**kwargs)

def delete(self, **kwargs):
kwargs['transform_name'] = True
kwargs = self._mutate_name(kwargs)
return self._delete(**kwargs)

def modify(self, **kwargs):
raise UnsupportedMethod(
"%s does not support the modify method" % self.__class__.__name__
)

def create(self, **kwargs):
raise UnsupportedMethod(
"%s does not support the create method" % self.__class__.__name__
)

def update(self, **kwargs):
raise UnsupportedMethod(
"%s does not support the update method" % self.__class__.__name__
)

def _check_load_parameters(self, **kwargs):
"""Override method for one in resource.py to check partition
The partition cannot be included as a parameter to load a guest.
Raise an exception if a consumer gives the partition parameter.
:raises: DisallowedReadParameter
"""

if 'partition' in kwargs:
msg = "'partition' is not allowed as a load parameter. Vcmp " \
"guests are accessed by name."
raise DisallowedReadParameter(msg)
super(Virtual_Disk, self)._check_load_parameters(**kwargs)

def _check_create_parameters(self, **kwargs):
"""Override method for one in resource.py to check partition
The partition cannot be included as a parameter to create a guest.
Raise an exception if a consumer gives the partition parameter.
:raises: DisallowedCreationParameter
"""

if 'partition' in kwargs:
msg = "'partition' is not allowed as a create parameter. Vcmp " \
"guests are created with the 'name' at least."
raise DisallowedCreationParameter(msg)
super(Virtual_Disk, self)._check_create_parameters(**kwargs)

def _mutate_name(self, kwargs):
slot = kwargs.pop('slot', None)
if slot is not None:
try:
kwargs['name'] = '{0}/{1}'.format(kwargs['name'], int(slot))
except ValueError:
raise F5SDKError(
"The provided 'slot' must be a number"
)
return kwargs

0 comments on commit 0492585

Please sign in to comment.