Deployment logs fetching
Added Deployment instance to group, store and fetch deployment logs (status event) by the deployment attempts Change-Id: I5d31da1140c3fcf9b72322093a5569ce54b36aaf
This commit is contained in:
parent
eb1cc1630a
commit
4bf7e6d45e
|
@ -0,0 +1,62 @@
|
|||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from muranoapi.openstack.common import wsgi
|
||||
from muranoapi.db.models import Deployment, Status
|
||||
from muranoapi.db.session import get_session
|
||||
from muranoapi.openstack.common import log as logging
|
||||
from sqlalchemy import desc
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Controller(object):
|
||||
def index(self, request, environment_id):
|
||||
unit = get_session()
|
||||
query = unit.query(Deployment) \
|
||||
.filter_by(environment_id=environment_id) \
|
||||
.order_by(desc(Deployment.created))
|
||||
result = query.all()
|
||||
deployments = [deployment.to_dict() for deployment in result]
|
||||
return {'deployments': deployments}
|
||||
|
||||
def statuses(self, request, environment_id, deployment_id):
|
||||
unit = get_session()
|
||||
query = unit.query(Status) \
|
||||
.filter_by(deployment_id=deployment_id) \
|
||||
.order_by(Status.created)
|
||||
|
||||
if 'service_id' in request.GET:
|
||||
service_id_set = set(request.GET.getall('service_id'))
|
||||
environment = unit.query(Deployment).get(deployment_id).description
|
||||
entity_ids = []
|
||||
if 'services' in environment:
|
||||
for service in environment['services']:
|
||||
if service['id'] in service_id_set:
|
||||
entity_ids.append(service['id'])
|
||||
if 'units' in service:
|
||||
unit_ids = [u['id'] for u in service['units']
|
||||
if 'id' in u]
|
||||
entity_ids = entity_ids + unit_ids
|
||||
if entity_ids:
|
||||
query = query.filter(Status.entity_id.in_(entity_ids))
|
||||
else:
|
||||
return {'reports': None}
|
||||
|
||||
result = query.all()
|
||||
return {'reports': [status.to_dict() for status in result]}
|
||||
|
||||
|
||||
def create_resource():
|
||||
return wsgi.Resource(Controller())
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
import routes
|
||||
from muranoapi.openstack.common import wsgi
|
||||
from muranoapi.api.v1 import environments, services
|
||||
from muranoapi.api.v1 import environments, services, deployments
|
||||
from muranoapi.api.v1 import sessions
|
||||
|
||||
|
||||
|
@ -83,6 +83,17 @@ class API(wsgi.Router):
|
|||
action='delete',
|
||||
conditions={'method': ['DELETE']})
|
||||
|
||||
deployments_resource = deployments.create_resource()
|
||||
mapper.connect('/environments/{environment_id}/deployments',
|
||||
controller=deployments_resource,
|
||||
action='index',
|
||||
conditions={'method': ['GET']})
|
||||
mapper.connect('/environments/{environment_id}/deployments/'
|
||||
'{deployment_id}',
|
||||
controller=deployments_resource,
|
||||
action='statuses',
|
||||
conditions={'method': ['GET']})
|
||||
|
||||
sessions_resource = sessions.create_resource()
|
||||
mapper.connect('/environments/{environment_id}/configure',
|
||||
controller=sessions_resource,
|
||||
|
@ -96,11 +107,6 @@ class API(wsgi.Router):
|
|||
controller=sessions_resource,
|
||||
action='delete',
|
||||
conditions={'method': ['DELETE']})
|
||||
mapper.connect('/environments/{environment_id}/sessions/'
|
||||
'{session_id}/reports',
|
||||
controller=sessions_resource,
|
||||
action='reports',
|
||||
conditions={'method': ['GET']})
|
||||
mapper.connect('/environments/{environment_id}/sessions/'
|
||||
'{session_id}/deploy',
|
||||
controller=sessions_resource,
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
# under the License.
|
||||
|
||||
from webob import exc
|
||||
from muranoapi.db.models import Session, Status
|
||||
from muranoapi.db.models import Session
|
||||
from muranoapi.db.session import get_session
|
||||
from muranoapi.db.services.sessions import SessionServices
|
||||
from muranoapi.db.services.sessions import SessionState
|
||||
|
@ -114,52 +114,6 @@ class Controller(object):
|
|||
|
||||
SessionServices.deploy(session, unit, request.context.auth_token)
|
||||
|
||||
def reports(self, request, environment_id, session_id):
|
||||
log.debug(_('Session:Reports <EnvId: {0}, '
|
||||
'SessionId: {1}>'.format(environment_id, session_id)))
|
||||
|
||||
unit = get_session()
|
||||
statuses = unit.query(Status).filter_by(session_id=session_id).all()
|
||||
result = statuses
|
||||
|
||||
if 'service_id' in request.GET:
|
||||
service_id = request.GET['service_id']
|
||||
|
||||
environment = unit.query(Session).get(session_id).description
|
||||
services = []
|
||||
if 'services' in environment and 'activeDirectories' in \
|
||||
environment['services']:
|
||||
services += environment['services']['activeDirectories']
|
||||
|
||||
if 'services' in environment and 'webServers' in \
|
||||
environment['services']:
|
||||
services += environment['services']['webServers']
|
||||
|
||||
if 'services' in environment and 'aspNetApps' in\
|
||||
environment['services']:
|
||||
services += environment['services']['aspNetApps']
|
||||
|
||||
if 'services' in environment and 'webServerFarms' in \
|
||||
environment['services']:
|
||||
services += environment['services']['webServerFarms']
|
||||
|
||||
if 'services' in environment and 'aspNetAppFarms' in\
|
||||
environment['services']:
|
||||
services += environment['services']['aspNetAppFarms']
|
||||
|
||||
service = [service for service in services
|
||||
if service['id'] == service_id][0]
|
||||
|
||||
if service:
|
||||
entities = [u['id'] for u in service['units']]
|
||||
entities.append(service_id)
|
||||
result = []
|
||||
for status in statuses:
|
||||
if status.entity_id in entities:
|
||||
result.append(status)
|
||||
|
||||
return {'reports': [status.to_dict() for status in result]}
|
||||
|
||||
|
||||
def create_resource():
|
||||
return wsgi.Resource(Controller())
|
||||
|
|
|
@ -18,10 +18,11 @@ from amqplib.client_0_8 import AMQPConnectionException
|
|||
import anyjson
|
||||
import eventlet
|
||||
from muranoapi.common.utils import retry, handle
|
||||
from muranoapi.db.models import Status, Session, Environment
|
||||
from muranoapi.db.models import Status, Session, Environment, Deployment
|
||||
from muranoapi.db.session import get_session
|
||||
from muranoapi.openstack.common import log as logging
|
||||
from muranoapi.openstack.common import log as logging, timeutils
|
||||
from muranoapi.common import config
|
||||
from sqlalchemy import desc
|
||||
|
||||
amqp = eventlet.patcher.import_patched('amqplib.client_0_8')
|
||||
conf = config.CONF.reports
|
||||
|
@ -99,6 +100,14 @@ def handle_result(msg):
|
|||
conf_session.state = 'deployed'
|
||||
conf_session.save(session)
|
||||
|
||||
#close deployment
|
||||
deployment = get_last_deployment(session, environment.id)
|
||||
deployment.finished = timeutils.utcnow()
|
||||
status = Status()
|
||||
status.deployment_id = deployment.id
|
||||
status.text = "Deployment finished"
|
||||
deployment.statuses.append(status)
|
||||
deployment.save(session)
|
||||
msg.channel.basic_ack(msg.delivery_tag)
|
||||
|
||||
|
||||
|
@ -115,11 +124,16 @@ def handle_report(msg):
|
|||
status.update(params)
|
||||
|
||||
session = get_session()
|
||||
#connect with session
|
||||
conf_session = session.query(Session).filter_by(
|
||||
**{'environment_id': status.environment_id,
|
||||
'state': 'deploying'}).first()
|
||||
status.session_id = conf_session.id
|
||||
|
||||
#connect with deployment
|
||||
with session.begin():
|
||||
running_deployment = get_last_deployment(session,
|
||||
status.environment_id)
|
||||
status.deployment_id = running_deployment.id
|
||||
session.add(status)
|
||||
|
||||
|
||||
def get_last_deployment(session, env_id):
|
||||
query = session.query(Deployment). \
|
||||
filter_by(environment_id=env_id). \
|
||||
order_by(desc(Deployment.started))
|
||||
return query.first()
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from sqlalchemy.schema import MetaData, Table, Column, ForeignKey
|
||||
from sqlalchemy.types import String, DateTime
|
||||
|
||||
meta = MetaData()
|
||||
|
||||
deployment = Table('deployment', meta,
|
||||
Column('id', String(32), primary_key=True),
|
||||
Column('environment_id', String(32),
|
||||
ForeignKey('environment.id')),
|
||||
Column('created', DateTime, nullable=False),
|
||||
Column('updated', DateTime, nullable=False),
|
||||
Column('started', DateTime, nullable=False),
|
||||
Column('finished', DateTime, nullable=True))
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta.bind = migrate_engine
|
||||
meta.reflect()
|
||||
deployment.create()
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
meta.bind = migrate_engine
|
||||
deployment.drop()
|
|
@ -0,0 +1,43 @@
|
|||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from sqlalchemy.schema import MetaData, Table, Column, ForeignKey
|
||||
from sqlalchemy.types import String
|
||||
|
||||
meta = MetaData()
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta.bind = migrate_engine
|
||||
meta.reflect()
|
||||
status = Table('status', meta, autoload=True)
|
||||
deployment_id = Column('deployment_id', String(32),
|
||||
ForeignKey('deployment.id'))
|
||||
deployment_id.create(status)
|
||||
status.c.environment_id.drop()
|
||||
status.c.session_id.drop()
|
||||
status.c.entity.alter(nullable=True)
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
meta.bind = migrate_engine
|
||||
meta.reflect()
|
||||
status = Table('status', meta, autoload=True)
|
||||
status.c.deployment_id.drop()
|
||||
environment_id = Column('environment_id', String(32),
|
||||
ForeignKey('environment.id'))
|
||||
environment_id.create(status)
|
||||
session_id = Column('session_id', String(32), ForeignKey('session.id'))
|
||||
session_id.create(status)
|
||||
status.c.entity.alter(nullable=False)
|
|
@ -0,0 +1,31 @@
|
|||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from sqlalchemy.schema import MetaData, Table, Column
|
||||
from sqlalchemy.types import Text
|
||||
|
||||
meta = MetaData()
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta.bind = migrate_engine
|
||||
deployment = Table('deployment', meta, autoload=True)
|
||||
description = Column('description', Text(), nullable=True, default='{}')
|
||||
description.create(deployment)
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
meta.bind = migrate_engine
|
||||
deployment = Table('deployment', meta, autoload=True)
|
||||
deployment.c.description.drop()
|
|
@ -107,8 +107,8 @@ class Environment(BASE, ModelBase):
|
|||
|
||||
sessions = relationship("Session", backref='environment',
|
||||
cascade='save-update, merge, delete')
|
||||
statuses = relationship("Status", backref='environment',
|
||||
cascade='save-update, merge, delete')
|
||||
deployments = relationship("Deployment", backref='environment',
|
||||
cascade='save-update, merge, delete')
|
||||
|
||||
def to_dict(self):
|
||||
dictionary = super(Environment, self).to_dict()
|
||||
|
@ -136,23 +136,42 @@ class Session(BASE, ModelBase):
|
|||
return dictionary
|
||||
|
||||
|
||||
class Deployment(BASE, ModelBase):
|
||||
__tablename__ = 'deployment'
|
||||
|
||||
id = Column(String(32), primary_key=True, default=uuidutils.generate_uuid)
|
||||
started = Column(DateTime, default=timeutils.utcnow, nullable=False)
|
||||
finished = Column(DateTime, default=None, nullable=True)
|
||||
description = Column(JsonBlob(), nullable=False)
|
||||
environment_id = Column(String(32), ForeignKey('environment.id'))
|
||||
|
||||
statuses = relationship("Status", backref='deployment',
|
||||
cascade='save-update, merge, delete')
|
||||
|
||||
def to_dict(self):
|
||||
dictionary = super(Deployment, self).to_dict()
|
||||
del dictionary["description"]
|
||||
if 'statuses' in dictionary:
|
||||
del dictionary['statuses']
|
||||
if 'environment' in dictionary:
|
||||
del dictionary['environment']
|
||||
return dictionary
|
||||
|
||||
|
||||
class Status(BASE, ModelBase):
|
||||
__tablename__ = 'status'
|
||||
|
||||
id = Column(String(32), primary_key=True, default=uuidutils.generate_uuid)
|
||||
entity_id = Column(String(32), nullable=False)
|
||||
entity = Column(String(10), nullable=False)
|
||||
environment_id = Column(String(32), ForeignKey('environment.id'))
|
||||
session_id = Column(String(32), ForeignKey('session.id'))
|
||||
entity_id = Column(String(32), nullable=True)
|
||||
entity = Column(String(10), nullable=True)
|
||||
deployment_id = Column(String(32), ForeignKey('deployment.id'))
|
||||
text = Column(Text(), nullable=False)
|
||||
|
||||
def to_dict(self):
|
||||
dictionary = super(Status, self).to_dict()
|
||||
#object relations may be not loaded yet
|
||||
if 'session' in dictionary:
|
||||
del dictionary['session']
|
||||
if 'environment' in dictionary:
|
||||
del dictionary['environment']
|
||||
if 'deployment' in dictionary:
|
||||
del dictionary['deployment']
|
||||
return dictionary
|
||||
|
||||
|
||||
|
@ -160,7 +179,7 @@ def register_models(engine):
|
|||
"""
|
||||
Creates database tables for all models with the given engine
|
||||
"""
|
||||
models = (Environment, Status, Session)
|
||||
models = (Environment, Status, Session, Deployment)
|
||||
for model in models:
|
||||
model.metadata.create_all(engine)
|
||||
|
||||
|
@ -169,6 +188,6 @@ def unregister_models(engine):
|
|||
"""
|
||||
Drops database tables for all models with the given engine
|
||||
"""
|
||||
models = (Environment, Status, Session)
|
||||
models = (Environment, Status, Session, Deployment)
|
||||
for model in models:
|
||||
model.metadata.drop_all(engine)
|
||||
|
|
|
@ -17,7 +17,7 @@ from amqplib.client_0_8 import Message
|
|||
import anyjson
|
||||
import eventlet
|
||||
from muranoapi.common import config
|
||||
from muranoapi.db.models import Session, Environment
|
||||
from muranoapi.db.models import Session, Environment, Deployment, Status
|
||||
from muranoapi.db.session import get_session
|
||||
|
||||
|
||||
|
@ -126,7 +126,15 @@ class SessionServices(object):
|
|||
environment['token'] = token
|
||||
|
||||
session.state = SessionState.deploying
|
||||
session.save(unit)
|
||||
deployment = Deployment()
|
||||
deployment.environment_id = environment['id']
|
||||
deployment.description = session.description
|
||||
status = Status()
|
||||
status.text = "Deployment scheduled"
|
||||
deployment.statuses.append(status)
|
||||
with unit.begin():
|
||||
unit.add(session)
|
||||
unit.add(deployment)
|
||||
|
||||
connection = amqp.Connection('{0}:{1}'.
|
||||
format(rabbitmq.host, rabbitmq.port),
|
||||
|
|
Loading…
Reference in New Issue