diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..aade0aa
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,14 @@
+after_success: coveralls
+install:
+ - pip install -r ./test_requirements.txt
+ - pip install "cloudshell-core>=2.0.0,<2.1.0"
+ - pip install "cloudshell-automation-api>=7.1,<7.3"
+ - pip install "cloudshell-shell-core>=2.3.0,<2.4.0"
+ - pip install pytest-cov
+language: python
+notifications:
+ webhools: "https://qualisystemslab-cloudshell-orch-sandbox.getbadges.io/api/app/webhook/96453247-3989-49f9-a6c0-201036e14a70"
+python:
+ - "2.7"
+script:
+ py.test --cov=sandbox_scripts
diff --git a/README.md b/README.md
index e4a7736..f2b274a 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,7 @@
# cloudshell-orch-sandbox
+
+[![Coverage Status](https://coveralls.io/repos/github/QualiSystemsLab/cloudshell-orch-sandbox/badge.svg?branch=develop)](https://coveralls.io/github/QualiSystemsLab/cloudshell-orch-sandbox?branch=develop) [![Build Status](https://travis-ci.org/QualiSystemsLab/cloudshell-orch-sandbox.svg?branch=develop)](https://travis-ci.org/QualiSystemsLab/cloudshell-orch-sandbox)
+
Package for sandbox orchestration script functions
diff --git a/sandbox_scripts/QualiEnvironmentUtils/QualiUtils.py b/sandbox_scripts/QualiEnvironmentUtils/QualiUtils.py
index 43fc226..b030cdb 100644
--- a/sandbox_scripts/QualiEnvironmentUtils/QualiUtils.py
+++ b/sandbox_scripts/QualiEnvironmentUtils/QualiUtils.py
@@ -7,4 +7,4 @@ def __init__(self, name, message):
self.name = name
def __str__(self):
- return 'CloudShell error at ' + self.name + '. Error is:' + self.message
+ return 'CloudShell error at ' + self.name + '. Error is: ' + self.message
diff --git a/sandbox_scripts/QualiEnvironmentUtils/Sandbox.py b/sandbox_scripts/QualiEnvironmentUtils/Sandbox.py
index d4d710a..4193517 100644
--- a/sandbox_scripts/QualiEnvironmentUtils/Sandbox.py
+++ b/sandbox_scripts/QualiEnvironmentUtils/Sandbox.py
@@ -4,9 +4,6 @@
from cloudshell.helpers.scripts import cloudshell_scripts_helpers as helpers
from os.path import *
-from quali_utils.quali_packaging import PackageEditor
-from quali_api_client import QualiAPIClient
-
SEVERITY_INFO = 20
SEVERITY_ERROR = 40
@@ -46,15 +43,14 @@ def __init__(self, reservation_id, logger):
# ----------------------------------
# ----------------------------------
- def write_message_to_output(self, message, severity_level=SEVERITY_INFO):
+ def _write_message_to_output(self, message, severity_level=SEVERITY_INFO):
"""
Write a message to the output window
"""
-
if severity_level == SEVERITY_INFO:
self.api_session.WriteMessageToReservationOutput(self.id, message)
elif severity_level == SEVERITY_ERROR:
- self.api_session.WriteMessageToReservationOutput(self.id, '' + message + '')
+ self.api_session.WriteMessageToReservationOutput(self.id, '' + message + '')
# ----------------------------------
def report_error(self, error_message, raise_error=True, write_to_output_window=False):
@@ -64,9 +60,10 @@ def report_error(self, error_message, raise_error=True, write_to_output_window=F
:param bool raise_error: Do you want to throw an exception
:param bool write_to_output_window: Would you like to write the message to the output window
"""
- self._logger.error(error_message)
+ if self._logger:
+ self._logger.error(error_message)
if write_to_output_window:
- self.write_message_to_output(error_message, SEVERITY_ERROR)
+ self._write_message_to_output(error_message, SEVERITY_ERROR)
if raise_error:
raise QualiError(self.id, error_message)
@@ -77,9 +74,10 @@ def report_info(self, message, write_to_output_window=False):
:param str message: The message you would like to present
:param bool write_to_output_window: Would you like to write the message to the output window?
"""
- self._logger.info(message)
+ if self._logger:
+ self._logger.info(message)
if write_to_output_window:
- self.write_message_to_output(message, SEVERITY_INFO)
+ self._write_message_to_output(message, SEVERITY_INFO)
# ----------------------------------
def get_root_resources(self):
@@ -127,9 +125,6 @@ def get_details(self):
"""
try:
return self.api_session.GetReservationDetails(self.id)
- except QualiError as qe:
- err = "Failed to get the Sandbox's details. " + str(qe)
- self.report_error(error_message=err)
except:
err = "Failed to get the Sandbox's details. Unexpected error: " + str(sys.exc_info()[0])
self.report_error(error_message=err)
@@ -170,7 +165,8 @@ def activate_connectors(self, write_to_output=True):
bi_endpoints.append(endpoint.Target)
bi_endpoints.append(endpoint.Source)
if not bi_endpoints:
- self.report_info(message="No connectors to connect for reservation {0}".format(self.id))
+ self.report_info(message="No connectors to connect for reservation {0}".format(self.id),
+ write_to_output_window=write_to_output)
return
self.api_session.ConnectRoutesInReservation(self.id, bi_endpoints, 'bi')
self.report_info(message="Connectors connected", write_to_output_window=write_to_output)
@@ -203,7 +199,8 @@ def activate_routes(self, write_to_output=True):
uni_endpoints.append(route_endpoint.Target)
if not bi_endpoints and not uni_endpoints:
- self.report_info(message="No routes to connect for reservation {0}".format(self.id))
+ self.report_info(message="No routes to connect for reservation {0}".format(self.id),
+ write_to_output_window=write_to_output)
return
if bi_endpoints:
self.api_session.ConnectRoutesInReservation(self.id, bi_endpoints, 'bi')
@@ -256,31 +253,19 @@ def enqueue_command(self, commandName, commandInputs=[], printOutput=False):
# -----------------------------------------
# -----------------------------------------
def save_sandbox_as_blueprint(self, blueprint_name, write_to_output=True):
- snapshot_exist = True
-
try:
- full_path = None
- tp = self.api_session.GetActiveTopologyNames()
-
- for value in tp.Topologies:
- filename = basename(value)
- if filename == blueprint_name:
- full_path = value
- break
-
- if full_path is None:
- snapshot_exist = False
+ #TODO - fullpath should be passed as a param to the function and not hard coded
+ # save the current Sandbox as a new Blueprint with the given snapshot name
+ fullpath = 'Snapshots'
+ self.api_session.SaveReservationAsTopology(self.id, topologyName=blueprint_name,folderFullPath=fullpath, includeInactiveRoutes=True)
except CloudShellAPIError as error:
err = "Failed to save sandbox as blueprint. " + error.message
- self.report_error(error_message=err, write_to_output_window=write_to_output)
- if snapshot_exist:
- err = "Blueprint " + blueprint_name + " already exist. Please select a different name."
- self.report_error(error_message=err, write_to_output_window=write_to_output)
- raise Exception('Blueprint name already exist. Please select a different name.')
- # save the current Sandbox as a new Blueprint with the given snapshot name
- fullpath = 'Snapshots'
- self.api_session.SaveReservationAsTopology(self.id, topologyName=blueprint_name,folderFullPath=fullpath, includeInactiveRoutes=True)
+ self.report_error(error_message=err, raise_error=True, write_to_output_window=write_to_output)
+ # if snapshot_exist:
+ # err = "Blueprint " + blueprint_name + " already exist. Please select a different name."
+ # self.report_error(error_message=err, write_to_output_window=write_to_output)
+ # raise Exception('Blueprint name already exist. Please select a different name.')
#update the new snapshot with the user as owner
username = helpers.get_reservation_context_details().owner_user
@@ -292,8 +277,8 @@ def save_sandbox_as_blueprint(self, blueprint_name, write_to_output=True):
# -----------------------------------------
def is_abstract(self, resource_alias):
for abstract_resource in self.blueprint_details.AbstractResources:
- if resource_alias == abstract_resource.Alias:
- return True
+ if resource_alias == abstract_resource.Alias:
+ return True
return False
# -----------------------------------------
@@ -312,8 +297,8 @@ def get_storage_server_resource(self):
def get_config_set_pool_resource(self):
root_resources = self.get_root_resources()
for resource in root_resources:
- if resource.model.lower() == 'config set pool':
- return resource
+ if resource.model.lower() == 'config set pool':
+ return resource
return None
diff --git a/sandbox_scripts/QualiEnvironmentUtils/SnapshotManager.py b/sandbox_scripts/QualiEnvironmentUtils/SnapshotManager.py
new file mode 100644
index 0000000..6b4e6cd
--- /dev/null
+++ b/sandbox_scripts/QualiEnvironmentUtils/SnapshotManager.py
@@ -0,0 +1,36 @@
+#TODO: implement this file/move code from NetworkSaveNResource
+from sandbox_scripts.QualiEnvironmentUtils.StorageManager import StorageManager
+from sandbox_scripts.QualiEnvironmentUtils.QualiUtils import QualiError
+'''
+class SnapshotManager(object):
+ def __init__(self, storage_client):
+ self.storage_client = storage_client
+ self.config_files_root = self.storage_client.get_configs_root()
+ # ----------------------------------
+ # Is this Sandbox originates from a snapshot Blueprint?
+ # ----------------------------------
+ def is_snapshot(self,fileName = " "):
+ # check if there is a directory with the Blueprint's name under the snapshots dir
+ if fileName != " ":
+ env_dir = self.config_files_root + '/Snapshots/' + fileName
+ else:
+ env_dir = self.config_files_root + '/Snapshots/' + self.sandbox.Blueprint_name
+
+ env_dir = env_dir.replace(' ', '_')
+ return self.storage_client.dir_exist(env_dir)
+
+ # ----------------------------------
+ # delete file name on storage
+ # ----------------------------------
+ def delete_src_file(self,fileName):
+
+ env_dir = self.config_files_root + '/Snapshots/' + fileName
+ env_dir = env_dir.replace(' ', '_')
+ self.storage_client.delete(env_dir)
+
+ # ----------------------------------
+ def create_snapshot_dir(self,snapshot_name):
+ env_dir = self.config_files_root + '/Snapshots/' + snapshot_name.strip()
+ if not self.storage_client.dir_exist(env_dir):
+ self.storage_client.create_dir(env_dir, write_to_output=True)
+'''
\ No newline at end of file
diff --git a/sandbox_scripts/QualiEnvironmentUtils/tests/__init__.py b/sandbox_scripts/QualiEnvironmentUtils/tests/__init__.py
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/sandbox_scripts/QualiEnvironmentUtils/tests/__init__.py
@@ -0,0 +1 @@
+
diff --git a/sandbox_scripts/QualiEnvironmentUtils/tests/test_Sandbox.py b/sandbox_scripts/QualiEnvironmentUtils/tests/test_Sandbox.py
new file mode 100644
index 0000000..85b6d42
--- /dev/null
+++ b/sandbox_scripts/QualiEnvironmentUtils/tests/test_Sandbox.py
@@ -0,0 +1,407 @@
+import unittest
+from mock import patch, Mock,call
+from sandbox_scripts.QualiEnvironmentUtils.Sandbox import SandboxBase
+from sandbox_scripts.QualiEnvironmentUtils.QualiUtils import QualiError
+from cloudshell.api.cloudshell_api import ReservationDescriptionInfo
+import json
+import os
+from cloudshell.api.common_cloudshell_api import CloudShellAPIError
+
+resContext = '''{"id":"5487c6ce-d0b3-43e9-8ee7-e27af8406905",
+ "ownerUser":"bob",
+ "ownerPass":"nIqm+BG6ZGJjby5hUittVFFJASc=",
+ "domain":"Global",
+ "environmentName":"My environment",
+ "description":"New demo environment",
+ "parameters":
+ { "globalInputs": [],
+ "resourceRequirements":[],
+ "resourceAdditionalInfo":[]}}'''
+
+conContext = '''{"serverAddress": "localhost",
+"adminAuthToken": "anAdminToken"}'''
+
+
+class SandboxTests(unittest.TestCase):
+ @patch('cloudshell.helpers.scripts.cloudshell_scripts_helpers.get_api_session')
+ def setUp(self, mock_api_session):
+ os.environ['reservationContext'] = resContext
+ os.environ['qualiConnectivityContext'] = conContext
+ tli = Mock()
+ tli.Topologies = ["My environment"]
+ mock_api_session.return_value.GetActiveTopologyNames = Mock(return_value=tli)
+
+ abstractinfo = Mock()
+ abstractinfo.Alias = "alias"
+ topoinfo = Mock()
+
+ topoinfo.Name = "My environment"
+ topoinfo.AbstractResources = [abstractinfo]
+ mock_api_session.return_value.GetTopologyDetails = Mock(return_value=topoinfo)
+ mock_logger = Mock()
+ self.sandbox = SandboxBase(reservation_id="5487c6ce-d0b3-43e9-8ee7-e27af8406905", logger=mock_logger)
+
+ self.mock_api_session = mock_api_session
+ self.mock_logger = mock_logger
+
+ def tearDown(self):
+ pass
+
+ #================================================================
+ #test report_error function
+ def test_report_error_without_raising_error_and_without_output(self):
+ try:
+ self.sandbox.report_error(error_message="error message",
+ raise_error=False,
+ write_to_output_window=False)
+ except Exception as e:
+ self.fail("Got an exception while not expecting to: " + e.message)
+
+ self.mock_api_session.return_value.WriteMessageToReservationOutput.assert_not_called()
+
+ def test_report_error_with_raising_error_and_without_output(self):
+ with self.assertRaises(QualiError) as e:
+ self.sandbox.report_error(error_message="error message",
+ raise_error=True,
+ write_to_output_window=False)
+
+ the_exception = e.exception
+ self.assertEqual(str(the_exception),
+ "CloudShell error at 5487c6ce-d0b3-43e9-8ee7-e27af8406905. Error is: error message")
+ self.mock_api_session.return_value.WriteMessageToReservationOutput.assert_not_called()
+
+ def test_report_error_without_raising_error_and_with_output(self):
+ self.sandbox.report_error(error_message="error message",
+ raise_error=False,
+ write_to_output_window=True)
+
+ self.mock_api_session.return_value.WriteMessageToReservationOutput.assert_called_with(
+ '5487c6ce-d0b3-43e9-8ee7-e27af8406905', 'error message')
+
+ def test_report_error_with_just_to_log(self):
+ self.sandbox.report_error(error_message="error message",
+ raise_error=False,
+ write_to_output_window=False)
+
+ self.mock_api_session.return_value.WriteMessageToReservationOutput.assert_not_called()
+ self.mock_logger.error.assert_called_with('error message')
+
+ #================================================================
+ #test report_info function
+ def test_report_info_to_log_without_output(self):
+ self.sandbox.report_info(message="error message",write_to_output_window=False)
+ self.mock_api_session.return_value.WriteMessageToReservationOutput.assert_not_called()
+ self.mock_logger.info.assert_called_with('error message')
+
+ def test_report_info_to_log_with_output(self):
+ self.sandbox.report_info(message="error message",write_to_output_window=True)
+ self.mock_api_session.return_value.WriteMessageToReservationOutput.\
+ assert_called_with('5487c6ce-d0b3-43e9-8ee7-e27af8406905', 'error message')
+ self.mock_logger.info.assert_called_with('error message')
+
+
+ #================================================================
+ #test get_root_resources
+ def test_no_resources_in_sandbox(self):
+ rdi = Mock()
+ rdi.ReservationDescription = Mock()
+ rdi.ReservationDescription.Resources = []
+ self.mock_api_session.return_value.GetReservationDetails = Mock(return_value=rdi)
+
+ resources = self.sandbox.get_root_resources()
+ self.assertEqual(resources, [], "got resources, excepted none")
+
+ #---------------------------
+ @patch('sandbox_scripts.QualiEnvironmentUtils.Sandbox.ResourceBase')
+ def test_get_root_resources_with_sub_resources(self, mock_resourcebase):
+ rdi = Mock()
+ resource1 = Mock()
+ resource1.Name = "r1"
+ resource1a = Mock()
+ resource1a.Name = "r1/r2"
+ resource2 = Mock()
+ resource2.Name = "r2"
+ rdi.ReservationDescription.Resources = [resource1, resource1a, resource2]
+ rdi.ReservationDescription.TopologiesReservedResources = []
+ self.mock_api_session.return_value.GetReservationDetails = Mock(return_value=rdi)
+
+ resources = self.sandbox.get_root_resources()
+ self.assertEqual(len(resources), 2, "didn't get resources, excepted two")
+
+ #---------------------------
+ @patch('sandbox_scripts.QualiEnvironmentUtils.Sandbox.ResourceBase')
+ def test_get_root_resources_with_services_only(self, mock_resourcebase):
+ rdi = Mock()
+ Service1 = Mock()
+ Service1.Name = "s1"
+ Service2 = Mock()
+ Service2.Name = "s2"
+ rdi.ReservationDescription.Services = [Service1,Service2]
+ rdi.ReservationDescription.Resources = []
+ rdi.ReservationDescription.TopologiesReservedResources = []
+ self.mock_api_session.return_value.GetReservationDetails = Mock(return_value=rdi)
+
+ resources = self.sandbox.get_root_resources()
+ self.assertEqual(len(resources), 0, "No resources expected")
+
+ #---------------------------
+ @patch('sandbox_scripts.QualiEnvironmentUtils.Sandbox.ResourceBase')
+ def test_get_root_resources_with_services_and_resource(self, mock_resourcebase):
+ rdi = Mock()
+ Service1 = Mock()
+ Service1.Name = "s1"
+ Service2 = Mock()
+ Service2.Name = "s2"
+ resource1 = Mock()
+ resource1.Name = "r1"
+ rdi.ReservationDescription.Services = [Service1,Service2]
+ rdi.ReservationDescription.Resources = [resource1]
+ rdi.ReservationDescription.TopologiesReservedResources = []
+ self.mock_api_session.return_value.GetReservationDetails = Mock(return_value=rdi)
+
+ resources = self.sandbox.get_root_resources()
+ self.assertEqual(len(resources), 1, "No resources expected")
+
+ #---------------------------
+ @patch('sandbox_scripts.QualiEnvironmentUtils.Sandbox.ResourceBase')
+ def test_get_root_resources_without_sub_resources_and_with_alias(self, mock_resourcebase):
+ rdi = Mock()
+ resource1 = Mock()
+ resource1.Name = "r1"
+ trr = Mock()
+ trr.Name = "r1"
+ trr.Alias = "my r1"
+ trr.TopologyName = "My environment"
+ rdi.ReservationDescription.Resources = [resource1]
+ rdi.ReservationDescription.TopologiesReservedResources = [trr]
+ self.mock_api_session.return_value.GetReservationDetails = Mock(return_value=rdi)
+
+ resources = self.sandbox.get_root_resources()
+ mock_resourcebase.assert_called_with('r1', 'my r1')
+ self.assertEqual(len(resources), 1, "didn't get resources, excepted one")
+
+ #================================================================
+ #test clear_all_resources_live_status
+ def test_clear_all_resources_live_status_no_devices(self):
+ rdi = Mock()
+ rdi.ReservationDescription.Resources = []
+ rdi.ReservationDescription.TopologiesReservedResources = []
+ self.mock_api_session.return_value.GetReservationDetails = Mock(return_value=rdi)
+
+ self.sandbox.clear_all_resources_live_status()
+ self.mock_api_session.return_value.SetResourceLiveStatus.assert_not_called()
+
+ #---------------------------
+ @patch('sandbox_scripts.QualiEnvironmentUtils.Sandbox.ResourceBase')
+ def test_clear_all_resources_live_status_two_devices(self,mock_resourcebase):
+ resource1 = Mock()
+ resource1.name = "r1"
+ resource2 = Mock()
+ resource2.name = "r2"
+ rr = Mock()
+ rr = [resource1, resource2]
+ self.sandbox.get_root_resources = Mock(return_value=rr)
+
+ self.sandbox.clear_all_resources_live_status()
+ #self.mock_api_session.return_value.SetResourceLiveStatus.assert_called()
+ calls = [call('r1', ''),
+ call('r2', '')]
+ self.mock_api_session.return_value.SetResourceLiveStatus.assert_has_calls(calls)
+
+ #================================================================
+ #test activate_connectors
+ def test_activate_connectors_no_connectors_no_output(self):
+ rdi = Mock()
+ rdi.ReservationDescription.Connectors = []
+ self.mock_api_session.return_value.GetReservationDetails = Mock(return_value=rdi)
+ self.sandbox.activate_connectors(False)
+ self.mock_api_session.return_value.ConnectRoutesInReservation.assert_not_called()
+ self.mock_api_session.return_value.WriteMessageToReservationOutput.assert_not_called()
+
+ #---------------------------
+ def test_activate_connectors_no_connectors_with_output(self):
+ rdi = Mock()
+ rdi.ReservationDescription.Connectors = []
+ self.mock_api_session.return_value.GetReservationDetails = Mock(return_value=rdi)
+ self.sandbox.activate_connectors(True)
+ self.mock_api_session.return_value.ConnectRoutesInReservation.assert_not_called()
+ calls = [call('5487c6ce-d0b3-43e9-8ee7-e27af8406905', 'Connecting the connectors'),
+ call('5487c6ce-d0b3-43e9-8ee7-e27af8406905', 'No connectors to connect for reservation 5487c6ce-d0b3-43e9-8ee7-e27af8406905')]
+ self.mock_api_session.return_value.WriteMessageToReservationOutput.assert_has_calls(calls)
+
+ #---------------------------
+ def test_activate_connectors_with_connectors_with_output(self):
+ rdi = Mock()
+ connector1 = Mock()
+ connector1.State = 'Disconnected'
+ connector1.Target = 'x'
+ connector1.Source = 'y'
+ rdi.ReservationDescription.Connectors = [connector1]
+ self.mock_api_session.return_value.GetReservationDetails = Mock(return_value=rdi)
+ self.sandbox.activate_connectors(True)
+ self.mock_api_session.return_value.ConnectRoutesInReservation.assert_called()
+ calls = [call('5487c6ce-d0b3-43e9-8ee7-e27af8406905', 'Connecting the connectors'),
+ call('5487c6ce-d0b3-43e9-8ee7-e27af8406905', 'Connectors connected')]
+ self.mock_api_session.return_value.WriteMessageToReservationOutput.assert_has_calls(calls)
+
+ #---------------------------
+ def test_activate_connectors_with_connectors_already_connected_with_output(self):
+ rdi = Mock()
+ connector1 = Mock()
+ connector1.State = 'Connected'
+ connector1.Target = 'x'
+ connector1.Source = 'y'
+ rdi.ReservationDescription.Connectors = [connector1]
+ self.mock_api_session.return_value.GetReservationDetails = Mock(return_value=rdi)
+ self.sandbox.activate_connectors(True)
+ self.mock_api_session.return_value.ConnectRoutesInReservation.assert_not_called()
+ calls = [call('5487c6ce-d0b3-43e9-8ee7-e27af8406905', 'Connecting the connectors'),
+ call('5487c6ce-d0b3-43e9-8ee7-e27af8406905', 'No connectors to connect for reservation 5487c6ce-d0b3-43e9-8ee7-e27af8406905')]
+ self.mock_api_session.return_value.WriteMessageToReservationOutput.assert_has_calls(calls)
+
+ #---------------------------
+ def test_activate_connectors_with_some_of_connectors_already_connected_with_output(self):
+ rdi = Mock()
+ connector1 = Mock()
+ connector1.State = 'Connected'
+ connector1.Target = 'x'
+ connector1.Source = 'y'
+ connector2 = Mock()
+ connector2.State = 'ConnectionFailed'
+ connector2.Target = 'a'
+ connector2.Source = 'z'
+ rdi.ReservationDescription.Connectors = [connector1,connector2]
+ self.mock_api_session.return_value.GetReservationDetails = Mock(return_value=rdi)
+ self.sandbox.activate_connectors(True)
+ self.mock_api_session.return_value.ConnectRoutesInReservation.assert_called_with('5487c6ce-d0b3-43e9-8ee7-e27af8406905', ['a', 'z'], 'bi')
+ calls = [call('5487c6ce-d0b3-43e9-8ee7-e27af8406905', 'Connecting the connectors'),
+ call('5487c6ce-d0b3-43e9-8ee7-e27af8406905', 'Connectors connected')]
+ self.mock_api_session.return_value.WriteMessageToReservationOutput.assert_has_calls(calls)
+
+ #================================================================
+ #test activate_routes
+ def test_activate_routes_no_routes_no_output(self):
+ rdi = Mock()
+ rdi.ReservationDescription.RequestedRoutesInfo = []
+ self.mock_api_session.return_value.GetReservationDetails = Mock(return_value=rdi)
+ self.sandbox.activate_routes(False)
+ self.mock_api_session.return_value.ConnectRoutesInReservation.assert_not_called()
+ self.mock_api_session.return_value.WriteMessageToReservationOutput.assert_not_called()
+
+ #---------------------------
+ def test_activate_routes_no_routes_with_output(self):
+ rdi = Mock()
+ rdi.ReservationDescription.RequestedRoutesInfo = []
+ self.mock_api_session.return_value.GetReservationDetails = Mock(return_value=rdi)
+ self.sandbox.activate_routes(True)
+ self.mock_api_session.return_value.ConnectRoutesInReservation.assert_not_called()
+ calls = [call('5487c6ce-d0b3-43e9-8ee7-e27af8406905', 'Connecting routes'),
+ call('5487c6ce-d0b3-43e9-8ee7-e27af8406905', 'No routes to connect for reservation 5487c6ce-d0b3-43e9-8ee7-e27af8406905')]
+ self.mock_api_session.return_value.WriteMessageToReservationOutput.assert_has_calls(calls)
+
+ #---------------------------
+ def test_activate_routes_with_bi_routes_with_output(self):
+ rdi = Mock()
+ route1 = Mock()
+ route1.RouteType = 'bi'
+ route1.Target = 'x'
+ route1.Source = 'y'
+ rdi.ReservationDescription.RequestedRoutesInfo = [route1]
+ self.mock_api_session.return_value.GetReservationDetails = Mock(return_value=rdi)
+ self.sandbox.activate_routes(True)
+ self.mock_api_session.return_value.ConnectRoutesInReservation.assert_called_with('5487c6ce-d0b3-43e9-8ee7-e27af8406905', ['x', 'y'], 'bi')
+ calls = [call('5487c6ce-d0b3-43e9-8ee7-e27af8406905', 'Connecting routes'),
+ call('5487c6ce-d0b3-43e9-8ee7-e27af8406905', 'Routes connected')]
+ self.mock_api_session.return_value.WriteMessageToReservationOutput.assert_has_calls(calls)
+
+ #---------------------------
+ def test_activate_routes_with_uni_routes_with_output(self):
+ rdi = Mock()
+ route2 = Mock()
+ route2.RouteType = 'uni'
+ route2.Target = 'x'
+ route2.Source = 'y'
+ rdi.ReservationDescription.RequestedRoutesInfo = [route2]
+ self.mock_api_session.return_value.GetReservationDetails = Mock(return_value=rdi)
+ self.sandbox.activate_routes(True)
+ self.mock_api_session.return_value.ConnectRoutesInReservation.assert_called_with('5487c6ce-d0b3-43e9-8ee7-e27af8406905', ['y', 'x'], 'uni')
+ calls = [call('5487c6ce-d0b3-43e9-8ee7-e27af8406905', 'Connecting routes'),
+ call('5487c6ce-d0b3-43e9-8ee7-e27af8406905', 'Routes connected')]
+ self.mock_api_session.return_value.WriteMessageToReservationOutput.assert_has_calls(calls)
+
+ #================================================================
+ #test save as blueprint
+ def test_save_sandbox_as_blueprint(self):
+ self.sandbox.save_sandbox_as_blueprint('aaa')
+ self.mock_api_session.return_value.SaveReservationAsTopology.assert_called_with('5487c6ce-d0b3-43e9-8ee7-e27af8406905',
+ folderFullPath='Snapshots',
+ includeInactiveRoutes=True,
+ topologyName='aaa')
+ self.mock_api_session.return_value.UpdateTopologyOwner.assert_called_with(ownerName='bob', topologyName='Snapshots/aaa')
+
+ # ---------------------------
+ def test_save_sandbox_as_blueprint_invalid_topo_name(self):
+ self.mock_api_session.return_value.SaveReservationAsTopology.side_effect = CloudShellAPIError(100,"Invalid name","")
+ with self.assertRaises(QualiError) as e:
+ self.sandbox.save_sandbox_as_blueprint('a@aa')
+ the_exception = e.exception
+ self.assertEqual(str(the_exception),
+ "CloudShell error at 5487c6ce-d0b3-43e9-8ee7-e27af8406905. Error is: Failed to save sandbox as blueprint. Invalid name")
+ self.mock_api_session.return_value.SaveReservationAsTopology.assert_called_with('5487c6ce-d0b3-43e9-8ee7-e27af8406905',
+ folderFullPath='Snapshots',
+ includeInactiveRoutes=True,
+ topologyName='a@aa')
+ self.mock_api_session.return_value.UpdateTopologyOwner.assert_not_called()
+
+ #================================================================
+ #test power_on_vms
+ def test_power_on_vms_vm_and_resource(self):
+
+ resource1 = Mock()
+ resource1.name = "r1"
+ resource1.is_app.return_value = True
+ resource2 = Mock()
+ resource2.name = "r2"
+ resource2.is_app.return_value = False
+ rr = Mock()
+ rr = [resource1, resource2]
+ self.sandbox.get_root_resources = Mock(return_value=rr)
+ self.sandbox.power_on_vms()
+ self.mock_api_session.return_value.ExecuteResourceConnectedCommand.assert_called_with('5487c6ce-d0b3-43e9-8ee7-e27af8406905', 'r1', 'PowerOn', 'power')
+
+ # ---------------------------
+ def test_power_on_vms_only_vms(self):
+
+ resource1 = Mock()
+ resource1.name = "r1"
+ resource1.is_app.return_value = True
+ resource2 = Mock()
+ resource2.name = "r2"
+ resource2.is_app.return_value = True
+ rr = Mock()
+ rr = [resource1, resource2]
+ self.sandbox.get_root_resources = Mock(return_value=rr)
+ self.sandbox.power_on_vms()
+ calls = [call('5487c6ce-d0b3-43e9-8ee7-e27af8406905', 'r1', 'PowerOn', 'power'),
+ call('5487c6ce-d0b3-43e9-8ee7-e27af8406905', 'r2', 'PowerOn', 'power')]
+
+ self.mock_api_session.return_value.ExecuteResourceConnectedCommand.assert_has_calls(calls)
+
+ # ---------------------------
+ def test_power_on_vms_no_vms(self):
+
+ resource1 = Mock()
+ resource1.name = "r1"
+ resource1.is_app.return_value = False
+ resource2 = Mock()
+ resource2.name = "r2"
+ resource2.is_app.return_value = False
+ rr = Mock()
+ rr = [resource1, resource2]
+ self.sandbox.get_root_resources = Mock(return_value=rr)
+ self.sandbox.power_on_vms()
+ self.mock_api_session.return_value.ExecuteResourceConnectedCommand.assert_not_called()
+
+#get_Apps_resources
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sandbox_scripts/environment/savesnapshot/SaveSnapshot.py b/sandbox_scripts/environment/savesnapshot/SaveSnapshot.py
index 4f319f2..3aa1565 100644
--- a/sandbox_scripts/environment/savesnapshot/SaveSnapshot.py
+++ b/sandbox_scripts/environment/savesnapshot/SaveSnapshot.py
@@ -1,8 +1,7 @@
# coding=utf-8
-from sandbox_scripts.QualiEnvironmentUtils.Networking.NetworkingSaveNRestore import *
from cloudshell.helpers.scripts import cloudshell_scripts_helpers as helpers
-from sandbox_scripts.profiler.env_profiler import profileit
+from sandbox_scripts.helpers.Networking.NetworkingSaveNRestore import *
class EnvironmentSaveSnapshot:
diff --git a/sandbox_scripts/environment/setup/setup_VM.py b/sandbox_scripts/environment/setup/setup_VM.py
index c6f654c..eb06528 100644
--- a/sandbox_scripts/environment/setup/setup_VM.py
+++ b/sandbox_scripts/environment/setup/setup_VM.py
@@ -1,9 +1,5 @@
-from multiprocessing.pool import ThreadPool
-from threading import Lock
-from sandbox_scripts.profiler.env_profiler import profileit
-from sandbox_scripts.QualiEnvironmentUtils.Networking.NetworkingSaveNRestore import *
-from cloudshell.core.logger import qs_logger
-from sandbox_scripts.helpers.resource_helpers import *
+from sandbox_scripts.helpers.Networking.NetworkingSaveNRestore import *
+
class EnvironmentSetupVM(object):
@@ -24,6 +20,7 @@ def execute(self):
reservation_details = api.GetReservationDetails(self.reservation_id)
sandbox = SandboxBase(self.reservation_id, self.logger)
+ #TODO: don't use networking save and restore to figure if it's a snapshot setup
saveNRestoreTool = NetworkingSaveRestore(sandbox)
if saveNRestoreTool.get_storage_client():
if saveNRestoreTool.is_snapshot():
diff --git a/sandbox_scripts/environment/setup/setup_resources.py b/sandbox_scripts/environment/setup/setup_resources.py
index b81e4d5..fd582c4 100644
--- a/sandbox_scripts/environment/setup/setup_resources.py
+++ b/sandbox_scripts/environment/setup/setup_resources.py
@@ -1,9 +1,11 @@
# coding=utf-8
-from sandbox_scripts.QualiEnvironmentUtils.Sandbox import *
-from sandbox_scripts.QualiEnvironmentUtils.Networking.NetworkingSaveNRestore import *
-from sandbox_scripts.QualiEnvironmentUtils.Networking.NetworkingHealthCheck import *
-from sandbox_scripts.profiler.env_profiler import profileit
-
+#from sandbox_scripts.helpers.Networking.NetworkingHealthCheck import *
+from cloudshell.helpers.scripts import cloudshell_scripts_helpers as helpers
+from sandbox_scripts.helpers.Networking.NetworkingSaveNRestore import NetworkingSaveRestore
+from sandbox_scripts.QualiEnvironmentUtils.Sandbox import SandboxBase
+from cloudshell.core.logger.qs_logger import get_qs_logger
+from sandbox_scripts.QualiEnvironmentUtils.QualiUtils import QualiError
+import os, sys
class EnvironmentSetupResources(object):
def __init__(self):
@@ -12,7 +14,6 @@ def __init__(self):
log_group=self.reservation_id,
log_category='Setup')
- #@profileit(scriptName='Setup')
def execute(self):
sandbox = SandboxBase(self.reservation_id, self.logger)
saveNRestoreTool = NetworkingSaveRestore(sandbox)
@@ -35,11 +36,9 @@ def execute(self):
ignore_models=['Generic TFTP server', 'Config Set Pool','Generic FTP server','netscout switch 3912']
if saveNRestoreTool.get_storage_client():
-
-
if saveNRestoreTool.is_snapshot():
saveNRestoreTool.load_config(config_stage='Snapshots', config_type='Running',
- ignore_models=ignore_models)
+ ignore_models=ignore_models)
else:
saveNRestoreTool.load_config(config_stage='Gold', config_type='Running',
diff --git a/sandbox_scripts/QualiEnvironmentUtils/Networking/__init__.py b/sandbox_scripts/environment/setup/tests/__init__.py
similarity index 100%
rename from sandbox_scripts/QualiEnvironmentUtils/Networking/__init__.py
rename to sandbox_scripts/environment/setup/tests/__init__.py
diff --git a/sandbox_scripts/environment/setup/tests/test_setup_resources.py b/sandbox_scripts/environment/setup/tests/test_setup_resources.py
new file mode 100644
index 0000000..f75d181
--- /dev/null
+++ b/sandbox_scripts/environment/setup/tests/test_setup_resources.py
@@ -0,0 +1,68 @@
+import unittest
+from mock import patch, Mock
+from sandbox_scripts.environment.setup.setup_resources import EnvironmentSetupResources
+import json
+import os
+
+
+resContext = '''{"id":"5487c6ce-d0b3-43e9-8ee7-e27af8406905",
+ "ownerUser":"bob",
+ "ownerPass":"nIqm+BG6ZGJjby5hUittVFFJASc=",
+ "domain":"Global",
+ "environmentName":"My environment",
+ "description":"New demo environment",
+ "parameters":
+ { "globalInputs": [],
+ "resourceRequirements":[],
+ "resourceAdditionalInfo":[]}}'''
+
+conContext = '''{"serverAddress": "localhost",
+"adminAuthToken": "anAdminToken"}'''
+
+class SetupResourcesTests(unittest.TestCase):
+
+ @patch('sandbox_scripts.environment.setup.setup_resources.get_qs_logger')
+ def setUp(self, mock_logger):
+ os.environ['reservationContext'] = resContext
+ os.environ['qualiConnectivityContext'] = conContext
+ self.setup_script = EnvironmentSetupResources()
+
+ def tearDown(self):
+ pass
+
+ @patch('cloudshell.helpers.scripts.cloudshell_scripts_helpers.get_api_session')
+ @patch('sandbox_scripts.environment.setup.setup_resources.SandboxBase')
+ @patch('sandbox_scripts.environment.setup.setup_resources.NetworkingSaveRestore')
+ def test_flow_ok_with_snapshots(self, mock_save, mock_sandboxbase, mock_api_session):
+
+ #tli = Mock()
+ #tli.Topologies = ["My environment"]
+ #mock_api_session.return_value.GetActiveTopologyNames = Mock(return_value = tli)
+ mock_save.return_value.is_snapshot.return_value = True
+ self.setup_script.execute()
+ mock_api_session.return_value.WriteMessageToReservationOutput.assert_called_with(message='Beginning resources config load', reservationId=u'5487c6ce-d0b3-43e9-8ee7-e27af8406905')
+ mock_sandboxbase.return_value.clear_all_resources_live_status.assert_called_with()
+ mock_save.return_value.load_config.assert_called_with(config_stage='Snapshots', config_type='Running', ignore_models=['Generic TFTP server', 'Config Set Pool', 'Generic FTP server', 'netscout switch 3912'])
+ mock_sandboxbase.return_value.power_on_vms.assert_called_with()
+ mock_sandboxbase.return_value.activate_all_routes_and_connectors.assert_called_with()
+
+ @patch('cloudshell.helpers.scripts.cloudshell_scripts_helpers.get_api_session')
+ @patch('sandbox_scripts.environment.setup.setup_resources.SandboxBase')
+ @patch('sandbox_scripts.environment.setup.setup_resources.NetworkingSaveRestore')
+ def test_flow_ok_with_gold(self, mock_save, mock_sandboxbase, mock_api_session):
+
+ #tli = Mock()
+ #tli.Topologies = ["My environment"]
+ #mock_api_session.return_value.GetActiveTopologyNames = Mock(return_value = tli)
+ mock_save.return_value.is_snapshot.return_value = False
+ self.setup_script.execute()
+ mock_api_session.return_value.WriteMessageToReservationOutput.assert_called_with(message='Beginning resources config load', reservationId=u'5487c6ce-d0b3-43e9-8ee7-e27af8406905')
+ mock_sandboxbase.return_value.clear_all_resources_live_status.assert_called_with()
+ mock_save.return_value.load_config.assert_called_with(config_set_name='', config_stage='Gold', config_type='Running', ignore_models=['Generic TFTP server', 'Config Set Pool', 'Generic FTP server', 'netscout switch 3912'])
+ mock_sandboxbase.return_value.power_on_vms.assert_called_with()
+ mock_sandboxbase.return_value.activate_all_routes_and_connectors.assert_called_with()
+
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sandbox_scripts/environment/teardown/teardown_VM.py b/sandbox_scripts/environment/teardown/teardown_VM.py
index 40a8f38..29b8c4c 100644
--- a/sandbox_scripts/environment/teardown/teardown_VM.py
+++ b/sandbox_scripts/environment/teardown/teardown_VM.py
@@ -1,11 +1,10 @@
-from sandbox_scripts.QualiEnvironmentUtils.Networking.NetworkingSaveNRestore import *
+from multiprocessing.pool import ThreadPool
+from threading import Lock
+
from cloudshell.core.logger import qs_logger
-from sandbox_scripts.profiler.env_profiler import profileit
-from sandbox_scripts.helpers.resource_helpers import get_vm_custom_param, get_resources_created_in_res
+from sandbox_scripts.helpers.Networking.NetworkingSaveNRestore import *
-from multiprocessing.pool import ThreadPool
-from threading import Lock
class EnvironmentTeardownVM:
REMOVE_DEPLOYED_RESOURCE_ERROR = 153
diff --git a/sandbox_scripts/environment/teardown/teardown_resources.py b/sandbox_scripts/environment/teardown/teardown_resources.py
index 0c28f36..781cb0d 100644
--- a/sandbox_scripts/environment/teardown/teardown_resources.py
+++ b/sandbox_scripts/environment/teardown/teardown_resources.py
@@ -1,7 +1,7 @@
# coding=utf-8
-from sandbox_scripts.QualiEnvironmentUtils.Networking.NetworkingSaveNRestore import *
from cloudshell.core.logger import qs_logger
-from sandbox_scripts.profiler.env_profiler import profileit
+
+from sandbox_scripts.helpers.Networking.NetworkingSaveNRestore import *
class EnvironmentTeardownResources:
diff --git a/sandbox_scripts/QualiEnvironmentUtils/Networking/NetworkingHealthCheck.py b/sandbox_scripts/helpers/Networking/NetworkingHealthCheck.py
similarity index 100%
rename from sandbox_scripts/QualiEnvironmentUtils/Networking/NetworkingHealthCheck.py
rename to sandbox_scripts/helpers/Networking/NetworkingHealthCheck.py
diff --git a/sandbox_scripts/QualiEnvironmentUtils/Networking/NetworkingSaveNRestore.py b/sandbox_scripts/helpers/Networking/NetworkingSaveNRestore.py
similarity index 99%
rename from sandbox_scripts/QualiEnvironmentUtils/Networking/NetworkingSaveNRestore.py
rename to sandbox_scripts/helpers/Networking/NetworkingSaveNRestore.py
index 580d5c2..f144ccf 100644
--- a/sandbox_scripts/QualiEnvironmentUtils/Networking/NetworkingSaveNRestore.py
+++ b/sandbox_scripts/helpers/Networking/NetworkingSaveNRestore.py
@@ -11,17 +11,6 @@
from sandbox_scripts.QualiEnvironmentUtils.StorageManager import StorageManager
-class image_struct:
- def __init__(self, path, version):
- self.path = path
- self.version = version
-
-class load_result_struct:
- def __init__(self, resource_name):
- self.run_result = True
- self.resource_name = resource_name
- self.message = ""
-
class NetworkingSaveRestore(object):
def __init__(self, sandbox):
"""
@@ -447,4 +436,16 @@ def is_resources_in_reservation_to_restore(self,ignore_models):
# ----------------------------------
# ----------------------------------
def get_storage_client(self):
- return self.storage_client
\ No newline at end of file
+ return self.storage_client
+
+class image_struct:
+ def __init__(self, path, version):
+ self.path = path
+ self.version = version
+
+class load_result_struct:
+ def __init__(self, resource_name):
+ self.run_result = True
+ self.resource_name = resource_name
+ self.message = ""
+
diff --git a/sandbox_scripts/helpers/Networking/__init__.py b/sandbox_scripts/helpers/Networking/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/test_requirements.txt b/test_requirements.txt
new file mode 100644
index 0000000..3428dcd
--- /dev/null
+++ b/test_requirements.txt
@@ -0,0 +1,8 @@
+nose
+coverage
+unittest2
+mock
+jsonpickle
+nose-exclude
+coveralls
+