Added implementation for Delete Node Task
* added unit tests for delete node task * updated BaseFixture class for unit test mocking to accept either a string to class to mock or class type directly * added mock code for nova client create vm, list vms and delete vm Change-Id: I7ad9e29a2ce1c4e73efc6dce84146537731cc87b
This commit is contained in:
parent
03760edabb
commit
90628ad709
|
@ -21,9 +21,9 @@ import novaclient.client as NovaClient
|
|||
def nova_client():
|
||||
return NovaClient.Client(2,
|
||||
'admin',
|
||||
'secrete',
|
||||
'messina',
|
||||
'demo',
|
||||
'http://192.168.41.183:5000/v2.0'
|
||||
'http://192.168.131.136:5000/v2.0'
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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 uuid
|
||||
|
||||
from cue import client
|
||||
from cue.tests import base
|
||||
from cue.tests.test_fixtures import nova
|
||||
import os_tasklib.nova.delete_vm as delete_vm
|
||||
|
||||
from taskflow import engines
|
||||
from taskflow.patterns import linear_flow
|
||||
|
||||
SHARED_CONF = {
|
||||
'connection': 'zookeeper',
|
||||
}
|
||||
|
||||
|
||||
class DeleteVmTests(base.TestCase):
|
||||
additional_fixtures = [
|
||||
nova.NovaClient
|
||||
]
|
||||
|
||||
task_store = {
|
||||
'vm_id': "0",
|
||||
}
|
||||
|
||||
def setUp(self):
|
||||
super(DeleteVmTests, self).setUp()
|
||||
# retrieve neutron client API class
|
||||
self.nova_client = client.nova_client()
|
||||
|
||||
# create flow with "DeleteVm" task
|
||||
self.flow = linear_flow.Flow('create port').add(delete_vm.DeleteVm(
|
||||
os_client=self.nova_client))
|
||||
self.image = self.nova_client.images.find(
|
||||
name="cirros-0.3.2-x86_64-uec-kernel")
|
||||
self.flavor = self.nova_client.flavors.find(name="m1.tiny")
|
||||
|
||||
def test_delete_vm_invalid_id(self):
|
||||
# create a few vms
|
||||
new_instances = [self.nova_client.servers.create(name="vm1",
|
||||
image=self.image,
|
||||
flavor=self.flavor),
|
||||
self.nova_client.servers.create(name="vm2",
|
||||
image=self.image,
|
||||
flavor=self.flavor),
|
||||
self.nova_client.servers.create(name="vm3",
|
||||
image=self.image,
|
||||
flavor=self.flavor)]
|
||||
|
||||
# delete non-existing vm (invalid id)
|
||||
DeleteVmTests.task_store['vm_id'] = uuid.uuid4()
|
||||
|
||||
# start engine to run delete task
|
||||
engines.run(self.flow, store=DeleteVmTests.task_store)
|
||||
|
||||
# verify our existing vms have not been deleted
|
||||
vms = self.nova_client.servers.list()
|
||||
found = 0
|
||||
for vm in vms:
|
||||
for created_vm in new_instances:
|
||||
if vm.id == created_vm.id:
|
||||
found += 1
|
||||
|
||||
# cleanup
|
||||
for vm in new_instances:
|
||||
self.nova_client.servers.delete(vm)
|
||||
|
||||
self.assertEqual(len(new_instances), found, "Not all VMs were found")
|
||||
|
||||
def test_delete_vm(self):
|
||||
# create a few vms
|
||||
image = self.nova_client.images.find(
|
||||
name="cirros-0.3.2-x86_64-uec-kernel")
|
||||
flavor = self.nova_client.flavors.find(name="m1.tiny")
|
||||
|
||||
new_instances = [self.nova_client.servers.create(name="vm1",
|
||||
image=image,
|
||||
flavor=flavor),
|
||||
self.nova_client.servers.create(name="vm2",
|
||||
image=image,
|
||||
flavor=flavor),
|
||||
self.nova_client.servers.create(name="vm3",
|
||||
image=image,
|
||||
flavor=flavor)]
|
||||
|
||||
# delete one vm
|
||||
vm_to_delete = new_instances.pop()
|
||||
DeleteVmTests.task_store['vm_id'] = vm_to_delete.id
|
||||
|
||||
# start engine to run delete task
|
||||
engines.run(self.flow, store=DeleteVmTests.task_store)
|
||||
|
||||
# verify vm has been deleted
|
||||
vms = self.nova_client.servers.list()
|
||||
vm_found = False
|
||||
for vm in vms:
|
||||
if vm.id == vm_to_delete.id:
|
||||
vm_found = True
|
||||
break
|
||||
|
||||
# cleanup
|
||||
for vm in new_instances:
|
||||
self.nova_client.servers.delete(vm)
|
||||
|
||||
self.assertEqual(False, vm_found, "VM was not deleted successfully")
|
|
@ -13,6 +13,8 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import inspect
|
||||
|
||||
import fixtures
|
||||
import mock
|
||||
|
||||
|
@ -51,7 +53,15 @@ class BaseFixture(fixtures.Fixture):
|
|||
:param cls: Class to be mock'd. Pass in the string path to the class.
|
||||
:return: A mock'd version of the class.
|
||||
"""
|
||||
patch = mock.patch(cls)
|
||||
class_name = ''
|
||||
if isinstance(cls, str):
|
||||
class_name = cls
|
||||
elif inspect.isclass(cls):
|
||||
class_name = "%s.%s" % (cls.__module__, cls.__name__)
|
||||
else:
|
||||
raise TypeError('Invalid parameter type provided')
|
||||
|
||||
patch = mock.patch(class_name)
|
||||
mock_instance = patch.__enter__()
|
||||
self.addCleanup(patch.__exit__)
|
||||
mocked_cls = mock_instance.return_value
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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 uuid
|
||||
|
||||
import novaclient.v1_1.client as nova_client
|
||||
|
||||
import cue.tests.test_fixtures.base as base
|
||||
|
||||
|
||||
class VmDetails():
|
||||
def __init__(self, vm_id, name, flavor):
|
||||
self.id = vm_id
|
||||
self.name = name
|
||||
self.flavor = flavor
|
||||
|
||||
|
||||
class NovaClient(base.BaseFixture):
|
||||
"""A test fixture to simulate a Nova Client connection
|
||||
|
||||
This class is used in test cases to simulate a real Nova Client
|
||||
connection in the absence of a working Neutron API endpoint.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up test fixture and apply all method overrides."""
|
||||
super(NovaClient, self).setUp()
|
||||
|
||||
self._vm_list = {}
|
||||
self._flavor_id = 1
|
||||
self._image_id = 1
|
||||
self._image_name = ""
|
||||
self._flavor_name = ""
|
||||
|
||||
v2_client = self.mock(nova_client.Client)
|
||||
v2_client.servers.create = self.create_vm
|
||||
v2_client.servers.delete = self.delete_vm
|
||||
v2_client.servers.list = self.list_vms
|
||||
v2_client.flavors.find = self.flavors_find
|
||||
v2_client.images.find = self.image_find
|
||||
|
||||
def flavors_find(self, name=None):
|
||||
"""Mock'd version of novaclient...flavors_find().
|
||||
|
||||
Finds a flavor ID based on provided name.
|
||||
|
||||
:param name: Flavor name.
|
||||
:return: Flavor ID matching provided flavor name.
|
||||
"""
|
||||
self._flavor_name = name
|
||||
return self._flavor_id
|
||||
|
||||
def image_find(self, name=None):
|
||||
"""Mock'd version of novaclient...image_find().
|
||||
|
||||
Finds a
|
||||
|
||||
:param name: Image name.
|
||||
:return: Image ID matching provided image name.
|
||||
"""
|
||||
self._image_name = name
|
||||
return self._image_id
|
||||
|
||||
def create_vm(self, **kwargs):
|
||||
"""Mock'd version of novaclient...create_vm().
|
||||
|
||||
Create a Nova VM.
|
||||
|
||||
:param body: Dictionary with vm information.
|
||||
:return: An updated copy of the 'body' that was passed in, with other
|
||||
information populated.
|
||||
"""
|
||||
if 'name' in kwargs:
|
||||
vm_name = kwargs['name']
|
||||
else:
|
||||
vm_name = "new_vm"
|
||||
|
||||
if 'flavor' in kwargs:
|
||||
vm_flavor = kwargs['flavor']
|
||||
else:
|
||||
vm_flavor = "medium"
|
||||
|
||||
newVm = VmDetails(vm_id=uuid.uuid4(), name=vm_name, flavor=vm_flavor)
|
||||
|
||||
self._vm_list[newVm.id] = newVm
|
||||
|
||||
return newVm
|
||||
|
||||
def delete_vm(self, vm_id):
|
||||
"""Mock'd version of novaclient...delete_vm().
|
||||
|
||||
:param vm object with id instance variable
|
||||
:return: n/a
|
||||
"""
|
||||
if vm_id in self._vm_list:
|
||||
del(self._vm_list[vm_id])
|
||||
|
||||
def list_vms(self, retrieve_all=True, **kwargs):
|
||||
"""Mock'd version of novaclient...list_vms().
|
||||
|
||||
List available vms.
|
||||
|
||||
:param retrieve_all: Set to true to retrieve all available ports
|
||||
"""
|
||||
if retrieve_all:
|
||||
return self._vm_list.values()
|
|
@ -17,9 +17,24 @@ import os_tasklib
|
|||
|
||||
|
||||
class CreatePort(os_tasklib.BaseTask):
|
||||
"""CreatePort Task
|
||||
|
||||
This task interfaces with Neutron API and creates a port based on the
|
||||
parameters provided to the Task.
|
||||
|
||||
"""
|
||||
default_provides = 'neutron_port_id'
|
||||
|
||||
def execute(self, network_id, port_name, **kwargs):
|
||||
"""Main execute method
|
||||
|
||||
:param network_id: Network id to connect new port to
|
||||
:type network_id: string
|
||||
:param port_name: Name for new port
|
||||
:type port_name: string
|
||||
:return: Port record provided by Neutron
|
||||
:rtype: dict
|
||||
"""
|
||||
body_value = {
|
||||
"port": {
|
||||
"admin_state_up": True,
|
||||
|
@ -29,9 +44,8 @@ class CreatePort(os_tasklib.BaseTask):
|
|||
}
|
||||
|
||||
port = self.os_client.create_port(body=body_value)
|
||||
port_id = port['port']['id']
|
||||
|
||||
return port_id
|
||||
return port
|
||||
|
||||
def revert(self, **kwargs):
|
||||
"""Revert function for a failed create port task."""
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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_tasklib
|
||||
|
||||
from cue.common.i18n import _LI # noqa
|
||||
from cue.openstack.common import log as logging
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DeleteVm(os_tasklib.BaseTask):
|
||||
"""DeleteVm Task
|
||||
|
||||
This task interfaces with Nova API and deletes a VM identified by the
|
||||
VM ID provided to the Task.
|
||||
|
||||
"""
|
||||
def execute(self, vm_id, **kwargs):
|
||||
"""Main execute method
|
||||
|
||||
:param vm_id: Network id to connect new port to
|
||||
:type vm_id: string
|
||||
:return: n/a
|
||||
"""
|
||||
self.os_client.servers.delete(vm_id)
|
||||
LOG.info(_LI('Deleting VM, id: %s') % vm_id)
|
Loading…
Reference in New Issue