Skip to content

Commit 3cd3f18

Browse files
committed
updating
1 parent 72f399c commit 3cd3f18

File tree

21 files changed

+840
-27
lines changed

21 files changed

+840
-27
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ DEBUG/
33
quali_api_sanity_exe/
44
*.zip
55
Orchestration-Templates/
6+
Bug-exploration/
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from cloudshell.api.cloudshell_api import CloudShellAPISession
2+
3+
user = "admin"
4+
password = "admin"
5+
server = "localhost"
6+
domain = "Global"
7+
8+
TOTAL_RESOURCES = 1000
9+
10+
api = CloudShellAPISession(host=server, username=user, password=password, domain=domain)
11+
12+
print("building resources...")
13+
for i in range(TOTAL_RESOURCES):
14+
print("resource" + str(i + 1))
15+
api.CreateResource(resourceModel="Generic Dut",
16+
resourceName="generic_dummy_b_{}".format(str(i + 1)),
17+
resourceAddress="{0}.{0}.{0}.{0}".format(str(i)),
18+
folderFullPath="dummy resources 2")
19+
20+
print("done")

generic-orchestration-samples/setup_demo_flow/first_module.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ def first_module_flow(sandbox, components=None):
1212
:param components
1313
:return:
1414
"""
15+
if not components:
16+
pass
17+
1518
api = sandbox.automation_api
1619
res_id = sandbox.id
1720
warn_print(api, sandbox.id, "=== Hello from sandbox!!!! ===")

generic-orchestration-samples/setup_send_mail/sb_rest/sandbox_rest_api.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,12 @@ def get_user_token(self, user_name):
192192
response = requests.post(url=url, data=json.dumps(body), headers=self._auth_headers)
193193
return self._handle_res_json(response)
194194

195+
def invalidate_token(self, token):
196+
url = self._no_version_base_url + "/token/{}".format(token)
197+
response = requests.delete(url=url, headers=self._auth_headers)
198+
return self._handle_res_json(response)
199+
200+
195201

196202
if __name__ == "__main__":
197203
server = "localhost"
@@ -200,7 +206,6 @@ def get_user_token(self, user_name):
200206
domain = "Global"
201207

202208
sb_rest = SandboxRest(server, cs_user, password, domain)
203-
sandbox_info = sb_rest.get_sandboxes()
204-
info_json = json.dumps(sandbox_info, indent=2)
205-
print(info_json)
209+
delete_res = sb_rest.invalidate_token("PZc7BIDg40KnqY87p98MRQ2")
210+
sandbox_info = sb_rest.get_user_token("admin")
206211
pass
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
from quali_utils.quali_packaging import PackageEditor, TopologyApp, AppResource, AppResourceInner, DeploymentService
2+
import requests
3+
from copy import deepcopy
4+
5+
# Create a new package in the local file system
6+
package_base_path = "C:\\quali_package_demo"
7+
# package_name = "demo_apps_blueprint.zip"
8+
package_name = "empty_blueprint.zip"
9+
p = PackageEditor()
10+
11+
package_path = "{}\\{}".format(package_base_path, package_name)
12+
13+
# create empty package
14+
p.create(package_path)
15+
16+
# Load the package and prepare for edit
17+
p.load(package_path)
18+
19+
# Edit the package: f.e add new family
20+
# p.add_topology(topology_name="temp_blueprint", is_public="True", image_file_path="", default_duration="15",
21+
# instructions="", categories="", diagram_zoom="0")
22+
23+
topology_name = p.get_topology_names()[0]
24+
# p.change_topology_name_and_alias(topology_name=names[0], new_name="new blueprint name")
25+
# names_new = p.get_topology_names()
26+
27+
p.add_topology("my_bp", True, "", "30", "", "", "100")
28+
29+
apps = p.get_apps(topology_name)
30+
app1 = apps[0]
31+
32+
new_app_copy = deepcopy(app1)
33+
new_app_copy.templateName = "my template from api"
34+
new_app_copy.appResource.name = "my temp app"
35+
36+
37+
p.add_app(topology_name, new_app_copy)
38+
pass
39+
40+
# ==== IMPORT PACKAGE INTO CLOUDSHELL =====
41+
# authenticate quali api
42+
r = requests.put('http://localhost:9000/Api/Auth/Login', {"username": "admin", "password": "admin", "domain": "Global"})
43+
authcode = "Basic " + r._content[1:-1]
44+
45+
# 2 Open the package before import
46+
fileobj = open(package_path, 'rb')
47+
48+
# 3 Send to CloudShell by calling Import Package REST API
49+
r = requests.post('http://localhost:9000/API/Package/ImportPackage',
50+
headers={"Authorization": authcode},
51+
files={"file": fileobj})
52+
print(r._content)
53+
print(r.ok)

packaging-api-samples/packaging_api_demo.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,5 @@
5858
r = requests.post('http://localhost:9000/API/Package/ImportPackage',
5959
headers={"Authorization": authcode},
6060
files={"file": fileobj})
61-
print r._content
62-
print r.ok
61+
print(r._content)
62+
print(r.ok)
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Many thanks to https://pymotw.com/2/urllib2/#uploading-files
2+
3+
import mimetools
4+
import mimetypes
5+
import itertools
6+
7+
8+
class MultiPartForm(object):
9+
"""Accumulate the data to be used when posting a form."""
10+
11+
def __init__(self):
12+
self.form_fields = []
13+
self.files = []
14+
self.boundary = mimetools.choose_boundary()
15+
return
16+
17+
def get_content_type(self):
18+
return 'multipart/form-data; boundary=%s' % self.boundary
19+
20+
def add_field(self, name, value):
21+
"""Add a simple field to the form data."""
22+
self.form_fields.append((name, value))
23+
return
24+
25+
def add_file(self, fieldname, filename, fileHandle, mimetype=None):
26+
"""Add a file to be uploaded."""
27+
body = fileHandle.read()
28+
if mimetype is None:
29+
mimetype = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
30+
self.files.append((fieldname, filename, mimetype, body))
31+
return
32+
33+
def __str__(self):
34+
"""Return a string representing the form data, including attached files."""
35+
# Build a list of lists, each containing "lines" of the
36+
# request. Each part is separated by a boundary string.
37+
# Once the list is built, return a string where each
38+
# line is separated by '\r\n'.
39+
parts = []
40+
part_boundary = '--' + self.boundary
41+
42+
# Add the form fields
43+
parts.extend(
44+
[part_boundary,
45+
'Content-Disposition: form-data; name="%s"' % name,
46+
'',
47+
value,
48+
]
49+
for name, value in self.form_fields
50+
)
51+
52+
# Add the files to upload
53+
parts.extend(
54+
[part_boundary,
55+
'Content-Disposition: file; name="%s"; filename="%s"' % \
56+
(field_name, filename),
57+
'Content-Type: %s' % content_type,
58+
'',
59+
body,
60+
]
61+
for field_name, filename, content_type, body in self.files
62+
)
63+
64+
# Flatten the list and add closing boundary marker,
65+
# then return CR+LF separated data
66+
flattened = list(itertools.chain(*parts))
67+
flattened.append('--' + self.boundary + '--')
68+
flattened.append('')
69+
return '\r\n'.join(flattened)
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
from urllib.request import urlopen, Request, build_opener, HTTPHandler
2+
import re
3+
import ntpath
4+
5+
from multipart_formdata import MultiPartForm
6+
7+
8+
class QualiApi(object):
9+
def __init__(self, host, username, password, domain="Global", port="9000"):
10+
self.host = host
11+
self.port = port
12+
13+
self.opener = build_opener(HTTPHandler)
14+
15+
login_url = 'http://{0}:{1}/API/Auth/Login'.format(host, port)
16+
data = 'username={0}&password={1}&domain={2}' \
17+
.format(username,
18+
password.replace('+', '%2B').replace('/', '%2F').replace('=', '%3D'),
19+
domain)
20+
request = Request(url=login_url, data=bytes(data))
21+
request.add_header('Content-Type', 'application/x-www-form-urlencoded')
22+
backup = request.get_method
23+
request.get_method = lambda: 'PUT'
24+
url = self.opener.open(request)
25+
self.token = url.read()
26+
self.token = re.sub(r'^"', '', self.token)
27+
self.token = re.sub(r'"$', '', self.token)
28+
request.get_method = backup
29+
30+
def upload_test_to_shared(self, test_location, target_location):
31+
"""
32+
:param test_location:
33+
:param target_location: folder hierarchy in shared folder. the path should be separated with /.
34+
if empty, test will be created in root shared folder.
35+
:type test_location: str
36+
:type target_location: str
37+
:return:
38+
"""
39+
if target_location.startswith('Shared'):
40+
target_location = target_location.lstrip('Shared').lstrip('/')
41+
42+
head, tail = ntpath.split(test_location)
43+
filename = tail or ntpath.basename(head)
44+
45+
form = MultiPartForm()
46+
47+
with open(test_location) as file_handle:
48+
form.add_file('test', filename, fileHandle=file_handle)
49+
50+
body = str(form)
51+
url = 'http://{0}:{1}/API/Scheduling/Tests/Shared/{2}'.format(self.host, self.port, target_location)
52+
request = Request(url)
53+
request.add_header('Content-type', form.get_content_type())
54+
request.add_header('Content-length', str(len(body)))
55+
request.add_header('Authorization', 'Basic {}'.format(self.token))
56+
request.data = body
57+
58+
try:
59+
response = self.opener.open(request)
60+
result = response.read()
61+
except Exception as e:
62+
print(str(e))
63+
raise e
64+
65+
return result
66+
67+
def delete_test_from_shared(self, test_location):
68+
url = 'http://{0}:{1}/API/Scheduling/Tests/Shared/{2}'.format(self.host, self.port, test_location)
69+
request = Request(url)
70+
request.get_method = lambda: 'DELETE'
71+
request.add_header('Authorization', 'Basic {}'.format(self.token))
72+
73+
try:
74+
response = self.opener.open(request)
75+
result = response.read()
76+
except Exception as e:
77+
print(str(e))
78+
raise e
79+
80+
return result
81+
82+
"""
83+
def delete_single_test_from_shared(test_location):
84+
api = QualiApi('localhost', '9000', 'admin', 'admin', 'Global')
85+
result = api.delete_test_from_shared(test_location)
86+
# verify response (result)
87+
print 'success'
88+
"""
89+
90+
def get_tests_from_shared(self, test_location):
91+
url = 'http://{0}:{1}/API/Scheduling/Explorer/Shared/{2}'.format(self.host, self.port, test_location)
92+
request = Request(url)
93+
request.get_method = lambda: 'GET'
94+
request.add_header('Authorization', 'Basic {}'.format(self.token))
95+
96+
try:
97+
response = self.opener.open(request)
98+
result = response.read()
99+
except Exception as e:
100+
print(str(e))
101+
raise e
102+
103+
return result
104+
105+
106+
if __name__ == "__main__":
107+
api = QualiApi("localhost", "admin", "admin")
108+
tests = api.get_tests_from_shared("Demo")
109+
pass
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Many thanks to https://pymotw.com/2/urllib2/#uploading-files
2+
3+
import mimetools
4+
import mimetypes
5+
import itertools
6+
7+
8+
class MultiPartForm(object):
9+
"""Accumulate the data to be used when posting a form."""
10+
11+
def __init__(self):
12+
self.form_fields = []
13+
self.files = []
14+
self.boundary = mimetools.choose_boundary()
15+
return
16+
17+
def get_content_type(self):
18+
return 'multipart/form-data; boundary=%s' % self.boundary
19+
20+
def add_field(self, name, value):
21+
"""Add a simple field to the form data."""
22+
self.form_fields.append((name, value))
23+
return
24+
25+
def add_file(self, fieldname, filename, fileHandle, mimetype=None):
26+
"""Add a file to be uploaded."""
27+
body = fileHandle.read()
28+
if mimetype is None:
29+
mimetype = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
30+
self.files.append((fieldname, filename, mimetype, body))
31+
return
32+
33+
def __str__(self):
34+
"""Return a string representing the form data, including attached files."""
35+
# Build a list of lists, each containing "lines" of the
36+
# request. Each part is separated by a boundary string.
37+
# Once the list is built, return a string where each
38+
# line is separated by '\r\n'.
39+
parts = []
40+
part_boundary = '--' + self.boundary
41+
42+
# Add the form fields
43+
parts.extend(
44+
[part_boundary,
45+
'Content-Disposition: form-data; name="%s"' % name,
46+
'',
47+
value,
48+
]
49+
for name, value in self.form_fields
50+
)
51+
52+
# Add the files to upload
53+
parts.extend(
54+
[part_boundary,
55+
'Content-Disposition: file; name="%s"; filename="%s"' % \
56+
(field_name, filename),
57+
'Content-Type: %s' % content_type,
58+
'',
59+
body,
60+
]
61+
for field_name, filename, content_type, body in self.files
62+
)
63+
64+
# Flatten the list and add closing boundary marker,
65+
# then return CR+LF separated data
66+
flattened = list(itertools.chain(*parts))
67+
flattened.append('--' + self.boundary + '--')
68+
flattened.append('')
69+
return '\r\n'.join(flattened)
Binary file not shown.

0 commit comments

Comments
 (0)