Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
slapos.core
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Xiaowu Zhang
slapos.core
Commits
a0b00e8e
Commit
a0b00e8e
authored
Jul 17, 2019
by
Rafael Monnerat
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
slapos.slap: Re-write API to follow JIO API
This might evolve into a full jio api to written in python
parent
bda4f527
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
120 additions
and
45 deletions
+120
-45
slapos/slap/hateoas.py
slapos/slap/hateoas.py
+109
-42
slapos/slap/slap.py
slapos/slap/slap.py
+11
-3
No files found.
slapos/slap/hateoas.py
View file @
a0b00e8e
...
@@ -55,6 +55,13 @@ fallback_handler = logging.StreamHandler()
...
@@ -55,6 +55,13 @@ fallback_handler = logging.StreamHandler()
fallback_logger
.
setLevel
(
logging
.
INFO
)
fallback_logger
.
setLevel
(
logging
.
INFO
)
fallback_logger
.
addHandler
(
fallback_handler
)
fallback_logger
.
addHandler
(
fallback_handler
)
ALLOWED_JIO_FIELD_LIST
=
[
"StringField"
,
"EmailField"
,
"IntegerField"
,
"FloatField"
,
"TextAreaField"
]
class
TempDocument
(
object
):
class
TempDocument
(
object
):
pass
pass
...
@@ -171,8 +178,6 @@ class HateoasNavigator(object):
...
@@ -171,8 +178,6 @@ class HateoasNavigator(object):
Inspired by
Inspired by
https://git.erp5.org/gitweb/jio.git/blob/HEAD:/src/jio.storage/erp5storage.js
https://git.erp5.org/gitweb/jio.git/blob/HEAD:/src/jio.storage/erp5storage.js
"""
"""
# XXX: needs to be designed for real. For now, just a non-maintainable prototype.
# XXX: export to a standalone library, independant from slap.
def
__init__
(
self
,
slapgrid_uri
,
def
__init__
(
self
,
slapgrid_uri
,
key_file
=
None
,
cert_file
=
None
,
key_file
=
None
,
cert_file
=
None
,
master_ca_file
=
None
,
timeout
=
60
):
master_ca_file
=
None
,
timeout
=
60
):
...
@@ -211,7 +216,6 @@ class HateoasNavigator(object):
...
@@ -211,7 +216,6 @@ class HateoasNavigator(object):
return
json
.
loads
(
result
)
return
json
.
loads
(
result
)
def
getRootDocument
(
self
):
def
getRootDocument
(
self
):
# XXX what about cache?
cached_root_document
=
getattr
(
self
,
'root_document'
,
None
)
cached_root_document
=
getattr
(
self
,
'root_document'
,
None
)
if
cached_root_document
:
if
cached_root_document
:
return
cached_root_document
return
cached_root_document
...
@@ -221,6 +225,82 @@ class HateoasNavigator(object):
...
@@ -221,6 +225,82 @@ class HateoasNavigator(object):
)
)
return
self
.
root_document
return
self
.
root_document
def
_getSearchUrl
(
self
):
root_document
=
self
.
getRootDocument
()
return
root_document
[
"_links"
][
'raw_search'
][
'href'
]
def
_getTraverseUrl
(
self
):
root_document
=
self
.
getRootDocument
()
return
root_document
[
"_links"
][
'traverse'
][
'href'
]
def
_extractPropertyFromFormDict
(
self
,
form_dict
):
""" Reimplemenation in python of extractPropertyFromFormJSON of jio.js """
form
=
form_dict
[
"_embedded"
][
"_view"
]
form_data_dict
=
{}
converted_dict
=
{
"portal_type"
:
form_dict
[
"_links"
][
"type"
][
"name"
]
}
if
"parent"
in
form_dict
[
"_links"
]:
converted_dict
[
"parent_relative_url"
]
=
\
"/"
.
join
(
form_dict
[
"_links"
][
"parent"
][
"href"
].
split
(
"/"
)[
-
2
:])
form_data_dict
[
"form_id"
]
=
{
"key"
:
[
form
[
"form_id"
][
"key"
]],
"default"
:
form
[
"form_id"
][
"default"
]
}
for
key
in
form
:
field
=
form
[
key
]
if
key
.
startswith
(
"my_"
):
key
=
key
[
len
(
"my_"
):]
elif
key
.
startswith
(
"your_"
):
key
=
key
[
len
(
"your_"
):]
else
:
continue
if
field
[
"type"
]
in
ALLOWED_JIO_FIELD_LIST
:
form_data_dict
[
key
]
=
{
"default"
:
field
.
get
(
"default"
,
None
),
"key"
:
field
[
"key"
]
}
converted_dict
[
key
]
=
field
.
get
(
"default"
,
None
)
return
{
"data"
:
converted_dict
,
"form_data"
:
form_data_dict
}
def
jio_allDocs
(
self
,
query
):
search_url
=
self
.
_getSearchUrl
()
getter_link
=
expand
(
search_url
,
query
)
catalog_json
=
self
.
GET
(
getter_link
)
catalog_dict
=
json
.
loads
(
catalog_json
)
# Return the same data structure from jio api:
return
{
'data'
:
{
"rows"
:
catalog_dict
[
"_embedded"
][
"contents"
],
"total_rows"
:
len
(
catalog_dict
[
"_embedded"
][
"contents"
])
}
}
def
jio_get
(
self
,
key
):
traverse_url
=
self
.
_getTraverseUrl
()
# Hardcoded view, but it should come from a site configuration
view
=
"slaposjs_view"
getter_link
=
expand
(
traverse_url
,
{
"relative_url"
:
key
,
"view"
:
view
})
document_json
=
self
.
GET
(
getter_link
)
document_dict
=
json
.
loads
(
document_json
)
return
self
.
_extractPropertyFromFormDict
(
document_dict
)
def
getDocumentAndHateoas
(
self
,
relative_url
,
view
=
'view'
):
def
getDocumentAndHateoas
(
self
,
relative_url
,
view
=
'view'
):
site_document
=
self
.
getRootDocument
()
site_document
=
self
.
getRootDocument
()
return
expand
(
return
expand
(
...
@@ -235,18 +315,16 @@ class HateoasNavigator(object):
...
@@ -235,18 +315,16 @@ class HateoasNavigator(object):
return
json
.
loads
(
self
.
GET
(
person_url
))
return
json
.
loads
(
self
.
GET
(
person_url
))
class
SlapHateoasNavigator
(
HateoasNavigator
):
class
SlapHateoasNavigator
(
HateoasNavigator
):
def
_hateoas_getHostingSubscriptionDict
(
self
):
def
_getHostingSubscriptionList
(
self
,
title
=
None
,
select_list
=
[
"title"
,
"url_string"
]):
action_object_slap_list
=
self
.
getMeDocument
()[
'_links'
][
'action_object_slap'
]
query_str
=
'portal_type:"Hosting Subscription" AND validation_state:validated'
for
action
in
action_object_slap_list
:
if
title
is
not
None
:
if
action
.
get
(
'title'
)
==
'getHateoasHostingSubscriptionList'
:
query_str
=
'portal_type:"Hosting Subscription" AND validation_state:validated AND title:="%s"'
%
title
getter_link
=
action
[
'href'
]
break
result
=
self
.
jio_allDocs
(
else
:
query
=
{
"query"
:
query_str
,
"select_list"
:
select_list
})
raise
Exception
(
'Hosting subscription not found.'
)
result
=
self
.
GET
(
getter_link
)
return
result
[
'data'
][
'rows'
]
return
json
.
loads
(
result
)[
'_links'
][
'content'
]
# XXX rename me to blablaUrl(self)
def
_hateoas_getRelatedHostingSubscription
(
self
):
def
_hateoas_getRelatedHostingSubscription
(
self
):
action_object_slap_list
=
self
.
getMeDocument
()[
'_links'
][
'action_object_slap'
]
action_object_slap_list
=
self
.
getMeDocument
()[
'_links'
][
'action_object_slap'
]
getter_link
=
self
.
hateoasGetLinkFromLinks
(
action_object_slap_list
,
'getHateoasRelatedHostingSubscription'
)
getter_link
=
self
.
hateoasGetLinkFromLinks
(
action_object_slap_list
,
'getHateoasRelatedHostingSubscription'
)
...
@@ -270,40 +348,36 @@ class SlapHateoasNavigator(HateoasNavigator):
...
@@ -270,40 +348,36 @@ class SlapHateoasNavigator(HateoasNavigator):
return
instance_list
[
'_links'
][
'content'
]
return
instance_list
[
'_links'
][
'content'
]
def
getHostingSubscriptionDict
(
self
):
def
getHostingSubscriptionDict
(
self
):
hosting_subscription_li
nk_list
=
self
.
_hateoas_getHostingSubscriptionDic
t
()
hosting_subscription_li
st
=
self
.
_getHostingSubscriptionLis
t
()
hosting_subscription_dict
=
{}
hosting_subscription_dict
=
{}
for
hosting_subscription_link
in
hosting_subscription_link_list
:
for
hosting_subscription
in
hosting_subscription_list
:
raw_information
=
self
.
getHostingSubscriptionRootSoftwareInstanceInformation
(
hosting_subscription_link
[
'title'
])
software_instance
=
TempDocument
()
software_instance
=
TempDocument
()
# XXX redefine SoftwareInstance to be more consistent
for
key
,
value
in
hosting_subscription
.
iteritems
():
for
key
,
value
in
raw_information
.
iteritems
():
if
key
in
[
'_links'
,
'url_string'
]:
if
key
in
[
'_links'
]:
continue
continue
setattr
(
software_instance
,
'_%s'
%
key
,
value
)
setattr
(
software_instance
,
'_%s'
%
key
,
value
)
setattr
(
software_instance
,
'_software_release_url'
,
raw_information
[
'_links'
][
'software_release'
])
setattr
(
software_instance
,
'_software_release_url'
,
hosting_subscription
[
"url_string"
])
hosting_subscription_dict
[
software_instance
.
_title
]
=
software_instance
hosting_subscription_dict
[
software_instance
.
_title
]
=
software_instance
return
hosting_subscription_dict
return
hosting_subscription_dict
def
getHostingSubscriptionRootSoftwareInstanceInformation
(
self
,
reference
):
def
getHostingSubscriptionRootSoftwareInstanceInformation
(
self
,
reference
):
hosting_subscription_list
=
self
.
_hateoas_getHostingSubscriptionDict
()
hosting_subscription_list
=
self
.
_getHostingSubscriptionList
(
title
=
reference
,
for
hosting_subscription
in
hosting_subscription_list
:
select_list
=
[
"title"
,
"relative_url"
])
if
hosting_subscription
.
get
(
'title'
)
==
reference
:
hosting_subscription_url
=
hosting_subscription
[
'href'
]
assert
len
(
hosting_subscription_list
)
==
1
,
\
"There are more them one Hosting Subscription for this reference"
for
hosting_subscription_candidate
in
hosting_subscription_list
:
if
hosting_subscription_candidate
.
get
(
'title'
)
==
reference
:
hosting_subscription_jio_key
=
hosting_subscription_candidate
[
'relative_url'
]
break
break
else
:
if
hosting_subscription_jio_key
is
None
:
raise
NotFoundError
(
'This document does not exist.'
)
raise
NotFoundError
(
'This document does not exist.'
)
hosting_subscription
=
json
.
loads
(
self
.
GET
(
hosting_subscription_url
))
software_instance_url
=
self
.
hateoasGetLinkFromLinks
(
return
self
.
jio_get
(
hosting_subscription_jio_key
)
hosting_subscription
[
'_links'
][
'action_object_slap'
],
'getHateoasRootInstance'
)
response
=
self
.
GET
(
software_instance_url
)
response
=
json
.
loads
(
response
)
software_instance_url
=
response
[
'_links'
][
'content'
][
0
][
'href'
]
return
self
.
_hateoasGetInformation
(
software_instance_url
)
def
getRelatedInstanceInformation
(
self
,
reference
):
def
getRelatedInstanceInformation
(
self
,
reference
):
related_hosting_subscription_url
=
self
.
_hateoas_getRelatedHostingSubscription
()
related_hosting_subscription_url
=
self
.
_hateoas_getRelatedHostingSubscription
()
...
@@ -313,13 +387,6 @@ class SlapHateoasNavigator(HateoasNavigator):
...
@@ -313,13 +387,6 @@ class SlapHateoasNavigator(HateoasNavigator):
return
instance
return
instance
def
_hateoas_getComputer
(
self
,
reference
):
def
_hateoas_getComputer
(
self
,
reference
):
root_document
=
self
.
getRootDocument
()
search_url
=
root_document
[
"_links"
][
'raw_search'
][
'href'
]
getter_link
=
expand
(
search_url
,
{
"query"
:
"reference:%s AND portal_type:Computer"
%
reference
,
"select_list"
:
[
"relative_url"
],
"limit"
:
1
})
result
=
self
.
GET
(
getter_link
)
content_list
=
json
.
loads
(
result
)[
'_embedded'
][
'contents'
]
content_list
=
json
.
loads
(
result
)[
'_embedded'
][
'contents'
]
if
len
(
content_list
)
==
0
:
if
len
(
content_list
)
==
0
:
raise
Exception
(
'No Computer found.'
)
raise
Exception
(
'No Computer found.'
)
...
...
slapos/slap/slap.py
View file @
a0b00e8e
...
@@ -262,11 +262,19 @@ class OpenOrder(SlapRequester):
...
@@ -262,11 +262,19 @@ class OpenOrder(SlapRequester):
raw_information
=
self
.
_hateoas_navigator
.
getHostingSubscriptionRootSoftwareInstanceInformation
(
partition_reference
)
raw_information
=
self
.
_hateoas_navigator
.
getHostingSubscriptionRootSoftwareInstanceInformation
(
partition_reference
)
software_instance
=
SoftwareInstance
()
software_instance
=
SoftwareInstance
()
# XXX redefine SoftwareInstance to be more consistent
# XXX redefine SoftwareInstance to be more consistent
for
key
,
value
in
six
.
iteritems
(
raw_information
):
for
key
,
value
in
six
.
iteritems
(
raw_information
[
"data"
]
):
if
key
in
[
'_links'
]:
if
key
in
[
'_links'
]:
continue
continue
setattr
(
software_instance
,
'_%s'
%
key
,
value
)
setattr
(
software_instance
,
'_%s'
%
key
,
value
)
setattr
(
software_instance
,
'_software_release_url'
,
raw_information
[
'_links'
][
'software_release'
])
if
raw_information
[
"data"
].
get
(
"text_content"
,
None
)
is
not
None
:
setattr
(
software_instance
,
'_parameter_dict'
,
xml2dict
(
raw_information
[
"data"
][
'text_content'
]))
else
:
setattr
(
software_instance
,
'_parameter_dict'
,
{})
setattr
(
software_instance
,
'_requested_state'
,
raw_information
[
"data"
][
'slap_state'
])
setattr
(
software_instance
,
'_connection_dict'
,
raw_information
[
"data"
][
'connection_parameter_list'
])
setattr
(
software_instance
,
'_software_release_url'
,
raw_information
[
"data"
][
'url_string'
])
return
software_instance
return
software_instance
def
requestComputer
(
self
,
computer_reference
):
def
requestComputer
(
self
,
computer_reference
):
...
@@ -509,7 +517,7 @@ class ComputerPartition(SlapRequester):
...
@@ -509,7 +517,7 @@ class ComputerPartition(SlapRequester):
if
key
in
[
'_links'
]:
if
key
in
[
'_links'
]:
continue
continue
setattr
(
software_instance
,
'_%s'
%
key
,
value
)
setattr
(
software_instance
,
'_%s'
%
key
,
value
)
setattr
(
software_instance
,
'_software_release_url'
,
raw_information
[
'_links'
][
'software_release'
])
setattr
(
software_instance
,
'_software_release_url'
,
raw_information
[
"_links"
][
"software_release"
])
return
software_instance
return
software_instance
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment