SDK for Nova keypairs

Change-Id: I89e255a3c7c64b81c6b0710aad64d5c478b1dcb6
Signed-off-by: Tatiana Ovchinnikova <t.v.ovtchinnikova@gmail.com>
This commit is contained in:
Tatiana Ovchinnikova
2026-07-06 12:07:30 -05:00
parent e48473ce01
commit 2fbfe7e6dd
13 changed files with 134 additions and 29 deletions
+14 -2
View File
@@ -200,8 +200,16 @@ def get_novaclient_with_instance_desc(request):
return novaclient(request, version=microversion)
def _microversion_string(microversion):
if microversion is None:
return None
if isinstance(microversion, api_versions.APIVersion):
return microversion.get_string()
return str(microversion)
@memoized.memoized
def computeclient(request):
def computeclient(request, microversion=None):
"""Return the openstacksdk compute proxy for the current request."""
(
_username,
@@ -230,7 +238,11 @@ def computeclient(request):
app_name='horizon',
app_version=importlib.metadata.version('horizon'),
)
return conn.compute
compute = conn.compute
microversion_str = _microversion_string(microversion)
if microversion_str:
compute.default_microversion = microversion_str
return compute
@profiler.trace
+7 -7
View File
@@ -426,31 +426,31 @@ def snapshot_create(request, instance_id, name):
@profiler.trace
def keypair_create(request, name, key_type='ssh'):
microversion = get_microversion(request, 'key_types')
return _nova.novaclient(request, microversion).\
keypairs.create(name, key_type=key_type)
return _nova.computeclient(request, microversion).create_keypair(
name=name, type=key_type)
@profiler.trace
def keypair_import(request, name, public_key, key_type='ssh'):
microversion = get_microversion(request, 'key_types')
return _nova.novaclient(request, microversion).\
keypairs.create(name, public_key, key_type)
return _nova.computeclient(request, microversion).create_keypair(
name=name, public_key=public_key, type=key_type)
@profiler.trace
def keypair_delete(request, name):
_nova.novaclient(request).keypairs.delete(name)
_nova.computeclient(request).delete_keypair(name)
@profiler.trace
def keypair_list(request):
microversion = get_microversion(request, 'key_type_list')
return _nova.novaclient(request, microversion).keypairs.list()
return list(_nova.computeclient(request, microversion).keypairs())
@profiler.trace
def keypair_get(request, name):
return _nova.novaclient(request).keypairs.get(name)
return _nova.computeclient(request).get_keypair(name)
@profiler.trace
@@ -437,12 +437,12 @@
function onGetKeypairs(data) {
angular.extend(
model.keypairs,
data.data.items.map(function (e) {
e.keypair.id = 'li_keypair:' + e.keypair.name;
return e.keypair;
data.data.items.map(function (keypair) {
keypair.id = 'li_keypair:' + keypair.name;
return keypair;
}));
if (data.data.items.length === 1) {
model.newInstanceSpec.key_pair.push(data.data.items[0].keypair);
model.newInstanceSpec.key_pair.push(data.data.items[0]);
}
}
@@ -54,8 +54,8 @@
return deferred.promise;
},
getKeypairs: function() {
var keypairs = [ { keypair: { name: 'key-1' } },
{ keypair: { name: 'key-2' } } ];
var keypairs = [ { name: 'key-1' },
{ name: 'key-2' } ];
var deferred = $q.defer();
deferred.resolve({ data: { items: keypairs } });
@@ -616,7 +616,7 @@
// });
it('should set a keypair by default if only one keypair is available', function () {
var keypair = { keypair: { name: 'key-1' } };
var keypair = { name: 'key-1' };
spyOn(novaApi, 'getKeypairs').and.callFake(function () {
var deferred = $q.defer();
deferred.resolve({ data: { items: [ keypair ] } });
@@ -625,7 +625,9 @@
model.initialize(true);
scope.$apply();
expect(model.newInstanceSpec.key_pair.length).toBe(1);
expect(model.newInstanceSpec.key_pair).toEqual([ keypair.keypair ]);
expect(model.newInstanceSpec.key_pair).toEqual([
{ name: 'key-1', id: 'li_keypair:key-1' }
]);
});
it('should set a security group by default if one named "default" is available',
@@ -151,7 +151,7 @@
}
function getName(item) {
return item.keypair.name.toLowerCase();
return item.name.toLowerCase();
}
}
})();
@@ -47,10 +47,10 @@
nova = $injector.get('horizon.app.core.openstack-service-api.nova');
toast = $injector.get('horizon.framework.widgets.toast.service');
deferredKeypairs = $q.defer();
deferredKeypairs.resolve({data: {items: [{keypair: {name: "Hokusai"}}]}});
deferredKeypairs.resolve({data: {items: [{name: "Hokusai"}]}});
spyOn(nova, 'getKeypairs').and.returnValue(deferredKeypairs.promise);
deferredNewKeypair = $q.defer();
deferredNewKeypair.resolve({data: {items: [{keypair: {name: "Hiroshige"}}]}});
deferredNewKeypair.resolve({data: {name: "Hiroshige", private_key: "pem"}});
spyOn(nova, 'createKeypair').and.returnValue(deferredNewKeypair.promise);
spyOn(modal, 'open').and.callThrough();
spyOn(toast, 'add').and.callFake(angular.noop);
@@ -147,7 +147,7 @@
}
function getName(item) {
return item.keypair.name.toLowerCase();
return item.name.toLowerCase();
}
}
})();
@@ -48,10 +48,10 @@
nova = $injector.get('horizon.app.core.openstack-service-api.nova');
toast = $injector.get('horizon.framework.widgets.toast.service');
deferredKeypairs = $q.defer();
deferredKeypairs.resolve({data: {items: [{keypair: {name: "Hokusai"}}]}});
deferredKeypairs.resolve({data: {items: [{name: "Hokusai"}]}});
spyOn(nova, 'getKeypairs').and.returnValue(deferredKeypairs.promise);
deferredNewKeypair = $q.defer();
deferredNewKeypair.resolve({data: {items: [{keypair: {name: "Hiroshige"}}]}});
deferredNewKeypair.resolve({data: {name: "Hiroshige", private_key: "pem"}});
spyOn(nova, 'createKeypair').and.returnValue(deferredNewKeypair.promise);
spyOn(modal, 'open').and.callThrough();
spyOn(toast, 'add').and.callFake(angular.noop);
@@ -65,7 +65,7 @@
}).result.then(go(config.successUrl));
function getName(item) {
return item.keypair.name;
return item.name;
}
function getKeypairs() {
@@ -21,7 +21,7 @@
var ctrl, keyPairCall, $timeout;
var nova = {
getKeypairs: function() {
var kps = {data: {items: [{keypair: {name: 'one'}},{keypair: {name: 'two'}} ]}};
var kps = {data: {items: [{name: 'one'},{name: 'two'} ]}};
keyPairCall.resolve(kps);
return keyPairCall.promise;
}
@@ -56,7 +56,6 @@
return {data: {items: response.data.items.map(modifyItem)}};
function modifyItem(item) {
item = item.keypair;
item.id = item.name;
item.trackBy = item.name + item.fingerprint;
return item;
@@ -40,7 +40,7 @@
deferredSession.resolve({});
deferred.resolve({
data: {
items: [{keypair: {name: 'keypair1', fingerprint: 'fp'}}]
items: [{name: 'keypair1', fingerprint: 'fp'}]
}
});
$timeout.flush();
@@ -56,9 +56,9 @@
var deferred = $q.defer();
spyOn(nova, 'getKeypair').and.returnValue(deferred.promise);
var result = service.getKeypairPromise('keypair1');
deferred.resolve({data: {keypair: {name: 'keypair1'}}});
deferred.resolve({data: {name: 'keypair1'}});
expect(nova.getKeypair).toHaveBeenCalled();
expect(result.$$state.value.data.keypair.name).toBe('keypair1');
expect(result.$$state.value.data.name).toBe('keypair1');
}));
});
@@ -28,6 +28,7 @@ from novaclient.v2 import servers
import openstack.compute.v2 as compute_v2
from openstack.compute.v2 import flavor as flavor_resource
from openstack.compute.v2 import keypair as keypair_resource
from openstack.test import fakes
from horizon import exceptions as horizon_exceptions
@@ -852,3 +853,94 @@ class FlavorApiTests(test.APIMockTestCase):
self.assertIsInstance(api_val, list)
self.computeclient.flavor_remove_tenant_access.assert_called_once_with(
flavor.id, tenant.id)
class KeypairApiTests(test.APIMockTestCase):
def setUp(self):
super().setUp()
self.computeclient = mock.create_autospec(
compute_v2.Proxy, instance=True)
patcher = mock.patch.object(
api._nova, 'computeclient', return_value=self.computeclient)
self.mock_computeclient = patcher.start()
self.addCleanup(patcher.stop)
def _sdk_keypair(self, nova_keypair=None, **attrs):
if nova_keypair is None:
nova_keypair = self.keypairs.first()
defaults = {
'name': nova_keypair.name,
'type': 'ssh',
}
defaults.update(attrs)
return fakes.generate_fake_resource(
keypair_resource.Keypair, **defaults)
@mock.patch.object(api.nova, 'get_microversion')
def test_keypair_list(self, mock_get_microversion):
keypairs = [self._sdk_keypair()]
mock_get_microversion.return_value = mock.sentinel.microversion
self.computeclient.keypairs.return_value = keypairs
api_keypairs = api.nova.keypair_list(self.request)
self.assertEqual(len(keypairs), len(api_keypairs))
mock_get_microversion.assert_called_once_with(
self.request, 'key_type_list')
self.mock_computeclient.assert_called_once_with(
self.request, mock.sentinel.microversion)
self.computeclient.keypairs.assert_called_once_with()
def test_keypair_get(self):
keypair = self._sdk_keypair()
self.computeclient.get_keypair.return_value = keypair
api_keypair = api.nova.keypair_get(self.request, keypair.name)
self.assertEqual(api_keypair.name, keypair.name)
self.mock_computeclient.assert_called_once_with(self.request)
self.computeclient.get_keypair.assert_called_once_with(keypair.name)
@mock.patch.object(api.nova, 'get_microversion')
def test_keypair_create(self, mock_get_microversion):
keypair = self._sdk_keypair()
mock_get_microversion.return_value = mock.sentinel.microversion
self.computeclient.create_keypair.return_value = keypair
api_keypair = api.nova.keypair_create(self.request, keypair.name,
key_type='ssh')
self.assertEqual(api_keypair.name, keypair.name)
mock_get_microversion.assert_called_once_with(
self.request, 'key_types')
self.mock_computeclient.assert_called_once_with(
self.request, mock.sentinel.microversion)
self.computeclient.create_keypair.assert_called_once_with(
name=keypair.name, type='ssh')
@mock.patch.object(api.nova, 'get_microversion')
def test_keypair_import(self, mock_get_microversion):
keypair = self._sdk_keypair()
mock_get_microversion.return_value = mock.sentinel.microversion
self.computeclient.create_keypair.return_value = keypair
api_keypair = api.nova.keypair_import(
self.request, keypair.name, 'public-key', key_type='ssh')
self.assertEqual(api_keypair.name, keypair.name)
mock_get_microversion.assert_called_once_with(
self.request, 'key_types')
self.mock_computeclient.assert_called_once_with(
self.request, mock.sentinel.microversion)
self.computeclient.create_keypair.assert_called_once_with(
name=keypair.name, public_key='public-key', type='ssh')
def test_keypair_delete(self):
keypair = self._sdk_keypair()
api_val = api.nova.keypair_delete(self.request, keypair.name)
self.assertIsNone(api_val)
self.mock_computeclient.assert_called_once_with(self.request)
self.computeclient.delete_keypair.assert_called_once_with(keypair.name)