Skip to content

Commit 3173974

Browse files
committed
Merge branch 'develop'
2 parents c0e6bb1 + 4717363 commit 3173974

11 files changed

Lines changed: 163 additions & 22 deletions

File tree

.travis.yml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,14 @@ python:
33
- "2.7"
44

55
install:
6-
- pip install -r package/requirements.txt --extra-index-url https://testpypi.python.org/simple
7-
- pip install cloudshell-shell-core --extra-index-url https://testpypi.python.org/simple
8-
- pip install cloudshell-core --extra-index-url https://testpypi.python.org/simple
6+
- pip install -r external_requirements.txt
97
- pip install -r test_requirements.txt
10-
- pip install coveralls
8+
- pip install "cloudshell-core>=2.0.0,<2.1.0" --extra-index-url https://testpypi.python.org/simple
9+
- pip install "cloudshell-shell-core>=2.0.0,<2.1.0" --extra-index-url https://testpypi.python.org/simple
10+
- pip install "cloudshell-automation-api>=7.1.0.0,<7.2.0.0" --extra-index-url https://testpypi.python.org/simple
1111

1212
script:
1313
- pushd package
14-
- pip install "cloudshell-automation-api>=7.1.0.0,<7.2.0.0" --extra-index-url https://testpypi.python.org/simple
1514
- python setup.py develop
1615
- popd
1716
- python runtests.py --with-coverage --cover-package=package --exclude-dir=integration

external_requirements.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pyvmomi==6.0.0
2+
jsonpickle==0.9.3
3+
enum==0.4.6

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

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import time
2-
2+
from datetime import date
33
import jsonpickle
4+
from cloudshell.cp.vcenter.models.OrchestrationSaveResult import OrchestrationSaveResult
5+
from cloudshell.cp.vcenter.models.OrchestrationSavedArtifactsInfo import OrchestrationSavedArtifactsInfo
6+
from cloudshell.cp.vcenter.models.OrchestrationSavedArtifact import OrchestrationSavedArtifact
47
from pyVim.connect import SmartConnect, Disconnect
58

69
from cloudshell.cp.vcenter.commands.connect_dvswitch import VirtualSwitchConnectCommand
@@ -17,7 +20,7 @@
1720
from cloudshell.cp.vcenter.common.cloud_shell.driver_helper import CloudshellDriverHelper
1821
from cloudshell.cp.vcenter.common.cloud_shell.resource_remover import CloudshellResourceRemover
1922
from cloudshell.cp.vcenter.common.model_factory import ResourceModelParser
20-
from cloudshell.cp.vcenter.common.utilites.command_result import set_command_result
23+
from cloudshell.cp.vcenter.common.utilites.command_result import set_command_result, get_result_from_command_output
2124
from cloudshell.cp.vcenter.common.utilites.common_name import generate_unique_name
2225
from cloudshell.cp.vcenter.common.utilites.common_utils import back_slash_to_front_converter
2326
from cloudshell.cp.vcenter.common.utilites.context_based_logger_factory import ContextBasedLoggerFactory
@@ -406,10 +409,11 @@ def save_snapshot(self, context, snapshot_name):
406409
:return:
407410
"""
408411
resource_details = self._parse_remote_model(context)
409-
self.command_wrapper.execute_command_with_connection(context,
410-
self.snapshot_saver.save_snapshot,
411-
resource_details.vm_uuid,
412-
snapshot_name)
412+
created_snapshot_path = self.command_wrapper.execute_command_with_connection(context,
413+
self.snapshot_saver.save_snapshot,
414+
resource_details.vm_uuid,
415+
snapshot_name)
416+
return set_command_result(created_snapshot_path)
413417

414418
def restore_snapshot(self, context, snapshot_name):
415419
"""
@@ -439,3 +443,50 @@ def get_snapshots(self, context):
439443
self.snapshots_retriever.get_snapshots,
440444
resource_details.vm_uuid)
441445
return set_command_result(result=res, unpicklable=False)
446+
447+
def orchestration_save(self, context, mode="shallow", custom_params=None):
448+
"""
449+
Creates a snapshot with a unique name and returns SavedResults as JSON
450+
:param context: resource context of the vCenterShell
451+
:param mode: Snapshot save mode, default shallow. Currently not it use
452+
:param custom_params: Set of custom parameter to be supported in the future
453+
:return: SavedResults serialized as JSON
454+
:rtype: SavedResults
455+
"""
456+
resource_details = self._parse_remote_model(context)
457+
created_date = date.today()
458+
snapshot_name = created_date.strftime('%y_%m_%d %H_%M_%S_%f')
459+
created_snapshot_path = self.save_snapshot(context=context, snapshot_name=snapshot_name)
460+
461+
created_snapshot_path = self._strip_double_quotes(created_snapshot_path)
462+
463+
orchestration_saved_artifact = OrchestrationSavedArtifact()
464+
orchestration_saved_artifact.artifact_type = 'vcenter_snapshot'
465+
orchestration_saved_artifact.identifier = created_snapshot_path
466+
467+
saved_artifacts_info = OrchestrationSavedArtifactsInfo(
468+
resource_name=resource_details.cloud_provider,
469+
created_date=created_date,
470+
restore_rules={'requires_same_resource': True},
471+
saved_artifact=orchestration_saved_artifact)
472+
473+
orchestration_save_result = OrchestrationSaveResult(saved_artifacts_info)
474+
475+
return set_command_result(result=orchestration_save_result, unpicklable=False)
476+
477+
@staticmethod
478+
def _strip_double_quotes(created_snapshot_path):
479+
if created_snapshot_path.startswith('"') and created_snapshot_path.endswith('"'):
480+
created_snapshot_path = created_snapshot_path[1:-1]
481+
return created_snapshot_path
482+
483+
def orchestration_restore(self, context, saved_details):
484+
"""
485+
486+
:param context:
487+
:param saved_details:
488+
:return:
489+
"""
490+
saved_artifacts_info = get_result_from_command_output(saved_details)
491+
snapshot_name = saved_artifacts_info['saved_artifacts_info']['saved_artifact']['identifier']
492+
return self.restore_snapshot(context=context, snapshot_name=snapshot_name)

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

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,13 @@ def save_snapshot(self, si, logger, vm_uuid, snapshot_name):
3434
"""
3535
vm = self.pyvmomi_service.find_by_uuid(si, vm_uuid)
3636

37-
self._verify_snapshot_name_does_not_exists(snapshot_name, vm)
37+
snapshot_path_to_be_created = SaveSnapshotCommand._get_snapshot_name_to_be_created(snapshot_name, vm)
38+
SaveSnapshotCommand._verify_snapshot_uniquness(snapshot_path_to_be_created, vm)
3839

3940
task = self._create_snapshot(logger, snapshot_name, vm)
4041

41-
return self.task_waiter.wait_for_task(task=task, logger=logger, action_name='Create Snapshot')
42+
self.task_waiter.wait_for_task(task=task, logger=logger, action_name='Create Snapshot')
43+
return snapshot_path_to_be_created
4244

4345
@staticmethod
4446
def _create_snapshot(logger, snapshot_name, vm):
@@ -49,11 +51,14 @@ def _create_snapshot(logger, snapshot_name, vm):
4951
return task
5052

5153
@staticmethod
52-
def _verify_snapshot_name_does_not_exists(snapshot_name, vm):
53-
current_snapshot_name = SnapshotRetriever.get_current_snapshot_name(vm)
54-
if not current_snapshot_name:
55-
return
56-
snapshot_path_to_be_created = SnapshotRetriever.combine(current_snapshot_name, snapshot_name)
54+
def _verify_snapshot_uniquness(snapshot_path_to_be_created, vm):
5755
all_snapshots = SnapshotRetriever.get_vm_snapshots(vm)
5856
if snapshot_path_to_be_created in all_snapshots:
5957
raise SnapshotAlreadyExistsException(SNAPSHOT_ALREADY_EXISTS)
58+
59+
@staticmethod
60+
def _get_snapshot_name_to_be_created(snapshot_name, vm):
61+
current_snapshot_name = SnapshotRetriever.get_current_snapshot_name(vm)
62+
if not current_snapshot_name:
63+
return ''
64+
return SnapshotRetriever.combine(current_snapshot_name, snapshot_name)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class OrchestrationSaveResult(object):
2+
def __init__(self, saved_artifacts_info):
3+
"""
4+
:type saved_artifacts_info: OrchestrationSavedArtifactsInfo
5+
"""
6+
self.saved_artifacts_info = saved_artifacts_info
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class OrchestrationSavedArtifact(object):
2+
def __init__(self):
3+
self.artifact_type = ''
4+
self.identifier = ''
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
class OrchestrationSavedArtifactsInfo(object):
2+
def __init__(self, resource_name, created_date, restore_rules, saved_artifact):
3+
"""
4+
:type resource_name: str
5+
:type created_date: date
6+
:type restore_rules: dict
7+
:type saved_artifact: OrchestrationSavedArtifact
8+
"""
9+
self.resource_name = resource_name
10+
self.created_date = created_date
11+
self.restore_rules = restore_rules
12+
self.saved_artifact = saved_artifact

package/cloudshell/tests/test_commands/test_command_orchestrator.py

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
from unittest import TestCase
22

3+
import jsonpickle
34
from cloudshell.api.cloudshell_api import ResourceInfo
45
from cloudshell.cp.vcenter.commands.command_orchestrator import CommandOrchestrator
5-
from mock import Mock, create_autospec
6+
from cloudshell.shell.core.driver_context import ResourceRemoteCommandContext, ResourceContextDetails, AppContext
7+
from mock import Mock, create_autospec, patch
8+
9+
RESTORE_SNAPSHOT = 'cloudshell.cp.vcenter.commands.command_orchestrator.CommandOrchestrator.restore_snapshot'
10+
SAVE_SNAPSHOT = 'cloudshell.cp.vcenter.commands.command_orchestrator.CommandOrchestrator.save_snapshot'
611

712

813
class TestCommandOrchestrator(TestCase):
@@ -124,4 +129,52 @@ def test_restore_snapshot(self):
124129

125130
def test_get_snapshots(self):
126131
self.command_orchestrator.get_snapshots(self.context)
127-
self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called)
132+
self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called)
133+
134+
def test_orchestration_save(self):
135+
# Arrange
136+
with patch(SAVE_SNAPSHOT) as save_snapshot_mock:
137+
save_snapshot_mock.return_value = '"new_snapshot"'
138+
139+
remote_command_context = create_autospec(ResourceRemoteCommandContext)
140+
remote_command_context.resource = create_autospec(ResourceContextDetails)
141+
remote_command_context.resource.fullname = 'vcenter'
142+
endpoint = create_autospec(ResourceContextDetails)
143+
endpoint.fullname = 'vm_111'
144+
endpoint.app_context = create_autospec(AppContext)
145+
endpoint.app_context.deployed_app_json = '{"vmdetails": {"uid": "vm_uuid1"}}'
146+
remote_command_context.remote_endpoints = [endpoint]
147+
148+
# Act
149+
saved_result = CommandOrchestrator().orchestration_save(context=remote_command_context,
150+
mode='shallow',
151+
custom_params=None)
152+
153+
# Assert
154+
save_snapshot_mock.assert_called_once()
155+
saved_result_dict = jsonpickle.decode(saved_result)
156+
self.assertEqual(saved_result_dict['saved_artifacts_info']['saved_artifact']['artifact_type'],
157+
'vcenter_snapshot')
158+
self.assertEqual(saved_result_dict['saved_artifacts_info']['saved_artifact']['identifier'], 'new_snapshot')
159+
self.assertEqual(saved_result_dict['saved_artifacts_info']['resource_name'], 'vcenter')
160+
self.assertIsNotNone(saved_result_dict['saved_artifacts_info']['created_date'])
161+
162+
def test_orchestration_restore(self):
163+
# Arrange
164+
with patch(RESTORE_SNAPSHOT) as mock_restore_snapshot:
165+
# Act
166+
self.command_orchestrator.orchestration_restore(self.context, '''{
167+
"saved_artifacts_info": {
168+
"resource_name": "ex cillum sed laboris",
169+
"created_date": "4313-10-12T18:03:15.053Z",
170+
"restore_rules": {
171+
"requires_same_resource": false
172+
},
173+
"saved_artifact": {
174+
"artifact_type": "veniam in qui",
175+
"identifier": "deserunt1"
176+
}
177+
}
178+
}''')
179+
# Assert
180+
mock_restore_snapshot.assert_called_once_with(context=self.context, snapshot_name='deserunt1')

test_requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ coverage
33
unittest2
44
mock
55
teamcity-messages
6-
jsonpickle
7-
nose-exclude
6+
nose-exclude
7+
coveralls

vcentershell_driver/driver.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,5 +105,11 @@ def remote_get_snapshots(self, context, ports):
105105
"""
106106
return self.command_orchestrator.get_snapshots(context)
107107

108+
def orchestration_save(self, context, ports, mode="shallow", custom_params=None):
109+
return self.command_orchestrator.orchestration_save(context, mode, custom_params)
110+
111+
def orchestration_restore(self, context, ports, saved_details):
112+
return self.command_orchestrator.orchestration_restore(context, saved_details)
113+
108114
def get_vm_uuid(self, context, vm_name):
109115
return self.command_orchestrator.get_vm_uuid_by_name(context, vm_name)

0 commit comments

Comments
 (0)