Skip to content

Commit 177dfd7

Browse files
committed
update services script added
1 parent d62b619 commit 177dfd7

36 files changed

+595
-293
lines changed

automation_api_scripts/__init__.py

Whitespace-only changes.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from cloudshell.api.cloudshell_api import CloudShellAPISession
2+
3+
SANDBOX_ID = "6c30767e-c495-4d3a-9a1b-c25a335d8205"
4+
5+
api = CloudShellAPISession(host="localhost", username="admin", password="admin", domain="Global")
6+
res = api.AddRoutesToReservation(reservationId=SANDBOX_ID,
7+
sourceResourcesFullPath="DUT Mock 2/Port 1",
8+
targetResourcesFullPath="DUT Mock 2/Port 1",
9+
mappingType="bi",
10+
routeAlias="test api")
11+
pass
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import time
2+
3+
from cloudshell.api.cloudshell_api import CloudShellAPISession
4+
5+
# TARGET_RESOURCE = "L1Mock1"
6+
TARGET_RESOURCE = "DUT Mock 2"
7+
api = CloudShellAPISession(host="localhost", username="admin", password="admin", domain="Global")
8+
res = api.GetResourceMappings(resources=[TARGET_RESOURCE])
9+
# res = api.MapPorts(sourcePort="L1Mock1/Blade 1/Port 004",
10+
# destinationPort="L1Mock1/Blade 1/Port 004",
11+
# mappingType="bi")
12+
pass

packaging-api-samples/__init__.py

Whitespace-only changes.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from cloudshell.api.cloudshell_api import CloudShellAPISession
2+
from quali_api import QualiAPISession
3+
import credentials
4+
from update_services import update_services_flow
5+
6+
7+
def main():
8+
import argparse
9+
parser = argparse.ArgumentParser()
10+
parser.add_argument("target_service")
11+
parser.add_argument("old_vlan")
12+
parser.add_argument("new_vlan")
13+
args = parser.parse_args()
14+
target_service = args.target_service
15+
old_vlan = args.old_vlan
16+
new_vlan = args.new_vlan
17+
18+
my_api = CloudShellAPISession(host=credentials.HOST,
19+
username=credentials.USER,
20+
password=credentials.PASSWORD,
21+
domain=credentials.DOMAIN)
22+
my_quali_api = QualiAPISession(host=credentials.HOST,
23+
username=credentials.USER,
24+
password=credentials.PASSWORD,
25+
domain=credentials.DOMAIN)
26+
update_services_flow(my_api, my_quali_api, target_service, old_vlan, new_vlan)
27+
28+
29+
if __name__ == "__main__":
30+
main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
VLAN_MANUAL_SERVICE = "VLAN Manual"
2+
VLAN_ID_ATTR = "VLAN ID"
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from cloudshell.api.cloudshell_api import CloudShellAPISession
2+
from typing import List
3+
from timeit import default_timer
4+
5+
6+
def find_blueprints_flow(api: CloudShellAPISession, target_service_name: str, old_vlan: str) -> List[str]:
7+
print("starting blueprint search")
8+
start = default_timer()
9+
all_blueprints = api.GetTopologiesByCategory().Topologies
10+
print(f"System Blueprint Count: {len(all_blueprints)}")
11+
12+
target_blueprints = []
13+
for blueprint in all_blueprints:
14+
services = api.GetTopologyDetails(blueprint).Services
15+
for curr_service in services:
16+
if curr_service.ServiceName == target_service_name:
17+
attrs = curr_service.Attributes
18+
vlan_id = [x for x in attrs if x.Name == "VLAN ID"][0].Value
19+
if vlan_id == old_vlan:
20+
print(f"found target blueprint {blueprint}")
21+
target_blueprints.append(blueprint)
22+
break
23+
print(f"Target blueprints found: {len(target_blueprints)}")
24+
print(f"search done after {int(default_timer() - start)} seconds")
25+
# need only the blueprint name for quali api, not the full path
26+
return [x.split("/")[-1] for x in target_blueprints]
27+
28+
29+
if __name__ == "__main__":
30+
import credentials
31+
import constants
32+
33+
OLD_VLAN = "43"
34+
api = CloudShellAPISession(host=credentials.HOST,
35+
username=credentials.USER,
36+
password=credentials.PASSWORD,
37+
domain=credentials.DOMAIN)
38+
found = find_blueprints_flow(api, constants.VLAN_MANUAL_SERVICE, OLD_VLAN)
39+
print(f"found: {found}")
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import os
2+
3+
import update_package
4+
from quali_api import QualiAPISession
5+
from timeit import default_timer
6+
7+
8+
def process_blueprint_flow(quali_api: QualiAPISession, blueprint_name: str, target_service: str, new_vlan_id: str):
9+
10+
print(f"processing blueprint {blueprint_name}")
11+
start = default_timer()
12+
13+
# download package
14+
zip_name = f"{blueprint_name}.zip"
15+
quali_api.export_package(blueprint_full_names=[blueprint_name],
16+
file_path=zip_name)
17+
18+
# remove unneeded files
19+
update_package.clean_bp_archive(zip_name)
20+
21+
# update target attribute
22+
update_package.edit_vlan_id_in_package(zip_name, target_service, new_vlan_id)
23+
24+
# re-upload
25+
quali_api.import_package(zip_name)
26+
27+
# delete zip archive
28+
os.remove(zip_name)
29+
print(f"done processing {blueprint_name} after {int(default_timer() - start)} seconds")
30+
31+
32+
if __name__ == "__main__":
33+
import credentials
34+
import constants
35+
TARGET_BLUEPRINT = "vlan dev"
36+
NEW_VLAN_ID = "122"
37+
api = QualiAPISession(host=credentials.HOST,
38+
username=credentials.USER,
39+
password=credentials.PASSWORD,
40+
domain=credentials.DOMAIN)
41+
process_blueprint_flow(api, TARGET_BLUEPRINT, constants.VLAN_MANUAL_SERVICE, NEW_VLAN_ID)
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import requests
2+
from typing import List
3+
4+
5+
class QualiAPISession:
6+
def __init__(self, host, username='', password='', domain='Global', token_id='', port=9000):
7+
self.session = requests.Session()
8+
self.base_url = f"http://{host}:{port}/Api"
9+
self._json_header = {"Content-Type": "application/json"}
10+
self.login(username, password, token_id, domain)
11+
12+
def login(self, username="", password="", token_id="", domain="Global"):
13+
if token_id:
14+
body = {"Token": token_id, "Domain": domain}
15+
elif username and password:
16+
body = {"Username": username, "Password": password, "Domain": domain}
17+
else:
18+
raise ValueError("Must supply Username / Password OR a token_id")
19+
url = f"{self.base_url}/Auth/Login"
20+
login_result = requests.put(url, json=body, headers=self._json_header)
21+
if not login_result.ok:
22+
raise Exception(f"Failed Quali API login. Status {login_result.status_code}: {login_result.text}")
23+
24+
# strip the extraneous quotes
25+
token_str = login_result.text[1:-1]
26+
self.session.headers.update({"Authorization": f"Basic {token_str}"})
27+
28+
@staticmethod
29+
def _validate_response(response: requests.Response):
30+
if not response.ok:
31+
response.raise_for_status()
32+
33+
def import_package(self, package_filepath: str):
34+
"""
35+
Push a zipped Package file into the CloudShell Server
36+
provide full path to zip file
37+
"""
38+
url = f"{self.base_url}/Package/ImportPackage"
39+
with open(package_filepath, "rb") as package_file:
40+
package_content = package_file.read()
41+
response = self.session.post(url, files={'QualiPackage': package_content})
42+
self._validate_response(response)
43+
44+
def export_package(self, blueprint_full_names: List[str], file_path: str):
45+
"""
46+
Export one or more multiple blueprints from CloudShell as a Quali Package
47+
pass file name to export to local dir, or full path
48+
"""
49+
url = f"{self.base_url}/Package/ExportPackage"
50+
body = {"TopologyNames": blueprint_full_names}
51+
response = self.session.post(url, json=body, headers=self._json_header)
52+
self._validate_response(response)
53+
with open(file_path, "wb") as target_file:
54+
target_file.write(response.content)
55+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
cloudshell-automation-api
2+
quali-utils # from cloudshell download center
3+
requests
4+
cloudshell-scriptfoundry
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import os
2+
import shutil
3+
import zipfile
4+
5+
from quali_utils.quali_packaging import PackageEditor
6+
import constants
7+
8+
9+
def _clean_bp_package(base_path: str):
10+
"""
11+
clean out unwanted folders
12+
"""
13+
dir_contents = os.listdir(base_path)
14+
for item in dir_contents:
15+
if item.endswith(".xml"):
16+
continue
17+
if item == "Topologies":
18+
continue
19+
full_path = os.path.join(base_path, item)
20+
shutil.rmtree(full_path)
21+
22+
23+
def clean_bp_archive(package_path: str):
24+
"""
25+
1. unzip the package
26+
2. clean out package for everything except Topology xml
27+
3. zip everything back up
28+
"""
29+
temp_folder = "temp_bp_extracted"
30+
31+
# UNZIP PACKAGE TO TEMP FOLDER
32+
with zipfile.ZipFile(package_path, 'r') as zip_ref:
33+
zip_ref.extractall(temp_folder)
34+
35+
# CLEAR OUT EVERYTHING EXCEPT APP TEMPLATES AND METADATA XML
36+
_clean_bp_package(temp_folder)
37+
38+
# REZIP TEMP FOLDER BACK TO ZIP PACKAGE
39+
package_file_name = package_path.split("/")[-1].split(".zip")[0] # handle full path and remove zip extension
40+
shutil.make_archive(package_file_name, 'zip', temp_folder)
41+
42+
# clean up temp folder
43+
shutil.rmtree(temp_folder)
44+
45+
46+
def edit_vlan_id_in_package(package_path: str, target_service: str, new_vlan_id: str):
47+
p = PackageEditor()
48+
p.load(package_path)
49+
bp_names = p.get_topology_names()
50+
if len(bp_names) > 1:
51+
raise ValueError("This script assumes only one blueprint per package")
52+
bp_name = bp_names[0]
53+
p.set_attribute_to_service(topology_name=bp_name,
54+
service_alias=target_service,
55+
attribute_name=constants.VLAN_ID_ATTR,
56+
attribute_value=new_vlan_id,
57+
publish=False)
58+
pass
59+
60+
61+
if __name__ == "__main__":
62+
TARGET_PACKAGE = "vlan dev.zip"
63+
TARGET_SERVICE = "VLAN Manual"
64+
clean_bp_archive(TARGET_PACKAGE)
65+
edit_vlan_id_in_package(TARGET_PACKAGE, TARGET_SERVICE, "42")
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
from cloudshell.api.cloudshell_api import CloudShellAPISession
2+
from quali_api import QualiAPISession
3+
from find_blueprints import find_blueprints_flow
4+
from process_blueprint import process_blueprint_flow
5+
from timeit import default_timer
6+
7+
8+
def update_services_flow(api: CloudShellAPISession,
9+
quali_api: QualiAPISession,
10+
target_service: str,
11+
old_vlan: str,
12+
new_vlan: str):
13+
start = default_timer()
14+
print(f"Starting Flow. Changing service '{target_service}' VLAN {old_vlan} --> {new_vlan}")
15+
16+
# find target blueprints
17+
target_blueprints = find_blueprints_flow(api, target_service, old_vlan)
18+
if not target_blueprints:
19+
print("No blueprints found")
20+
return
21+
22+
# process bluperints
23+
for curr_bp in target_blueprints:
24+
process_blueprint_flow(quali_api, curr_bp, target_service, new_vlan)
25+
26+
print(f"Update flow done after total {int(default_timer() - start)} seconds")
27+
28+
29+
if __name__ == "__main__":
30+
import credentials
31+
import constants
32+
33+
OLD_VLAN_ID = "122"
34+
NEW_VLAN_ID = "129"
35+
my_api = CloudShellAPISession(host=credentials.HOST,
36+
username=credentials.USER,
37+
password=credentials.PASSWORD,
38+
domain=credentials.DOMAIN)
39+
my_quali_api = QualiAPISession(host=credentials.HOST,
40+
username=credentials.USER,
41+
password=credentials.PASSWORD,
42+
domain=credentials.DOMAIN)
43+
update_services_flow(my_api, my_quali_api, constants.VLAN_MANUAL_SERVICE, OLD_VLAN_ID, NEW_VLAN_ID)

packaging-api-samples/upload-app/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)