Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
CONF
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
UvA
CONF
Commits
9551f6d6
Commit
9551f6d6
authored
5 years ago
by
Spiros Koulouzis
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
split methods to util and set node properties to default
parent
6606fbe8
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
206 additions
and
98 deletions
+206
-98
planner.py
drip_planner2/src/planner/planner.py
+89
-89
spec_service.py
drip_planner2/src/planner/spec_service.py
+4
-5
rpc_server.py
drip_planner2/src/rpc_server.py
+6
-4
tosca.py
drip_planner2/src/utils/tosca.py
+107
-0
No files found.
drip_planner2/src/planner/planner.py
View file @
9551f6d6
...
...
@@ -2,13 +2,14 @@ import logging
from
toscaparser.nodetemplate
import
NodeTemplate
from
toscaparser.tosca_template
import
ToscaTemplate
import
networkx
as
nx
from
src.utils.TOSCA_parser
import
TOSCAParser
import
operator
from
planner.spec_service
import
*
from
utils.tosca
import
*
from
utils
import
tosca
as
tosca_util
class
Planner
:
node_type_key_names_to_remove
=
[
'capabilities'
,
'requirements'
,
'derived_from'
]
def
__init__
(
self
,
path
):
self
.
template
=
ToscaTemplate
(
path
)
...
...
@@ -18,65 +19,76 @@ class Planner:
self
.
all_nodes
.
update
(
self
.
tosca_node_types
.
items
())
self
.
all_nodes
.
update
(
self
.
all_custom_def
.
items
())
self
.
required_nodes
=
[]
props
=
{}
props
[
'kb_url'
]
=
"https://host"
props
=
{
'kb_url'
:
"https://host"
}
self
.
spec_service
=
SpecService
(
props
)
# graph = self.build_graph(template.nodetemplates)
def
set_infrastructure_specifications
(
self
):
self
.
set_vm_specifications
()
def
set_vm_specifications
(
self
):
for
node
in
self
.
template
.
nodetemplates
:
if
node
.
type
==
'tosca.nodes.ARTICONF.VM.Compute'
:
props
=
{}
username_prop
=
node
.
get_property_value
(
'user_name'
)
vm_username_val
=
self
.
spec_service
.
get_vm_username
()
props
[
'properties'
]
=
self
.
set_prop
(
prop_key
,
prop_value
)
if
vm_username_val
:
props
[
'properties'
]
=
{
'user_name'
:
vm_username_val
}
else
:
if
username_prop
[
'required'
]
==
'true'
and
username_prop
[
'default'
]:
vm_username_val
=
username_prop
[
'default'
]
props
[
'properties'
]
=
{
'user_name'
:
vm_username_val
}
node
.
_properties
=
props
logging
.
info
(
str
(
node
.
_properties
))
# for prop in node.get_properties_objects():
# logging.info(prop.name + ' : ' + str(prop.value))
def
set_prop
(
self
,
prop_key
,
prop_value
):
def
add_required_nodes_to_template
(
self
,
required_nodes
):
for
req_node
in
required_nodes
:
node_template
=
tosca_util
.
node_type_2_node_template
(
req_node
)
self
.
template
.
nodetemplates
.
append
(
node_template
)
return
self
.
template
def
set_infrastructure_specifications
(
self
,
required_nodes
):
required_nodes
=
self
.
set_vm_specifications
(
required_nodes
)
required_nodes
=
self
.
set_topology_specifications
(
required_nodes
)
return
required_nodes
def
set_vm_specifications
(
self
,
required_nodes
):
for
node
in
required_nodes
:
node_type_name
=
tosca_util
.
get_node_type_name
(
node
)
if
node_type_name
==
'tosca.nodes.ARTICONF.VM.Compute'
:
node_template_props
=
{
'properties'
:
{}}
node_properties
=
tosca_util
.
get_node_properties
(
node
)
for
node_type_prop_key
in
node_properties
:
node_template_prop
=
self
.
get_node_template_property
(
node_type_prop_key
,
node_properties
[
node_type_prop_key
])
node_template_props
[
'properties'
][
node_type_prop_key
]
=
node_template_prop
node
=
tosca_util
.
set_node_properties
(
node
,
node_template_props
)
logging
.
info
(
'node: '
+
node_type_name
+
' properties: '
+
str
(
node_template_props
))
return
required_nodes
def
get_node_template_property
(
self
,
prop_key
,
node_prop_dict
):
prop_value
=
self
.
spec_service
.
get_property
(
prop_key
)
if
prop_value
:
return
{
prop_key
:
node_prop_dict
}
else
:
if
'required'
in
node_prop_dict
and
'default'
in
node_prop_dict
:
return
node_prop_dict
[
'default'
]
if
'constraints'
in
node_prop_dict
:
constraints
=
node_prop_dict
[
'constraints'
]
for
constraint
in
constraints
:
if
next
(
iter
(
constraint
))
==
'greater_or_equal'
:
return
constraint
[
next
(
iter
(
constraint
))]
return
None
# Resolve requirements. Go over all nodes and recursively resolve requirements till node has no requirements
# e.g. docker -> k8s -> cluster -> vm
def
resolve_requirements
(
self
):
for
node
in
self
.
template
.
nodetemplates
:
self
.
add_required_nodes
(
node
)
self
.
template
.
nodetemplates
.
extend
(
self
.
required_nodes
)
def
get_tosca_template
(
self
):
tp
=
TOSCAParser
()
yaml_str
=
tp
.
tosca_template2_yaml
(
self
.
template
)
return
yaml_str
return
self
.
required_nodes
def
add_required_nodes
(
self
,
node
):
node_type
=
tosca_util
.
get_node_type_name
(
node
)
missing_requirements
=
self
.
get_missing_requirements
(
node
)
if
not
missing_requirements
:
logging
.
debug
(
'Node: '
+
node
.
type
+
' has no requirements'
)
logging
.
debug
(
'Node: '
+
node
_
type
+
' has no requirements'
)
return
matching_node
=
self
.
find_best_node
(
missing_requirements
)
# Only add node that is not in node_templates
matching_node_type_name
=
next
(
iter
(
matching_node
))
capable_node_template
=
self
.
node_type_2_node_template
(
matching_node
)
if
not
self
.
contains_node_type
(
self
.
required_nodes
,
matching_node_type_name
):
node
=
self
.
add_missing_requirements
(
node
,
missing_requirements
,
capable_node_template
.
name
)
logging
.
info
(
'Adding: '
+
str
(
capable_node_template
.
type
))
self
.
required_nodes
.
append
(
capable_node_template
)
# capable_node_template = self.node_type_2_node_template(matching_node)
if
not
tosca_util
.
contains_node_type
(
self
.
required_nodes
,
matching_node_type_name
):
matching_node_type_name
=
next
(
iter
(
matching_node
))
node
=
self
.
add_missing_requirements
(
node
,
missing_requirements
,
matching_node_type_name
)
logging
.
info
(
'Adding: '
+
str
(
matching_node_type_name
))
self
.
required_nodes
.
append
(
matching_node
)
# Find matching nodes for the new node's requirements
self
.
add_required_nodes
(
capable_node_templat
e
)
self
.
add_required_nodes
(
matching_nod
e
)
def
build_graph
(
self
,
nodetemplates
):
graph
=
nx
.
Graph
()
...
...
@@ -99,33 +111,39 @@ class Planner:
return
graph
def
get_missing_requirements
(
self
,
node
):
logging
.
debug
(
'Looking for requirements for node: '
+
node
.
type
)
def_type
=
self
.
all_nodes
[
node
.
type
]
node_type_name
=
tosca_util
.
get_node_type_name
(
node
)
node_requirements
=
tosca_util
.
get_node_requirements
(
node
)
parent_type_requirements
=
tosca_util
.
get_parent_type_requirements
(
node
,
self
.
all_nodes
)
logging
.
debug
(
'Looking for requirements for node: '
+
node_type_name
)
def_type
=
self
.
all_nodes
[
node_type_name
]
def_requirements
=
[]
if
'requirements'
in
def_type
.
keys
():
def_requirements
=
def_type
[
'requirements'
]
logging
.
debug
(
'Found requirements: '
+
str
(
def_requirements
)
+
' for node: '
+
node
.
typ
e
)
logging
.
debug
(
'Found requirements: '
+
str
(
def_requirements
)
+
' for node: '
+
node
_type_nam
e
)
missing_requirements
=
[]
if
not
node
.
requirements
:
if
not
node_requirements
:
missing_requirements
=
def_requirements
elif
def_requirements
:
for
def_requirement
in
def_requirements
:
for
key
in
def_requirement
:
for
node_req
in
node
.
requirements
:
for
node_req
in
node
_
requirements
:
if
key
not
in
node_req
:
req_name
=
next
(
iter
(
def_requirement
))
def_requirement
[
req_name
][
'node'
]
=
None
missing_requirements
.
append
(
def_requirement
)
# Make sure we have the definition. Otherwise we get an error in the recursion
if
'derived_from'
in
def_type
.
keys
()
and
not
def_type
[
'derived_from'
]
in
node
.
custom_def
.
keys
():
node
.
custom_def
[
def_type
[
'derived_from'
]]
=
self
.
all_custom_def
[
def_type
[
'derived_from'
]
]
if
node
.
parent_type
and
node
.
parent_type
.
requirements
:
# if 'derived_from' in def_type.keys() and not def_type['derived_from'] in
custom_def.keys():
# node.custom_def[def_type['derived_from']] = custom_def['derived_from'
]
parent_type
=
tosca_util
.
get_node_type_name
(
node
)
if
parent_type
and
parent_type_
requirements
:
logging
.
debug
(
' Adding to : '
+
str
(
node
.
name
)
+
' parent requirements from: '
+
str
(
node
.
parent_type
.
type
))
missing_requirements
=
missing_requirements
+
node
.
parent_type
.
requirements
' Adding to : '
+
str
(
node
_type_name
)
+
' parent requirements from: '
+
str
(
parent_
type
))
missing_requirements
=
missing_requirements
+
parent_type_
requirements
logging
.
debug
(
' missing_requirements: '
+
str
(
missing_requirements
))
return
missing_requirements
...
...
@@ -148,39 +166,11 @@ class Planner:
candidate_nodes
.
update
(
candidate_child_nodes
)
capable_nodes
=
{}
# Only return the nodes that have interfaces. This means that they are not "abstract"
nodes_type_names_with_interface
=
self
.
get_node_types_with_interface
(
candidate_nodes
)
nodes_type_names_with_interface
=
tosca_util
.
get_node_types_with_interface
(
candidate_nodes
)
for
type_name
in
nodes_type_names_with_interface
:
capable_nodes
[
type_name
]
=
candidate_nodes
[
type_name
]
return
capable_nodes
def
contains_node_type
(
self
,
node_types_list
,
node_type_name
):
if
node_types_list
is
None
:
return
False
for
node_type
in
node_types_list
:
if
isinstance
(
node_type
,
NodeTemplate
):
type_name
=
node_type
.
type
elif
isinstance
(
node_type
,
dict
):
type_name
=
next
(
iter
(
node_type
))
if
type_name
==
node_type_name
:
return
True
return
False
def
node_type_2_node_template
(
self
,
node_type
):
nodetemplate_dict
=
{}
type_name
=
next
(
iter
(
node_type
))
node_type_array
=
type_name
.
split
(
"."
)
name
=
node_type_array
[
len
(
node_type_array
)
-
1
]
.
lower
()
nodetemplate_dict
[
name
]
=
node_type
[
next
(
iter
(
node_type
))]
.
copy
()
nodetemplate_dict
[
name
][
'type'
]
=
type_name
for
name_to_remove
in
self
.
node_type_key_names_to_remove
:
if
name_to_remove
in
nodetemplate_dict
[
name
]:
nodetemplate_dict
[
name
]
.
pop
(
name_to_remove
)
if
'type'
in
node_type
[
next
(
iter
(
node_type
))]:
node_type
[
next
(
iter
(
node_type
))]
.
pop
(
'type'
)
return
NodeTemplate
(
name
,
nodetemplate_dict
,
node_type
)
def
find_best_node
(
self
,
missing_requirements
):
matching_nodes
=
{}
number_of_matching_requirement
=
{}
...
...
@@ -226,15 +216,25 @@ class Planner:
child_nodes
[
tosca_node_type
]
=
self
.
all_nodes
[
tosca_node_type
]
return
child_nodes
def
get_node_types_with_interface
(
self
,
nodes
):
node_types_with_interface
=
[]
for
node_name
in
nodes
:
if
'interfaces'
in
nodes
[
node_name
]
.
keys
()
and
'tosca.nodes.Root'
!=
node_name
:
node_types_with_interface
.
append
(
node_name
)
return
node_types_with_interface
def
add_missing_requirements
(
self
,
node
,
missing_requirements
,
capable_node_name
):
for
req
in
missing_requirements
:
req
[
next
(
iter
(
req
))][
'node'
]
=
capable_node_name
node
.
requirements
.
append
(
req
)
if
isinstance
(
node
,
NodeTemplate
):
contains_requirement
=
False
for
node_requirement
in
node
.
requirements
:
if
node_requirement
==
req
:
contains_requirement
=
True
break
if
not
contains_requirement
:
node
.
requirements
.
append
(
req
)
elif
isinstance
(
node
,
dict
):
type_name
=
next
(
iter
(
node
))
node_requirements
=
node
[
type_name
][
'requirements'
]
contains_requirement
=
False
for
node_requirement
in
node_requirements
:
if
node_requirement
==
req
:
contains_requirement
=
True
break
if
not
contains_requirement
:
node
[
type_name
][
'requirements'
]
.
append
(
req
)
return
node
This diff is collapsed.
Click to expand it.
drip_planner2/src/planner/spec_service.py
View file @
9551f6d6
class
SpecService
:
def
__init__
(
self
,
props
):
self
.
properties
=
props
def
__init__
(
self
,
conf
):
self
.
configuration
=
conf
def
get_vm_username
(
self
):
return
"vm_user"
\ No newline at end of file
def
get_property
(
self
,
prop_key
):
return
None
This diff is collapsed.
Click to expand it.
drip_planner2/src/rpc_server.py
View file @
9551f6d6
...
...
@@ -15,6 +15,7 @@ import tempfile
import
time
import
logging
import
base64
from
utils
import
tosca
as
tosca_util
logger
=
logging
.
getLogger
(
__name__
)
# if not getattr(logger, 'handler_set', None):
...
...
@@ -127,10 +128,11 @@ if __name__ == "__main__":
tosca_file_path
=
"../../TOSCA/application_example.yaml"
# planner = BasicPlanner(tosca_file_path)
planner
=
Planner
(
tosca_file_path
)
planner
.
resolve_requirements
()
planner
.
set_infrastructure_specifications
()
template
=
planner
.
get_tosca_template
()
# logger.info("template ----: \n" + template)
required_nodes
=
planner
.
resolve_requirements
()
required_nodes
=
planner
.
set_infrastructure_specifications
(
required_nodes
)
planner
.
add_required_nodes_to_template
(
required_nodes
)
template
=
tosca_util
.
get_tosca_template_as_yml
(
planner
.
template
)
logger
.
info
(
"template ----:
\n
"
+
template
)
else
:
logger
.
info
(
"Input args: "
+
sys
.
argv
[
0
]
+
' '
+
sys
.
argv
[
1
]
+
' '
+
sys
.
argv
[
2
])
channel
=
init_chanel
(
sys
.
argv
)
...
...
This diff is collapsed.
Click to expand it.
drip_planner2/src/utils/tosca.py
0 → 100644
View file @
9551f6d6
from
toscaparser.nodetemplate
import
NodeTemplate
from
utils.TOSCA_parser
import
TOSCAParser
node_type_key_names_to_remove
=
[
'capabilities'
,
'requirements'
,
'derived_from'
]
def
get_node_type_name
(
node
):
if
isinstance
(
node
,
NodeTemplate
):
node_type
=
node
.
type
elif
isinstance
(
node
,
dict
):
node_type
=
next
(
iter
(
node
))
return
node_type
def
get_node_requirements
(
node
):
if
isinstance
(
node
,
NodeTemplate
):
node_requirements
=
node
.
requirements
elif
isinstance
(
node
,
dict
):
node_type_name
=
get_node_type_name
(
node
)
if
'requirements'
not
in
node
[
node_type_name
]:
node
[
node_type_name
][
'requirements'
]
=
{}
node_requirements
=
node
[
node_type_name
][
'requirements'
]
return
node_requirements
def
get_parent_type
(
node
):
if
isinstance
(
node
,
NodeTemplate
):
parent_type
=
node
.
parent_type
elif
isinstance
(
node
,
dict
):
parent_type
=
node
[
node_type_name
][
'derived_from'
]
return
parent_type
def
get_node_type_requirements
(
type_name
,
all_nodes
):
def_type
=
all_nodes
[
type_name
]
if
'requirements'
in
def_type
.
keys
():
return
def_type
[
'requirements'
]
return
None
def
get_parent_type_requirements
(
node
,
all_nodes
):
if
isinstance
(
node
,
NodeTemplate
):
if
node
.
parent_type
and
node
.
parent_type
.
requirements
:
parent_type_requirements
=
node
.
parent_type
.
requirements
else
:
parent_type_requirements
=
{}
elif
isinstance
(
node
,
dict
):
node_type_name
=
get_node_type_name
(
node
)
parent_type_requirements
=
get_node_type_requirements
(
node_type_name
,
all_nodes
)
return
parent_type_requirements
def
get_node_types_with_interface
(
nodes
):
node_types_with_interface
=
[]
for
node_name
in
nodes
:
if
'interfaces'
in
nodes
[
node_name
]
.
keys
()
and
'tosca.nodes.Root'
!=
node_name
:
node_types_with_interface
.
append
(
node_name
)
return
node_types_with_interface
def
node_type_2_node_template
(
node_type
):
nodetemplate_dict
=
{}
type_name
=
next
(
iter
(
node_type
))
node_type_array
=
type_name
.
split
(
"."
)
name
=
node_type_array
[
len
(
node_type_array
)
-
1
]
.
lower
()
nodetemplate_dict
[
name
]
=
node_type
[
next
(
iter
(
node_type
))]
.
copy
()
nodetemplate_dict
[
name
][
'type'
]
=
type_name
for
name_to_remove
in
node_type_key_names_to_remove
:
if
name_to_remove
in
nodetemplate_dict
[
name
]:
nodetemplate_dict
[
name
]
.
pop
(
name_to_remove
)
if
'type'
in
node_type
[
next
(
iter
(
node_type
))]:
node_type
[
next
(
iter
(
node_type
))]
.
pop
(
'type'
)
return
NodeTemplate
(
name
,
nodetemplate_dict
,
node_type
)
def
get_tosca_template_as_yml
(
template
):
tp
=
TOSCAParser
()
yaml_str
=
tp
.
tosca_template2_yaml
(
template
)
return
yaml_str
def
contains_node_type
(
node_types_list
,
node_type_name
):
if
node_types_list
is
None
:
return
False
for
node_type
in
node_types_list
:
if
isinstance
(
node_type
,
NodeTemplate
):
type_name
=
node_type
.
type
elif
isinstance
(
node_type
,
dict
):
type_name
=
next
(
iter
(
node_type
))
if
type_name
==
node_type_name
:
return
True
return
False
def
get_node_properties
(
node
):
node_type_name
=
get_node_type_name
(
node
)
return
node
[
node_type_name
][
'properties'
]
def
set_node_properties
(
node
,
properties
):
node_type_name
=
get_node_type_name
(
node
)
node
[
node_type_name
][
'properties'
]
=
properties
return
node
\ No newline at end of file
This diff is collapsed.
Click to expand it.
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