Commit 36d3df83 authored by Daniele Venzano's avatar Daniele Venzano

Revert some API changes as they belong to a development branch, fix the observer in the process

parent e3b2fab8
......@@ -25,12 +25,12 @@ from argparse import ArgumentParser, Namespace, FileType, RawDescriptionHelpForm
from pprint import pprint
from zoe_cmd import utils
from zoe_lib.zoe_api import ZoeClient
from zoe_lib.users import ZoeUserAPI
from zoe_lib.services import ZoeServiceAPI
from zoe_lib.exceptions import ZoeAPIException
from zoe_lib.executions import ZoeExecutionsAPI
from zoe_lib.query import ZoeQueryAPI
from zoe_lib.applications import app_validate
from zoe_lib.applications import app_validate, predefined_app_generate, predefined_app_list
def stats_cmd(_):
......@@ -40,7 +40,7 @@ def stats_cmd(_):
def user_new_cmd(args):
api = ZoeClient(utils.zoe_url(), utils.zoe_user(), utils.zoe_pass())
api = ZoeUserAPI(utils.zoe_url(), utils.zoe_user(), utils.zoe_pass())
name = args.name
password = args.password
role = args.role
......@@ -48,14 +48,14 @@ def user_new_cmd(args):
print("Role must be one of admin, user, guest)")
return
try:
api.user_new(name, password, role)
api.create(name, password, role)
except ZoeAPIException as e:
print('Error creating user: {}'.format(e))
def user_get_cmd(args):
api = ZoeClient(utils.zoe_url(), utils.zoe_user(), utils.zoe_pass())
user = api.user_get(args.name)
api = ZoeUserAPI(utils.zoe_url(), utils.zoe_user(), utils.zoe_pass())
user = api.get(args.name)
if user is None:
print('No such user')
else:
......@@ -65,13 +65,13 @@ def user_get_cmd(args):
def user_delete_cmd(args):
api = ZoeClient(utils.zoe_url(), utils.zoe_user(), utils.zoe_pass())
api.user_delete(args.name)
api = ZoeUserAPI(utils.zoe_url(), utils.zoe_user(), utils.zoe_pass())
api.delete(args.name)
def user_list_cmd(_):
api = ZoeClient(utils.zoe_url(), utils.zoe_user(), utils.zoe_pass())
users = api.user_list()
api = ZoeQueryAPI(utils.zoe_url(), utils.zoe_user(), utils.zoe_pass())
users = api.query('user')
for user in users:
print('<- User {} ->'.format(user['name']))
print('Role: {}'.format(user['role']))
......@@ -79,15 +79,13 @@ def user_list_cmd(_):
def pre_app_list_cmd(_):
api = ZoeClient(utils.zoe_url(), utils.zoe_user(), utils.zoe_pass())
for a in api.predefined_app_list():
for a in predefined_app_list():
print(a)
def pre_app_export_cmd(args):
api = ZoeClient(utils.zoe_url(), utils.zoe_user(), utils.zoe_pass())
try:
app = api.predefined_app_generate(args.app_name)
app = predefined_app_generate(args.app_name)
except ZoeAPIException:
print('Application not found')
else:
......
......@@ -19,11 +19,39 @@ This module contains code to validate application descriptions.
import logging
from zoe_lib.exceptions import InvalidApplicationDescription
from zoe_lib.exceptions import InvalidApplicationDescription, ZoeAPIException
from zoe_lib.predefined_apps import PREDEFINED_APPS
log = logging.getLogger(__name__)
def predefined_app_list():
"""
Returns a list of predefined application available
:return: a list of application names
"""
name_list = []
for gen_app in PREDEFINED_APPS:
app = gen_app()
name_list.append(app['name'])
return name_list
def predefined_app_generate(name):
"""
Returns the predefined application corresponding to the name given as argument
:param name: the name of the application to generate
:return: an application dictionary
"""
for gen_app in PREDEFINED_APPS:
app = gen_app()
if app['name'] == name:
return app
raise ZoeAPIException('No such predefined application')
def app_validate(data):
required_keys = ['name', 'will_end', 'priority', 'requires_binary', 'version']
for k in required_keys:
......
......@@ -28,12 +28,15 @@ class ZoeServiceAPI(ZoeAPIBase):
"""
The service API class. Services are read-only objects. The delete operation merely informs the master that a service has died outside of its control.
"""
def get(self, container_id: int) -> dict:
def get(self, container_id):
"""
Retrieve service state.
:param container_id: the service to query
:return:
:type container_id: int
:rtype dict
"""
c, status_code = self._rest_get('/service/' + str(container_id))
if status_code == 200:
......@@ -43,14 +46,16 @@ class ZoeServiceAPI(ZoeAPIBase):
else:
raise ZoeAPIException('error retrieving service {}'.format(container_id))
def died(self, service_name, execution_name):
def died(self, container_id):
"""
Inform the master that a service died. Used by the observer process.
:param service_name: name of the service that died
:param execution_name: name of the execution the service that died belongs to
:param container_id: ID of the service that died
:return:
:type container_id: int
:rtype: None
"""
data, status_code = self._rest_delete('/service/{}/{}'.format(execution_name, service_name))
data, status_code = self._rest_delete('/service/{}'.format(container_id))
if status_code != 204:
raise ZoeAPIException(data['message'])
......@@ -27,6 +27,18 @@ class ZoeUserAPI(ZoeAPIBase):
The UserAPI class has methods for interacting with Zoe's user system.
"""
def create(self, name, password, role):
"""
Creates a new user.
:param name: the user name address
:param password: the user password
:param role: the user role
:return: the new user ID
:type name: str
:type password: str
:type role: str
"""
data = {
'name': name,
'password': password,
......@@ -39,6 +51,15 @@ class ZoeUserAPI(ZoeAPIBase):
raise ZoeAPIException(user['message'])
def get(self, user_name):
"""
Get a user object given a user_name.
:param user_name: the user_name to retrieve
:return: the user dictionary, or None
:type user_name: str
:rtype dict|None
"""
user, status_code = self._rest_get('/user/' + user_name)
if status_code == 200:
return user
......@@ -46,6 +67,14 @@ class ZoeUserAPI(ZoeAPIBase):
return None
def delete(self, user_name):
"""
Delete a user given a user_name.
:param user_name: the user_name to delete
:return: None
:type user_name: str
"""
data, status_code = self._rest_delete('/user/' + str(user_name))
if status_code != 204:
raise ZoeAPIException(data['message'])
# Copyright (c) 2016, Daniele Venzano
#
# 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 zoe_lib.users import ZoeUserAPI
from zoe_lib.executions import ZoeExecutionsAPI
from zoe_lib.services import ZoeServiceAPI
from zoe_lib.info import ZoeInfoAPI
from zoe_lib.query import ZoeQueryAPI
from zoe_lib.exceptions import ZoeAPIException
from zoe_lib.predefined_apps import PREDEFINED_APPS
class ZoeClient:
def __init__(self, url, user, password):
"""
Create a new ZoeAPI client instance.
:param url: the master URL
:param user: the user name to use for the connection
:param password: the user password
"""
self.user_api = ZoeUserAPI(url, user, password)
self.exec_api = ZoeExecutionsAPI(url, user, password)
self.service_api = ZoeServiceAPI(url, user, password)
self.query_api = ZoeQueryAPI(url, user, password)
info_api = ZoeInfoAPI(url, user, password)
master_info = info_api.info()
self.deployment_name = master_info['deployment_name']
def _validate_user_name(self, user_name):
if '.-' in user_name:
raise ZoeAPIException('User names cannot contain "." or "-"')
def _validate_role(self, role_name):
if role_name not in ['admin', 'user', 'guest']:
raise ZoeAPIException('Roles must be one of admin, user or guest')
def user_new(self, name, password, role):
"""
Creates a new user.
:param name: the user name address
:param password: the user password
:param role: the user role
:return: the new user ID
:type name: str
:type password: str
:type role: str
"""
self._validate_user_name(name)
self._validate_role(name)
return self.user_api.create(name, password, role)
def user_get(self, user_name):
"""
Get a user object given a user_name.
:param user_name: the user_name to retrieve
:return: the user dictionary, or None
:type user_name: str
:rtype dict|None
"""
self._validate_user_name(user_name)
return self.user_api.get(user_name)
def user_delete(self, user_name):
"""
Delete a user given a user_name.
:param user_name: the user_name to delete
:return: None
:type user_name: str
"""
self._validate_user_name(user_name)
return self.user_api.delete(user_name)
def user_list(self):
"""
Retrieves the list of users (can be used only by a user with the admin role.
:return: a list of users
"""
return self.query_api.query('user')
def predefined_app_list(self):
"""
Returns a list of predefined application available
:return: a list of application names
"""
name_list = []
for gen_app in PREDEFINED_APPS:
app = gen_app()
name_list.append(app['name'])
return name_list
def predefined_app_generate(self, name):
"""
Returns the predefined application corresponding to the name given as argument
:param name: the name of the application to generate
:return: an application dictionary
"""
for gen_app in PREDEFINED_APPS:
app = gen_app()
if app['name'] == name:
return app
raise ZoeAPIException('No such predefined application')
......@@ -62,10 +62,12 @@ class PlatformManager:
copts.name = service_description.name + "-" + execution.name + "-" + execution.owner.name + "-" + get_conf().deployment_name + "-zoe"
copts.set_memory_limit(service_description.required_resources['memory'])
copts.network_name = '{}-{}-zoe'.format(execution.owner.name, get_conf().deployment_name)
container_id = self.state_manager.gen_id()
service_id = self.state_manager.gen_id()
copts.labels = {
'zoe.execution.name': execution.name,
'zoe.execution.id': str(execution.id),
'zoe.service.name': service_description.name,
'zoe.service.id': str(service_id),
'zoe.owner': execution.owner.name,
'zoe.deployment_name': get_conf().deployment_name,
'zoe.type': 'app_service'
......@@ -105,7 +107,7 @@ class PlatformManager:
service.is_monitor = service_description.monitor
service.ports = [p.to_dict() for p in service_description.ports]
service.id = container_id
service.id = service_id
execution.services.append(service)
service.execution = execution
......
......@@ -36,10 +36,9 @@ def guest_check_thread(args):
zoe_containers = swarm.list({'zoe.deployment_name': get_conf().deployment_name})
for c in zoe_containers:
if 'Exited' in c['status']:
zoe_name = c['labels']['zoe.service.name']
exec_name = c['labels']['zoe.execution.name']
zoe_id = c['labels']['zoe.service.id']
try:
container_died(zoe_name, exec_name)
container_died(zoe_id)
except ZoeAPIException:
log.warning('Container ' + c['name'] + ' has died, but Zoe does not know anything about it, deleting')
swarm.terminate_container(c['id'], delete=True)
......
......@@ -20,19 +20,18 @@ def main_callback(event):
if event['Action'] == "die":
try:
service_name = event['Actor']['Attributes']['zoe.service.name']
execution_name = event['Actor']['Attributes']['zoe.execution.name']
container_died(service_name, execution_name)
service_id = event['Actor']['Attributes']['zoe.service.id']
container_died(service_id)
except KeyError:
return
def container_died(service_name, execution_name):
def container_died(service_id):
log.debug('A container died')
# tell the master via the rest api
cont_api = ZoeServiceAPI(get_conf().master_url, 'zoeadmin', get_conf().zoeadmin_password)
try:
cont_api.died(service_name, execution_name)
cont_api.died(service_id)
except ZoeAPIException as e:
if e.message != "No such service":
log.exception('Error reporting a dead service')
# Copyright (c) 2015, Daniele Venzano
# Copyright (c) 2016, Daniele Venzano
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -21,8 +21,8 @@ from zoe_lib.services import ZoeServiceAPI
from zoe_lib.executions import ZoeExecutionsAPI
from zoe_lib.predefined_apps.eurecom_aml_lab import spark_jupyter_notebook_lab_app
from zoe_lib.query import ZoeQueryAPI
from zoe_lib.users import ZoeUserAPI
from zoe_lib.exceptions import ZoeAPIException
from zoe_lib.zoe_api import ZoeClient
from zoe_web.config import get_conf
from zoe_web.web import web_bp
......@@ -49,8 +49,8 @@ def home_guest():
if match is None:
return missing_auth()
api = ZoeClient(get_conf().master_url, guest_identifier, guest_password)
query_api = ZoeQueryAPI(get_conf().master_url, guest_identifier, guest_password)
user_api = ZoeUserAPI(get_conf().master_url, guest_identifier, guest_password)
template_vars = {
'refresh': randint(2, 8),
......@@ -61,7 +61,7 @@ def home_guest():
}
try:
user = api.user_get(guest_identifier)
user = user_api.get(guest_identifier)
except ZoeAPIException:
return missing_auth()
if len(user) == 0:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment