Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
feudal
feudalBackend
Commits
844200d8
Commit
844200d8
authored
Nov 30, 2018
by
Lukas Burgey
Browse files
Make service and vo deployment cooperate with each other
parent
2e2602ff
Changes
3
Hide whitespace changes
Inline
Side-by-side
feudal/backend/models/brokers.py
View file @
844200d8
# pylint: disable=global-statement
import
logging
from
logging
import
getLogger
from
json
import
dumps
from
requests.auth
import
HTTPBasicAuth
from
django.db
import
models
...
...
@@ -10,7 +11,7 @@ from django_mysql.models import JSONField
import
pika
from
pika.exceptions
import
ConnectionClosed
LOGGER
=
logging
.
getLogger
(
__name__
)
LOGGER
=
getLogger
(
__name__
)
RABBITMQ_CONNECTION
=
None
...
...
@@ -23,6 +24,14 @@ def exchanges_default():
]
def
publish_to_user
(
user
,
obj
):
from
.
import
serializers
RabbitMQInstance
.
load
().
publish_to_user
(
user
,
dumps
(
serializers
.
UpdateSerializer
(
obj
).
data
),
)
# singleton for simple configs
# https://steelkiwi.com/blog/practical-application-singleton-design-pattern/
class
SingletonModel
(
models
.
Model
):
...
...
@@ -159,21 +168,6 @@ class RabbitMQInstance(SingletonModel):
msg
,
)
def
publish_by_service
(
self
,
service
,
msg
):
self
.
_publish
(
'services'
,
service
.
name
,
msg
,
)
def
publish_by_vo
(
self
,
vo
,
msg
):
self
.
_publish
(
vo
.
broker_exchange
,
vo
.
name
,
msg
,
)
def
publish_to_user
(
self
,
user
,
msg
):
self
.
_publish
(
'users'
,
...
...
feudal/backend/models/deployments.py
View file @
844200d8
...
...
@@ -10,9 +10,8 @@ from polymorphic.models import PolymorphicModel
from
feudal.backend.auth.v1.models.vo
import
VO
from
.
import
Site
,
Service
from
.
import
Site
,
Service
,
brokers
from
.users
import
User
,
SSHPublicKey
from
.brokers
import
RabbitMQInstance
LOGGER
=
getLogger
(
__name__
)
...
...
@@ -113,15 +112,7 @@ class Deployment(PolymorphicModel):
self
.
state_target
=
target
self
.
save
()
# FIXME this is breaking things when one wants deploy and another gets a user_remove
# # set the target to all credentials
# for state in self.states.all():
# state.assure_credential_states_exist()
# for credential_state in CredentialState.objects.filter(
# target__deployments=self,
# ):
# credential_state.set_target(target)
self
.
publish_to_user
()
# Deployment.user_deploy
def
user_deploy
(
self
):
...
...
@@ -132,26 +123,31 @@ class Deployment(PolymorphicModel):
for
item
in
self
.
states
.
filter
(
~
Q
(
state
=
DEPLOYED
)):
item
.
user_deploy
()
self
.
publish
()
self
.
publish
_to_client
()
# Deployment.user_remove
def
user_remove
(
self
):
LOGGER
.
debug
(
self
.
msg
(
'user_remove'
))
can_publish
=
False
self
.
_set_target
(
NOT_DEPLOYED
)
# states which are not NOT_DEPLOYED
for
item
in
self
.
states
.
filter
(
~
Q
(
state
=
NOT_DEPLOYED
)):
if
item
.
user_remove
():
can_publish
=
True
# we only publish to the clients if allowed
# we are not allowed to publish a removal if another deployment for our
# DeploymentStates exists and has the target DEPLOYED
if
can_publish
:
self
.
publish
()
else
:
self
.
publish_to_user
()
item
.
user_remove
()
# we always publish to the client
# ATTENTION! This may cause removals of Services which are wanted by other deployments!
# These will be deployed again when their DepState realises the error
self
.
publish_to_client
()
# this did not make sense
# # we only publish to the clients if allowed
# # we are not allowed to publish a removal if another deployment for our
# # DeploymentStates exists and has the target DEPLOYED
# if can_publish:
# self.publish()
# else:
# self.publish_to_user()
def
user_credential_added
(
self
,
key
):
for
item
in
self
.
states
.
all
():
...
...
@@ -167,13 +163,13 @@ class Deployment(PolymorphicModel):
def
publish_to_client
(
self
):
if
settings
.
DEBUG_PUBLISHING
:
LOGGER
.
debug
(
self
.
msg
(
'publish_to_client
'
))
LOGGER
.
debug
(
self
.
msg
(
'publish_to_client
: {}'
.
format
(
self
.
state_target
)
))
from
.serializers
import
clients
data
=
clients
.
DeploymentSerializer
(
self
).
data
msg
=
dumps
(
data
)
RabbitMQInstance
.
load
().
publish
(
brokers
.
RabbitMQInstance
.
load
().
publish
(
self
,
msg
,
)
...
...
@@ -184,15 +180,13 @@ class Deployment(PolymorphicModel):
return
if
settings
.
DEBUG_PUBLISHING
:
LOGGER
.
debug
(
self
.
msg
(
'publish_to_user
'
))
LOGGER
.
debug
(
self
.
msg
(
'publish_to_user
: {}'
.
format
(
self
.
state_target
)
))
from
.
import
serializers
msg
=
dumps
({
'deployment'
:
serializers
.
DeploymentSerializer
(
self
).
data
,
})
RabbitMQInstance
.
load
().
publish_to_user
(
brokers
.
publish_to_user
(
self
.
user
,
msg
,
{
'deployment'
:
self
,
},
)
def
publish
(
self
):
...
...
@@ -460,7 +454,7 @@ class DeploymentState(models.Model):
# starts tracking this the credential for this item
def
user_credential_added
(
self
,
credential
):
if
settings
.
DEBUG_CREDENTIALS
:
LOGGER
.
debug
(
'user_credential_added: %s %s'
,
self
,
credential
)
LOGGER
.
debug
(
self
.
msg
(
'Adding credential {}'
.
format
(
credential
.
name
))
)
CredentialState
.
get_credential_state
(
credential
,
...
...
@@ -469,7 +463,7 @@ class DeploymentState(models.Model):
def
user_credential_removed
(
self
,
credential
):
if
settings
.
DEBUG_CREDENTIALS
:
LOGGER
.
debug
(
'user_credential_removed: %s %s'
,
self
,
credential
)
LOGGER
.
debug
(
self
.
msg
(
'Removing credential {}'
.
format
(
credential
.
name
))
)
try
:
credential_state
=
self
.
credential_states
.
get
(
credential
=
credential
)
...
...
@@ -496,10 +490,7 @@ class DeploymentState(models.Model):
LOGGER
.
debug
(
self
.
msg
(
'State: already deployed'
))
return
self
.
_set_state
(
DEPLOYMENT_PENDING
,
publish
=
False
,
# the post response already contains the update
)
self
.
_set_state
(
DEPLOYMENT_PENDING
)
# DeploymentState.user_remove
# returns True if no other deployment needs this state_item to be deployed
...
...
@@ -524,20 +515,17 @@ class DeploymentState(models.Model):
or
self
.
state
==
REJECTED
)
):
self
.
_reset
()
self
.
_set_state
(
NOT_DEPLOYED
,
publish
=
False
)
self
.
_set_state
(
NOT_DEPLOYED
)
elif
(
self
.
state
==
DEPLOYMENT_PENDING
or
self
.
state
==
QUESTIONNAIRE
):
self
.
_set_state
(
NOT_DEPLOYED
)
self
.
_set_state
(
NOT_DEPLOYED
,
publish
=
True
)
else
:
# default: start the removal process
self
.
_set_state
(
REMOVAL_PENDING
,
publish
=
False
,
# the post response already contains the update
)
self
.
_set_state
(
REMOVAL_PENDING
)
# True: signal the callee that a publish_to_client is permitted
return
True
...
...
@@ -549,7 +537,7 @@ class DeploymentState(models.Model):
return
self
.
questionnaire
=
answers
self
.
_set_state
(
DEPLOYMENT_PENDING
,
publish
=
False
)
self
.
_set_state
(
DEPLOYMENT_PENDING
)
self
.
publish_to_client
()
def
client_credential_states
(
self
,
credential_states
):
...
...
@@ -576,14 +564,11 @@ class DeploymentState(models.Model):
state
=
output
.
get
(
'state'
,
''
)
LOGGER
.
debug
(
self
.
msg
(
'Client response: {}'
.
format
(
state
)))
self
.
_set_state
(
state
)
credential_states
=
output
.
get
(
'user_credential_states'
,
None
)
if
credential_states
is
not
None
:
self
.
client_credential_states
(
credential_states
)
self
.
message
=
output
.
get
(
'message'
,
''
)
self
.
save
()
# update values
if
state
==
DEPLOYED
:
...
...
@@ -605,9 +590,14 @@ class DeploymentState(models.Model):
else
:
return
'unknown state "{}"'
.
format
(
state
)
# FIXME this apparently causes deployment loops
# _set_state does not always save!
self
.
save
()
# publish after we updated the values of the response
self
.
_set_state
(
state
,
publish
=
True
)
# is the target reached now?
if
self
.
state_target
!=
self
.
state
:
if
str
(
self
.
state_target
)
!=
str
(
self
.
state
)
:
LOGGER
.
debug
(
self
.
msg
(
'Target {} still not reached. Publishing again'
.
format
(
self
.
state_target
,
)))
...
...
@@ -633,10 +623,14 @@ class DeploymentState(models.Model):
except
CredentialState
.
DoesNotExist
:
LOGGER
.
error
(
'CredentialState.DoesNotExist in _set_state'
)
def
_set_state
(
self
,
state
,
publish
=
Tru
e
):
def
_set_state
(
self
,
state
,
publish
=
Fals
e
):
self
.
_assure_credential_states_exist
()
# not trans
if
str
(
self
.
state
)
==
str
(
state
):
# publish to user (even if the state did not change!)
if
publish
:
self
.
publish_to_user
()
return
LOGGER
.
debug
(
self
.
msg
(
'State: {} -> {} - Target: {}'
.
format
(
self
.
state
,
state
,
self
.
state_target
)))
...
...
@@ -644,33 +638,41 @@ class DeploymentState(models.Model):
self
.
state
=
state
self
.
save
()
# publish to user
if
publish
and
self
.
deployments
.
exists
():
if
publish
:
self
.
publish_to_user
()
def
publish_to_user
(
self
):
for
deployment
in
self
.
deployments
.
all
():
deployment
.
publish_to_user
()
if
self
.
user
is
not
None
:
if
settings
.
DEBUG_PUBLISHING
:
LOGGER
.
debug
(
self
.
msg
(
'publish_to_user'
))
brokers
.
publish_to_user
(
self
.
user
,
{
'deployment_state'
:
self
,
},
)
def
publish_to_client
(
self
):
for
deployment
in
self
.
deployments
.
all
():
# only publish to the client using deployments with our target
for
deployment
in
self
.
deployments
.
filter
(
state_target
=
self
.
state_target
):
deployment
.
publish_to_client
()
def
msg
(
self
,
msg
):
return
'{} - {}'
.
format
(
self
,
msg
)
return
'
{} - {}'
.
format
(
self
,
msg
)
def
__str__
(
self
):
if
self
.
deployments
.
exists
():
deployment_names
=
[
str
(
deployment
.
id
)
for
deployment
in
self
.
deployments
.
all
()]
return
'D
State
: ({}:{}:{})#{}'
.
format
(
return
'D
ep-St
: ({}:{}:{})#{}'
.
format
(
','
.
join
(
deployment_names
),
self
.
service
,
self
.
site
,
self
.
id
,
)
return
'D
State
: (ORPHANED:{}:{})#{}'
.
format
(
return
'D
ep-St
: (ORPHANED:{}:{})#{}'
.
format
(
self
.
service
,
self
.
site
,
self
.
id
,
...
...
@@ -763,13 +765,10 @@ class CredentialState(models.Model):
self
.
state
=
state
self
.
save
()
self
.
target
.
publish_to_user
()
def
credential_deleted
(
self
):
if
self
.
state
==
NOT_DEPLOYED
:
self
.
_delete_state
()
LOGGER
.
debug
(
'related credential: %s'
,
self
.
credential
)
self
.
state_target
=
NOT_DEPLOYED
self
.
_credential_deleted
=
True
self
.
save
()
...
...
@@ -785,10 +784,10 @@ class CredentialState(models.Model):
credential
.
try_delete_key
()
def
msg
(
self
,
message
):
return
'{} - {}'
.
format
(
self
,
message
)
return
'
{} - {}'
.
format
(
self
,
message
)
def
__str__
(
self
):
return
'C
State
: ({}:{})#{}'
.
format
(
return
'C
red-St
: ({}:{})#{}'
.
format
(
self
.
target
.
id
,
self
.
credential
,
self
.
id
,
...
...
feudal/backend/models/serializers/__init__.py
View file @
844200d8
...
...
@@ -117,6 +117,7 @@ class VODeploymentSerializer(serializers.ModelSerializer):
class
ServiceDeploymentSerializer
(
serializers
.
ModelSerializer
):
states
=
DeploymentStateSerializer
(
many
=
True
)
service
=
ServiceSerializer
()
class
Meta
:
model
=
ServiceDeployment
fields
=
DEPLOYMENT_FIELDS
+
(
...
...
@@ -132,41 +133,33 @@ class DeploymentSerializer(PolymorphicSerializer):
}
# contains properties which change less often
class
UserSerializer
(
serializers
.
ModelSerializer
):
vos
=
VOSerializer
(
many
=
True
)
ssh_keys
=
SSHPublicKeySerializer
(
many
=
True
)
class
Meta
:
model
=
User
fields
=
[
'id'
,
'profile_name'
,
'ssh_keys'
,
'userinfo'
,
'vos'
,
]
class
UserStateSerializer
(
serializers
.
ModelSerializer
):
vos
=
VOSerializer
(
many
=
True
)
ssh_keys
=
SSHPublicKeySerializer
(
many
=
True
)
deployments
=
DeploymentSerializer
(
many
=
True
)
services
=
ServiceSerializer
(
many
=
True
)
ssh_keys
=
SSHPublicKeySerializer
(
many
=
True
)
states
=
DeploymentStateSerializer
(
many
=
True
)
vos
=
VOSerializer
(
many
=
True
)
class
Meta
:
model
=
User
fields
=
[
fields
=
(
'deployments'
,
'id'
,
'profile_name'
,
'services'
,
'ssh_keys'
,
'states'
,
'userinfo'
,
'vos'
,
]
)
class
StateSerializer
(
serializers
.
Serializer
):
error
=
serializers
.
CharField
(
allow_blank
=
True
,
required
=
False
)
user
=
UserStateSerializer
()
class
UpdateSerializer
(
serializers
.
Serializer
):
error
=
serializers
.
CharField
(
allow_blank
=
True
,
required
=
False
)
deployment
=
DeploymentSerializer
(
required
=
False
)
deployment_state
=
DeploymentStateSerializer
(
required
=
False
)
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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