Skip to content

Commit eda37ed

Browse files
authored
Merge pull request #893 from QualiSystems/feature/alex_dev_retry_refreship_for_api
added retry in refresh_ip for api calls to cloudshell
2 parents 4679ef9 + d56c166 commit eda37ed

6 files changed

Lines changed: 62 additions & 71 deletions

File tree

package/cloudshell/cp/vcenter/commands/command_orchestrator.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import jsonpickle
44

55
from cloudshell.cp.vcenter.models.DeployFromImageDetails import DeployFromImageDetails
6+
from cloudshell.shell.core.context import ResourceRemoteCommandContext
67
from cloudshell.cp.vcenter.models.OrchestrationSaveResult import OrchestrationSaveResult
78
from cloudshell.cp.vcenter.models.OrchestrationSavedArtifactsInfo import OrchestrationSavedArtifactsInfo
89
from cloudshell.cp.vcenter.models.OrchestrationSavedArtifact import OrchestrationSavedArtifact
@@ -303,16 +304,15 @@ def destroy_vm_only(self, context, ports):
303304
def refresh_ip(self, context, cancellation_context, ports):
304305
"""
305306
Refresh IP Command, will refresh the ip of the vm and will update it on the resource
306-
:param models.QualiDriverModels.ResourceRemoteCommandContext context: the context the command runs on
307+
:param ResourceRemoteCommandContext context: the context the command runs on
307308
:param cancellation_context:
308309
:param list[string] ports: the ports of the connection between the remote resource and the local resource, NOT IN USE!!!
309310
"""
310311
resource_details = self._parse_remote_model(context)
311312
# execute command
312313
res = self.command_wrapper.execute_command_with_connection(context,
313314
self.refresh_ip_command.refresh_ip,
314-
resource_details.vm_uuid,
315-
resource_details.fullname,
315+
resource_details,
316316
cancellation_context,
317317
context.remote_endpoints[0].app_context.app_request_json)
318318
return set_command_result(result=res, unpicklable=False)
@@ -373,6 +373,8 @@ def _parse_remote_model(self, context):
373373
app_resource_detail.vm_uuid = holder.vmdetails.uid
374374
app_resource_detail.cloud_provider = context.resource.fullname
375375
app_resource_detail.fullname = resource.fullname
376+
if hasattr(holder.vmdetails, 'vmCustomParams'):
377+
app_resource_detail.vm_custom_params = holder.vmdetails.vmCustomParams
376378
return app_resource_detail
377379

378380
def power_on_not_roemote(self, context, vm_uuid, resource_fullname):

package/cloudshell/cp/vcenter/commands/refresh_ip.py

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import re
22
import time
33

4+
from retrying import retry
5+
46
from cloudshell.cp.vcenter.commands.ip_result import IpResult, IpReason
57

68
from cloudshell.cp.vcenter.common.vcenter.vm_location import VMLocation
9+
from cloudshell.cp.vcenter.models.GenericDeployedAppResourceModel import GenericDeployedAppResourceModel
710

811

912
class RefreshIpCommand(object):
@@ -19,15 +22,15 @@ def _do_not_run_on_static_vm(self, app_request_json):
1922
if app_request_json == '' or app_request_json is None:
2023
raise ValueError('This command cannot be executed on a Static VM.')
2124

22-
def refresh_ip(self, si, logger, session, vcenter_data_model, vm_uuid, resource_name, cancellation_context,app_request_json):
25+
def refresh_ip(self, si, logger, session, vcenter_data_model, resource_model, cancellation_context,
26+
app_request_json):
2327
"""
2428
Refreshes IP address of virtual machine and updates Address property on the resource
2529
2630
:param vim.ServiceInstance si: py_vmomi service instance
2731
:param logger:
2832
:param vCenterShell.driver.SecureCloudShellApiSession session: cloudshell session
29-
:param str vm_uuid: UUID of Virtual Machine
30-
:param str resource_name: Logical resource name to update address property on
33+
:param GenericDeployedAppResourceModel resource_model: UUID of Virtual Machine
3134
:param VMwarevCenterResourceModel vcenter_data_model: the vcenter data model attributes
3235
:param cancellation_context:
3336
"""
@@ -36,29 +39,34 @@ def refresh_ip(self, si, logger, session, vcenter_data_model, vm_uuid, resource_
3639
default_network = VMLocation.combine(
3740
[vcenter_data_model.default_datacenter, vcenter_data_model.holding_network])
3841

39-
resource = session.GetResourceDetails(resource_name)
40-
41-
match_function = self.ip_manager.get_ip_match_function(self._get_ip_refresh_ip_regex(resource))
42+
match_function = self.ip_manager.get_ip_match_function(
43+
self._get_ip_refresh_ip_regex(resource_model.vm_custom_params))
4244

43-
timeout = self._get_ip_refresh_timeout(resource)
45+
timeout = self._get_ip_refresh_timeout(resource_model.vm_custom_params)
4446

45-
vm = self.pyvmomi_service.find_by_uuid(si, vm_uuid)
47+
vm = self.pyvmomi_service.find_by_uuid(si, resource_model.vm_uuid)
4648

4749
ip_res = self.ip_manager.get_ip(vm, default_network, match_function, cancellation_context, timeout, logger)
4850

4951
if ip_res.reason == IpReason.Timeout:
5052
raise ValueError('IP address of VM \'{0}\' could not be obtained during {1} seconds'
51-
.format(resource_name, timeout))
53+
.format(resource_model.fullname, timeout))
5254

5355
if ip_res.reason == IpReason.Success:
54-
session.UpdateResourceAddress(resource_name, ip_res.ip_address)
56+
self._update_resource_address_with_retry(session=session,
57+
resource_name=resource_model.fullname,
58+
ip_address=ip_res.ip_address)
5559

5660
return ip_res.ip_address
5761

62+
@retry(stop_max_attempt_number=5, wait_fixed=1000)
63+
def _update_resource_address_with_retry(self, session, resource_name, ip_address):
64+
session.UpdateResourceAddress(resource_name, ip_address)
65+
5866
@staticmethod
59-
def _get_ip_refresh_timeout(resource):
67+
def _get_ip_refresh_timeout(custom_params):
6068
timeout = RefreshIpCommand._get_custom_param(
61-
resource=resource,
69+
custom_params=custom_params,
6270
custom_param_name='refresh_ip_timeout')
6371

6472
if not timeout:
@@ -67,21 +75,18 @@ def _get_ip_refresh_timeout(resource):
6775
return float(timeout)
6876

6977
@staticmethod
70-
def _get_ip_refresh_ip_regex(resource):
78+
def _get_ip_refresh_ip_regex(custom_params):
7179
return RefreshIpCommand._get_custom_param(
72-
resource=resource,
80+
custom_params=custom_params,
7381
custom_param_name='ip_regex')
7482

7583
@staticmethod
76-
def _get_custom_param(resource, custom_param_name):
77-
custom_param_values = []
78-
vm_details = resource.VmDetails
79-
if vm_details and hasattr(vm_details, 'VmCustomParams') and vm_details.VmCustomParams:
80-
custom_params = vm_details.VmCustomParams
81-
params = custom_params if isinstance(custom_params, list) else [custom_params]
82-
custom_param_values = [custom_param.Value for custom_param
83-
in params
84-
if custom_param.Name == custom_param_name]
84+
def _get_custom_param(custom_params, custom_param_name):
85+
if not custom_params:
86+
return None
87+
88+
custom_param_values = [custom_param.value for custom_param in custom_params
89+
if custom_param.name == custom_param_name]
8590

8691
if custom_param_values:
8792
return custom_param_values[0]

package/cloudshell/cp/vcenter/models/GenericDeployedAppResourceModel.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ class GenericDeployedAppResourceModel(object):
22
def __init__(self):
33
self.vm_uuid = ''
44
self.cloud_provider = ''
5+
self.fullname = ''
6+
self.vm_custom_params = None

package/cloudshell/tests/test_commands/test_refresh_ip.py

Lines changed: 25 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from unittest import TestCase
22

33
from cloudshell.api.cloudshell_api import ResourceInfoVmDetails, ResourceInfo, VmCustomParam
4+
from cloudshell.cp.vcenter.models import GenericDeployedAppResourceModel
45
from mock import Mock, create_autospec
56
from cloudshell.cp.vcenter.commands.refresh_ip import RefreshIpCommand
67
from cloudshell.cp.vcenter.models.VMwarevCenterResourceModel import VMwarevCenterResourceModel
@@ -30,18 +31,15 @@ def test_refresh_ip(self):
3031
ip_regex = self._create_custom_param('ip_regex', '192\.168\..*')
3132
refresh_ip_timeout = self._create_custom_param('refresh_ip_timeout', '10')
3233

33-
resource_instance = create_autospec(ResourceInfo)
34-
resource_instance.ResourceModelName = 'Generic Deployed App'
35-
resource_instance.ResourceAttributes = {'vm_uuis': '123',
36-
'cloud_provider': 'vCenter'
37-
}
38-
resource_instance.VmDetails = create_autospec(ResourceInfoVmDetails)
39-
resource_instance.VmDetails.VmCustomParams = [ip_regex, refresh_ip_timeout]
34+
resource_model = create_autospec(GenericDeployedAppResourceModel)
35+
resource_model.fullname = 'Generic Deployed App'
36+
resource_model.vm_uuid = '123',
37+
resource_model.cloud_provider = 'vCenter'
38+
resource_model.vm_custom_params = [ip_regex, refresh_ip_timeout]
4039

4140
refresh_ip_command = RefreshIpCommand(pyvmomi_service, ResourceModelParser(), Mock())
4241
session = Mock()
4342
session.UpdateResourceAddress = Mock(return_value=True)
44-
session.GetResourceDetails = Mock(return_value=resource_instance)
4543
si = Mock()
4644

4745
center_resource_model = VMwarevCenterResourceModel()
@@ -53,8 +51,7 @@ def test_refresh_ip(self):
5351
refresh_ip_command.refresh_ip(si=si,
5452
session=session,
5553
vcenter_data_model=center_resource_model,
56-
vm_uuid='machine1',
57-
resource_name='default_network',
54+
resource_model=resource_model,
5855
cancellation_context=cancellation_context,
5956
logger=Mock(),
6057
app_request_json=Mock())
@@ -63,11 +60,9 @@ def test_refresh_ip(self):
6360
self.assertTrue(session.UpdateResourceAddress.called_with('machine1', '192.168.1.1'))
6461

6562
def _create_custom_param(self, name, value):
66-
node = Mock()
67-
node.attrib = {'Name': name, 'Value': value}
68-
vm_custom_param = VmCustomParam(node, '')
69-
vm_custom_param.Name = name
70-
vm_custom_param.Value = value
63+
vm_custom_param = Mock()
64+
vm_custom_param.name = name
65+
vm_custom_param.value = value
7166
return vm_custom_param
7267

7368
def test_refresh_ip_choose_ipv4(self):
@@ -92,18 +87,16 @@ def test_refresh_ip_choose_ipv4(self):
9287
ip_regex = self._create_custom_param('ip_regex', '')
9388
refresh_ip_timeout = self._create_custom_param('refresh_ip_timeout', '10')
9489

95-
resource_instance = create_autospec(ResourceInfo)
96-
resource_instance.ResourceModelName = 'Generic Deployed App'
97-
resource_instance.ResourceAttributes = {'vm_uuis': '123',
98-
'cloud_provider': 'vCenter'
99-
}
100-
resource_instance.VmDetails = create_autospec(ResourceInfoVmDetails)
101-
resource_instance.VmDetails.VmCustomParams = [ip_regex, refresh_ip_timeout]
90+
resource_model = create_autospec(GenericDeployedAppResourceModel)
91+
resource_model.fullname = 'Generic Deployed App'
92+
resource_model.vm_uuid = '123',
93+
resource_model.cloud_provider = 'vCenter'
94+
resource_model.vm_custom_params = [ip_regex, refresh_ip_timeout]
10295

10396
refresh_ip_command = RefreshIpCommand(pyvmomi_service, ResourceModelParser(), Mock())
10497
session = Mock()
10598
session.UpdateResourceAddress = Mock(return_value=True)
106-
session.GetResourceDetails = Mock(return_value=resource_instance)
99+
session.GetResourceDetails = Mock(return_value=resource_model)
107100
si = Mock()
108101

109102
center_resource_model = VMwarevCenterResourceModel()
@@ -116,8 +109,7 @@ def test_refresh_ip_choose_ipv4(self):
116109
si=si,
117110
session=session,
118111
vcenter_data_model=center_resource_model,
119-
vm_uuid='machine1',
120-
resource_name='default_network',
112+
resource_model=resource_model,
121113
cancellation_context=cancellation_context,
122114
logger=Mock(),
123115
app_request_json=Mock())
@@ -147,18 +139,16 @@ def test_refresh_ip_choose_ip_by_regex(self):
147139
ip_regex = self._create_custom_param('ip_regex', '192\.168\..*')
148140
refresh_ip_timeout = self._create_custom_param('refresh_ip_timeout', '10')
149141

150-
resource_instance = create_autospec(ResourceInfo)
151-
resource_instance.ResourceModelName = 'Generic Deployed App'
152-
resource_instance.ResourceAttributes = {'vm_uuis': '123',
153-
'cloud_provider': 'vCenter'
154-
}
155-
resource_instance.VmDetails = create_autospec(ResourceInfoVmDetails)
156-
resource_instance.VmDetails.VmCustomParams = [ip_regex, refresh_ip_timeout]
142+
resource_model = create_autospec(GenericDeployedAppResourceModel)
143+
resource_model.fullname = 'Generic Deployed App'
144+
resource_model.vm_uuid = '123',
145+
resource_model.cloud_provider = 'vCenter'
146+
resource_model.vm_custom_params = [ip_regex, refresh_ip_timeout]
157147

158148
refresh_ip_command = RefreshIpCommand(pyvmomi_service, ResourceModelParser(), Mock())
159149
session = Mock()
160150
session.UpdateResourceAddress = Mock(return_value=True)
161-
session.GetResourceDetails = Mock(return_value=resource_instance)
151+
session.GetResourceDetails = Mock(return_value=resource_model)
162152
si = Mock()
163153

164154
center_resource_model = VMwarevCenterResourceModel()
@@ -171,8 +161,7 @@ def test_refresh_ip_choose_ip_by_regex(self):
171161
si=si,
172162
session=session,
173163
vcenter_data_model=center_resource_model,
174-
vm_uuid='machine1',
175-
resource_name='default_network',
164+
resource_model=resource_model,
176165
cancellation_context=cancellation_context,
177166
logger=Mock(),
178167
app_request_json=Mock())
@@ -184,5 +173,5 @@ def test_refresh_ip_should_fail_static_vm(self):
184173
# Act
185174
refresh_ip_command = RefreshIpCommand(Mock(), Mock(), Mock())
186175
# assert
187-
self.assertRaises(ValueError, refresh_ip_command.refresh_ip, Mock(), Mock(), Mock(), Mock(), Mock(), Mock(),
176+
self.assertRaises(ValueError, refresh_ip_command.refresh_ip, Mock(), Mock(), Mock(), Mock(), Mock(),
188177
Mock(), None)

package/cloudshell/tests/tests_pycommon/test_resourceModelParser.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,3 @@ def test_parse_resource_info_model_class_does_not_exist(self):
6969
resource_model_parser = ResourceModelParser()
7070

7171
self.assertRaises(ValueError, resource_model_parser.convert_to_resource_model, {}, None)
72-
73-
def test_parse_response_info(self):
74-
resource_model_parser = ResourceModelParser()
75-
76-
attributes = {'VM_UUID': '422258cd-8b76-e375-8c3b-8e1bf86a4713', 'Cloud Provider':'vCenter' }
77-
78-
resource_model = resource_model_parser.convert_to_resource_model(attributes, GenericDeployedAppResourceModel)
79-
80-
self.assertEqual(resource_model.vm_uuid, '422258cd-8b76-e375-8c3b-8e1bf86a4713')

package/test_requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
nose
2+
mock
3+
freezegun

0 commit comments

Comments
 (0)