Source code for cloudify_rest_client.manager

########
# Copyright (c) 2014 GigaSpaces Technologies Ltd. All rights reserved
#
# 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 cloudify_rest_client.responses import ListResponse


[docs] class ConfigItem(dict): """A configuration entry""" def __init__(self, config): super(ConfigItem, self).__init__() self.update(config) @property def name(self): """Name of the configuration entry""" return self.get('name') @property def value(self): """The setting value""" return self.get('value') @property def schema(self): """JSON schema of the configuration value, if any. When changing the setting, the new value must conform to this schema. """ return self.get('schema') @property def scope(self): """Components affected by this configuration entry. Eg. mgmtworker, rest, or agents """ return self.get('scope') @property def updater_name(self): """Name of the user who last changed this value""" return self.get('updater_name') @property def updated_at(self): """Time this value was last changed at""" return self.get('updated_at') @property def is_editable(self): """Whether or not it is possible to change this setting. Settings that are not marked editable can still be changed by setting force=True, however that might lead to unexpected results. Use with caution. """ return self.get('is_editable') @property def admin_only(self): """This setting's value is only viewable (and changeable) by admins""" return self.get('admin_only')
[docs] class ManagerItem(dict): """A manager entry""" def __init__(self, manager): super(ManagerItem, self).__init__() self.update(manager) @property def id(self): """ Manager's ID in the DB (unique, incremental) type: int """ return self.get('id') @property def hostname(self): """ Manager's hostname (unique) type: string """ return self.get('hostname') @property def private_ip(self): """ Manager's private IP type: string """ return self.get('private_ip') @property def public_ip(self): """ Manager's public IP type: string """ return self.get('public_ip') @property def version(self): """ Manager's version type: string """ return self.get('version') @property def edition(self): """ Manager's edition type: string """ return self.get('edition') @property def distribution(self): """ Manager's distribution type: string """ return self.get('distribution') @property def distro_release(self): """ Manager's distribution release type: string """ return self.get('distro_release') @property def fs_sync_node_id(self): """ Manager's FS sync node id - used by Syncthing replication type: string """ return self.get('fs_sync_node_id') @property def networks(self): """Networks and IPs declared for this manager :rtype: dict """ return self.get('networks') @property def ca_cert_content(self): """Content of the CA cert to use for connecting to this manager""" return self.get('ca_cert_content')
[docs] class DBNodeItem(dict): def __init__(self, db_node): super(DBNodeItem, self).__init__() self.update(db_node) @property def name(self): """ Name of this DB node""" return self.get('name') @property def host(self): """IP address of this DB node""" return self.get('host') @property def is_external(self): """Is the DB external""" return self.get('is_external')
[docs] class RabbitMQBrokerItem(dict): def __init__(self, broker): super(RabbitMQBrokerItem, self).__init__() self.update(broker) @property def name(self): """Name of this broker""" return self.get('name') @property def host(self): """IP address of this broker""" return self.get('host') @property def username(self): """Admin username for this broker. Only set if the calling user has the broker_credentials permission. """ return self.get('username') @property def password(self): """Admin password for this broker. Only set if the calling user has the broker_credentials permission. """ return self.get('password') @property def management_host(self): """IP address of this broker""" return self.get('management_host') @property def port(self): """The TCP port this broker is listening on""" return self.get('port') @property def params(self): """Additional params to use when creating a connection""" return self.get('params') @property def ca_cert_content(self): """Content of the CA cert to use for connecting to this broker""" return self.get('ca_cert_content') @property def networks(self): """Networks and IPs declared for this broker :rtype: dict """ return self.get('networks') @property def is_external(self): """Is the broker external""" return self.get('is_external')
[docs] class ManagerClient(object): def __init__(self, api): self.api = api
[docs] def get_status(self): """ :return: Cloudify's management machine status. """ response = self.api.get('/status') return response
[docs] def get_config(self, name=None, scope=None): """Get configuration of the manager. If name is provided, only return that single value. If scope is provided, return all values for that scope. """ if name and scope: response = self.api.get('/config/{0}.{1}'.format(scope, name)) return ConfigItem(response) if name: response = self.api.get('/config/{0}'.format(name)) return ConfigItem(response) if scope: response = self.api.get('/config', params={'scope': scope}) else: response = self.api.get('/config') return ListResponse([ConfigItem(item) for item in response['items']], response['metadata'])
[docs] def put_config(self, name, value, force=False): """Update a given setting. Note that the new value must conform to the schema, if any. :param force: Force changing non-editable settings """ response = self.api.put('/config/{0}'.format(name), data={ 'value': value, 'force': force }) return ConfigItem(response)
[docs] def add_manager(self, hostname, private_ip, public_ip, version, edition, distribution, distro_release, ca_cert_content=None, fs_sync_node_id='', networks=None): """ Add a new manager to the managers table """ manager = { 'hostname': hostname, 'private_ip': private_ip, 'public_ip': public_ip, 'version': version, 'edition': edition, 'distribution': distribution, 'distro_release': distro_release } if ca_cert_content: manager['ca_cert_content'] = ca_cert_content if fs_sync_node_id: manager['fs_sync_node_id'] = fs_sync_node_id if networks: manager['networks'] = networks response = self.api.post('/managers', data=manager) return ManagerItem(response)
[docs] def remove_manager(self, hostname): """ Remove a manager from the managers table Will be used for clustering when a manager needs to be removed from the cluster, not necessarily for uninstalling the manager :param hostname: The manager's hostname """ self.api.delete('/managers/{0}'.format(hostname))
[docs] def update_manager(self, hostname, fs_sync_node_id, bootstrap_cluster): """ Updating a manager's FS sync node id used by Syncthing replication :param hostname: hostname of the manager to update :param fs_sync_node_id: Syncthing node ID :param bootstrap_cluster: Whether it is the 1st manager in the cluster or not """ response = self.api.put('/managers/{0}'.format(hostname), data={ 'fs_sync_node_id': fs_sync_node_id, 'bootstrap_cluster': bootstrap_cluster }) return ManagerItem(response)
[docs] def get_managers(self, hostname=None, _include=None): """ Get all the managers in the managers table or Get a specific manager based on 'hostname' :param hostname: hostname of manager to return :param _include: list of columns to include in the returned list """ if hostname: response = self.api.get('/managers', params={'hostname': hostname}, _include=_include) else: response = self.api.get('/managers', _include=_include) return ListResponse( [ManagerItem(item) for item in response['items']], response['metadata'] )
[docs] def add_broker(self, name, address, port=None, networks=None): """Add a broker to the brokers table. This will allow cloudify components to use this broker. It will not actually create the broker- the creation should be done beforehand using cfy_manager. :param name: The broker's name. :param address: The broker's address. :param port: The broker's port, if not default (5671). :param networks: The broker's networks. This will default to having a default network with the address parameter. If this is supplied, the address in the address parameter must belong to one of the networks. :return: The broker that was created. """ params = { 'name': name, 'address': address, } if port: params['port'] = port if networks: params['networks'] = networks response = self.api.post('/brokers', data=params) return RabbitMQBrokerItem(response)
[docs] def remove_broker(self, name): """Remove a broker from the brokers table. This will stop cloudify components from talking directly to the specified broker. It will not take any action against the broker itself, which should be removed using cfy_manager. :param name: The broker's name. :return: The broker that was deleted. """ self.api.delete('/brokers/{0}'.format(name))
[docs] def update_broker(self, name, networks): """Update a broker. Update a broker, adding or changing networks for that broker. Networks cannot be deleted from a broker without deleting that broker. :param name: The broker's name. :param networks: The networks to add or change. :return: The updated broker. """ response = self.api.put('/brokers/{0}'.format(name), data={ 'networks': networks, }) return RabbitMQBrokerItem(response)
[docs] def get_brokers(self): response = self.api.get('/brokers',) return ListResponse( [RabbitMQBrokerItem(item) for item in response['items']], response['metadata'] )
[docs] def update_db_nodes(self): """Force updating DB information on all manager nodes. :return: A list of DB nodes in the cluster. """ params = {'action': 'update'} response = self.api.post('/db-nodes', data=params) return ListResponse( [DBNodeItem(item) for item in response['items']], response['metadata'] )
[docs] def get_db_nodes(self): response = self.api.get('/db-nodes') return ListResponse( [DBNodeItem(item) for item in response['items']], response['metadata'] )
[docs] def get_version(self): """ :return: Cloudify's management machine version information. """ response = self.api.get('/version', versioned_url=False) return response
[docs] def get_context(self, _include=None): """ Gets the context which was stored on management machine bootstrap. The context contains Cloudify specific information and Cloud provider specific information. :param _include: List of fields to include in response. :return: Context stored in manager. """ response = self.api.get('/provider/context', _include=_include) return response
[docs] def create_context(self, name, context): """ Creates context in Cloudify's management machine. This method is usually invoked right after management machine bootstrap with relevant Cloudify and cloud provider context information. :param name: Cloud provider name. :param context: Context as dict. :return: Create context result. """ data = {'name': name, 'context': context} response = self.api.post('/provider/context', data, expected_status_code=201) return response
[docs] def update_context(self, name, context): """ Updates context in Cloudify's management machine. The context is imperative for the manager to function properly, only use this method if you know exactly what you are doing. Note that if the provider context does not exist, this call will result with an error. :param name: Cloud provider name. :param context: Context as dict. """ data = {'name': name, 'context': context} response = self.api.post('/provider/context', data, expected_status_code=200, params={'update': 'true'}) return response