2157 lines
56 KiB
Python
2157 lines
56 KiB
Python
# Licensed to the Apache Software Foundation (ASF) under one or more
|
|
# contributor license agreements. See the NOTICE file distributed with
|
|
# this work for additional information regarding copyright ownership.
|
|
# The ASF licenses this file to You 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.
|
|
"""
|
|
1&1 Cloud Server Compute driver
|
|
"""
|
|
import json
|
|
|
|
from libcloud.compute.providers import Provider
|
|
from libcloud.common.base import JsonResponse, ConnectionKey
|
|
from libcloud.compute.base import NodeSize, NodeImage, NodeLocation, \
|
|
Node, NodeAuthPassword, NodeAuthSSHKey
|
|
from libcloud.common.types import InvalidCredsError
|
|
from libcloud.compute.types import NodeState
|
|
from libcloud.utils.py3 import httplib
|
|
from libcloud.compute.base import NodeDriver
|
|
|
|
from time import sleep
|
|
|
|
API_HOST = 'cloudpanel-api.1and1.com'
|
|
API_VERSION = '/v1/'
|
|
|
|
__all__ = [
|
|
'API_HOST',
|
|
'API_VERSION',
|
|
'OneAndOneResponse',
|
|
'OneAndOneConnection',
|
|
'OneAndOneNodeDriver'
|
|
]
|
|
|
|
|
|
class OneAndOneResponse(JsonResponse):
|
|
"""
|
|
OneAndOne response parsing.
|
|
"""
|
|
valid_response_codes = [httplib.OK, httplib.CREATED, httplib.ACCEPTED]
|
|
|
|
def parse_error(self):
|
|
|
|
if self.status == httplib.UNAUTHORIZED:
|
|
body = self.parse_body()
|
|
raise InvalidCredsError(body['message'])
|
|
else:
|
|
body = self.parse_body()
|
|
if 'message' in body:
|
|
error = '%s (code: %s)' % (body['message'], self.status)
|
|
else:
|
|
error = body
|
|
return error
|
|
|
|
def success(self):
|
|
return self.status in self.valid_response_codes
|
|
|
|
|
|
class OneAndOneConnection(ConnectionKey):
|
|
"""
|
|
Connection class for the 1&1 driver
|
|
"""
|
|
|
|
host = API_HOST
|
|
api_prefix = API_VERSION
|
|
responseCls = OneAndOneResponse
|
|
|
|
def encode_data(self, data):
|
|
return json.dumps(data)
|
|
|
|
def add_default_headers(self, headers):
|
|
"""
|
|
Add headers that are necessary for every request
|
|
|
|
This method adds ``token`` and ``Content-Type`` to the request.
|
|
"""
|
|
headers['X-Token'] = self.key
|
|
headers['Content-Type'] = 'application/json'
|
|
return headers
|
|
|
|
def request(self, action, params=None, data=None, headers=None,
|
|
method='GET', raw=False):
|
|
"""
|
|
Some requests will use the href attribute directly.
|
|
If this is not the case, then we should formulate the
|
|
url based on the action specified.
|
|
If we are using a full url, we need to remove the
|
|
host and protocol components.
|
|
"""
|
|
action = self.api_prefix + action.lstrip('/')
|
|
|
|
return super(OneAndOneConnection, self). \
|
|
request(action=action,
|
|
params=params,
|
|
data=data,
|
|
headers=headers,
|
|
method=method,
|
|
raw=raw)
|
|
|
|
|
|
class OneAndOneNodeDriver(NodeDriver):
|
|
"""
|
|
Base OneAndOne node driver.
|
|
"""
|
|
connectionCls = OneAndOneConnection
|
|
name = '1and1'
|
|
website = 'http://www.1and1.com'
|
|
type = Provider.ONEANDONE
|
|
|
|
NODE_STATE_MAP = {
|
|
'POWERING_ON': NodeState.STARTING,
|
|
'POWERING_OFF': NodeState.PENDING,
|
|
'POWERED_OFF': NodeState.STOPPING,
|
|
'POWERED_ON': NodeState.RUNNING,
|
|
'REBOOTING': NodeState.REBOOTING,
|
|
'CONFIGURING': NodeState.RECONFIGURING,
|
|
'REMOVING': NodeState.UNKNOWN,
|
|
'DEPLOYING': NodeState.STARTING,
|
|
}
|
|
|
|
"""
|
|
Core Functions
|
|
"""
|
|
|
|
def list_sizes(self):
|
|
"""
|
|
Lists all sizes
|
|
|
|
:return: A list of all configurable node sizes.
|
|
:rtype: ``list`` of :class:`NodeSize`
|
|
"""
|
|
sizes = []
|
|
|
|
fixed_instances = self._list_fixed_instances()
|
|
for value in fixed_instances:
|
|
node_size = self._to_node_size(value)
|
|
sizes.append(node_size)
|
|
|
|
return sizes
|
|
|
|
def list_locations(self):
|
|
"""
|
|
Lists all locations
|
|
|
|
:return: ``list`` of :class:`NodeLocation`
|
|
:rtype: ``list``
|
|
"""
|
|
datacenters = self.ex_list_datacenters()
|
|
locations = []
|
|
for values in datacenters:
|
|
node_size = self._to_location(values)
|
|
locations.append(node_size)
|
|
|
|
return locations
|
|
|
|
def list_images(self, image_type=None):
|
|
"""
|
|
:return: ``list`` of :class: `NodeImage`
|
|
:rtype: ``list``
|
|
"""
|
|
response = self.connection.request(
|
|
action='server_appliances',
|
|
method='GET'
|
|
)
|
|
|
|
return self._to_images(response.object, image_type)
|
|
|
|
def get_image(self, image_id):
|
|
response = self.connection.request(
|
|
action='server_appliances/%s' % image_id,
|
|
method='GET'
|
|
)
|
|
return self._to_image(response.object)
|
|
|
|
"""
|
|
Node functions
|
|
"""
|
|
|
|
def create_node(self,
|
|
name,
|
|
image,
|
|
ex_fixed_instance_size_id,
|
|
location=None,
|
|
auth=None,
|
|
ex_ip=None,
|
|
ex_monitoring_policy_id=None,
|
|
ex_firewall_policy_id=None,
|
|
ex_loadbalancer_id=None,
|
|
ex_description=None,
|
|
ex_power_on=None):
|
|
"""
|
|
Creates a node.
|
|
|
|
:param name: The name of the new node
|
|
:type name: `str`
|
|
|
|
:param ex_fixed_instance_size_id:
|
|
Fixed instance size ID from list_sizes
|
|
:type ex_fixed_instance_size_id: ``str``
|
|
|
|
:param location: 1&1 Data center Location
|
|
:type location: `NodeLocation`
|
|
|
|
:param ex_ip: IP address
|
|
:type ex_ip: `str`
|
|
|
|
:param ex_ssh_key: SSH Key
|
|
:type ex_ssh_key: `str`
|
|
|
|
:param password: Password
|
|
:type password: `str`
|
|
|
|
:param ex_monitoring_policy_id:
|
|
:type ex_firewall_policy_id: `str`
|
|
|
|
:param ex_firewall_policy_id:
|
|
:type ex_firewall_policy_id: `str`
|
|
|
|
:param ex_loadbalancer_id:
|
|
:type ex_loadbalancer_id: `str`
|
|
|
|
:param ex_description:
|
|
:type ex_description: `str`
|
|
|
|
:param ex_power_on:
|
|
:type ex_power_on: `bool`
|
|
|
|
:return: Instance of class ``Node``
|
|
:rtype: :class:`Node`
|
|
"""
|
|
|
|
body = {
|
|
'name': name,
|
|
'appliance_id': image.id,
|
|
'hardware': {
|
|
'fixed_instance_size_id': ex_fixed_instance_size_id
|
|
},
|
|
}
|
|
|
|
if location is not None:
|
|
body['datacenter_id'] = location.id
|
|
if ex_power_on is not None:
|
|
body['power_on'] = ex_power_on
|
|
|
|
if ex_description is not None:
|
|
body['description'] = ex_description
|
|
|
|
if ex_firewall_policy_id is not None:
|
|
body['firewall_policy_id'] = ex_firewall_policy_id
|
|
|
|
if ex_monitoring_policy_id is not None:
|
|
body['monitoring_policy_id'] = ex_monitoring_policy_id
|
|
|
|
if ex_loadbalancer_id is not None:
|
|
body['loadbalancer_id'] = ex_loadbalancer_id
|
|
|
|
if auth is not None:
|
|
if isinstance(auth, NodeAuthPassword):
|
|
body['password'] = auth.password
|
|
elif isinstance(auth, NodeAuthSSHKey):
|
|
body['rsa_key'] = auth.pubkey
|
|
if ex_ip is not None:
|
|
body['ip_id'] = ex_ip
|
|
|
|
response = self.connection.request(
|
|
action='servers',
|
|
data=body,
|
|
method='POST',
|
|
)
|
|
|
|
return self._to_node(response.object)
|
|
|
|
def list_nodes(self):
|
|
"""
|
|
List all nodes.
|
|
|
|
:return: ``list`` of :class:`Node`
|
|
:rtype: ``list``
|
|
"""
|
|
response = self.connection.request(
|
|
action='servers',
|
|
method='GET'
|
|
)
|
|
|
|
return self._to_nodes(response.object)
|
|
|
|
def destroy_node(self, node, ex_keep_ips=False):
|
|
"""
|
|
Destroys a node.
|
|
|
|
:param node: The node you wish to destroy.
|
|
:type volume: :class:`Node`
|
|
|
|
:param ex_keep_ips: True to keep all IP addresses assigned to the node
|
|
:type ex_keep_ips: : ``bool``
|
|
|
|
:return: Instance of class ``Node``
|
|
:rtype: :class: `Node`
|
|
"""
|
|
self.ex_shutdown_server(node.id)
|
|
|
|
self._wait_for_state(node.id, 'POWERED_OFF')
|
|
|
|
response = self.connection.request(
|
|
action='servers/%s' % node.id,
|
|
params={'keep_ips': ex_keep_ips},
|
|
method='DELETE'
|
|
)
|
|
|
|
return self._to_node(response.object)
|
|
|
|
def reboot_node(self, node):
|
|
"""
|
|
Reboots the node.
|
|
|
|
:param node: The node you wish to destroy.
|
|
:type volume: :class:`Node`
|
|
|
|
:return: Instance of class ``Node``
|
|
:rtype: :class: `Node`
|
|
"""
|
|
shutdown_body = {
|
|
"action": "REBOOT",
|
|
"method": "HARDWARE"
|
|
}
|
|
response = self.connection.request(
|
|
action='servers/%s/status/action' % node.id,
|
|
data=shutdown_body,
|
|
method='PUT',
|
|
)
|
|
return self._to_node(response.object)
|
|
|
|
"""
|
|
Extension functions
|
|
"""
|
|
|
|
def ex_rename_server(self, server_id, name=None, description=None):
|
|
"""
|
|
Renames the server
|
|
:param server_id: ID of the server you want to rename
|
|
|
|
:param name: New name of the server
|
|
:type: ``str``
|
|
|
|
:param description: New description of the server
|
|
:type: ``str``
|
|
|
|
:return: Instance of class ``Node``
|
|
:rtype: :class: `Node`
|
|
"""
|
|
|
|
body = {}
|
|
if name is not None:
|
|
body["name"] = name
|
|
if description is not None:
|
|
body["description"] = description
|
|
|
|
response = self.connection.request(
|
|
action='servers/%s' % server_id,
|
|
data=body,
|
|
method='PUT'
|
|
)
|
|
|
|
return self._to_node(response.object)
|
|
|
|
def ex_get_server_hardware(self, server_id):
|
|
"""
|
|
Gets all server hardware
|
|
|
|
:param server_id: Id of the server
|
|
:type: ``str``
|
|
|
|
:return: Server's hardware
|
|
:rtype: ``dict``
|
|
"""
|
|
response = self.connection.request(
|
|
action='servers/%s/hardware' % server_id,
|
|
method='GET'
|
|
)
|
|
return response.object
|
|
|
|
"""
|
|
Hardware operations
|
|
"""
|
|
|
|
def ex_modify_server_hardware(self, server_id,
|
|
fixed_instance_size_id=None, vcore=None,
|
|
cores_per_processor=None, ram=None):
|
|
"""
|
|
Modifies server's hardware
|
|
|
|
:param server_id:
|
|
:type: ``str``
|
|
|
|
:param fixed_instance_size_id: Id of the fixed instance size
|
|
:type: ``str``
|
|
|
|
:param vcore: Virtual cores count
|
|
:type: ``int``
|
|
|
|
:param cores_per_processor: Count of cores per procesor
|
|
:type: ``int``
|
|
|
|
:param ram: Amount of ram for the server
|
|
:type: ``int``
|
|
|
|
:return: Instance of class ``Node``
|
|
:type: :class: `Node`
|
|
"""
|
|
|
|
body = {}
|
|
|
|
if fixed_instance_size_id is not None:
|
|
body['fixed_instance_size_id'] = fixed_instance_size_id
|
|
if vcore is not None:
|
|
body['vcore'] = vcore
|
|
if cores_per_processor is not None:
|
|
body['cores_per_processor'] = cores_per_processor
|
|
if ram is not None:
|
|
body['ram'] = ram
|
|
|
|
response = self.connection.request(
|
|
action='servers/%s/hardware' % server_id,
|
|
data=body,
|
|
method='PUT'
|
|
)
|
|
|
|
return self._to_node(response.object)
|
|
|
|
"""
|
|
HDD operations
|
|
"""
|
|
|
|
def ex_modify_server_hdd(self, server_id, hdd_id=None, size=None):
|
|
"""
|
|
Modifies server hard disk drives
|
|
|
|
:param server_id: Id of the server
|
|
:type: ``str``
|
|
|
|
:param hdd_id: Id of the hard disk
|
|
:type: ``str``
|
|
|
|
:param size: Size of the hard disk
|
|
:type: ``str``
|
|
|
|
:return: Instance of class ``Node``
|
|
:rtype: :class: `Node`
|
|
"""
|
|
|
|
body = {}
|
|
|
|
if size is not None:
|
|
body['size'] = size
|
|
|
|
response = self.connection.request(
|
|
action='servers/%s/hardware/hdds/%s' % (server_id, hdd_id),
|
|
data=body,
|
|
method='PUT'
|
|
)
|
|
|
|
return self._to_node(response.object)
|
|
|
|
def ex_add_hdd(self, server_id, size, is_main):
|
|
"""
|
|
Add a hard disk to the server
|
|
|
|
:param server_id: Id of the server
|
|
:type: ``str``
|
|
|
|
:param size: Size of the new disk
|
|
:type: ``str``
|
|
|
|
:param is_main: Indicates if the disk is going to be the boot disk
|
|
:type: ``boolean``
|
|
|
|
:return: Instance of class ``Node``
|
|
:type: :class: `Node`
|
|
"""
|
|
body = {
|
|
'size': size,
|
|
'is_main': is_main
|
|
}
|
|
|
|
response = self.connection.request(
|
|
action='servers/%s/hardware/hdds' % server_id,
|
|
data=body,
|
|
method='POST'
|
|
)
|
|
|
|
return self._to_node(response.object)
|
|
|
|
def ex_remove_hdd(self, server_id, hdd_id):
|
|
"""
|
|
Removes existing hard disk
|
|
|
|
:param server_id: Id of the server
|
|
:type: ``str``
|
|
|
|
:param hdd_id: Id of the hard disk
|
|
:type: ``str``
|
|
|
|
:return: Instance of class ``Node``
|
|
:rtype: :class: `Node`
|
|
"""
|
|
|
|
response = self.connection.request(
|
|
action='servers/%s/hardware/hdds/%s' % (server_id, hdd_id),
|
|
method='DELETE'
|
|
)
|
|
|
|
return self._to_node(response.object)
|
|
|
|
"""
|
|
Data center operations
|
|
"""
|
|
|
|
def ex_list_datacenters(self):
|
|
"""
|
|
Lists all data centers
|
|
|
|
:return: List of data centers
|
|
:rtype: ``dict``
|
|
"""
|
|
response = self.connection.request(
|
|
action='datacenters',
|
|
method='GET'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_get_server(self, server_id):
|
|
"""
|
|
Gets a server
|
|
|
|
:param server_id: Id of the server to be retrieved
|
|
:type: ``str``
|
|
|
|
:return: Instance of class ``Node``
|
|
:rtype: :class: `Node`
|
|
"""
|
|
|
|
response = self.connection.request(
|
|
action='servers/%s' % (server_id),
|
|
method='GET'
|
|
)
|
|
|
|
return self._to_node(response.object)
|
|
|
|
def ex_shutdown_server(self, server_id, method='SOFTWARE'):
|
|
"""
|
|
Shuts down the server
|
|
|
|
:param server_id: Id of the server to be shut down
|
|
:type: ``str``
|
|
|
|
:param method: Method of shutting down "SOFTWARE" or "HARDWARE"
|
|
|
|
:return: Instance of class ``Node``
|
|
:rtype: :class: `Node`
|
|
"""
|
|
|
|
shutdown_body = {
|
|
'action': 'POWER_OFF',
|
|
'method': method
|
|
}
|
|
response = self.connection.request(
|
|
action='servers/%s/status/action' % (server_id),
|
|
data=shutdown_body,
|
|
method='PUT',
|
|
)
|
|
return self._to_node(response.object)
|
|
|
|
"""
|
|
Image operations
|
|
"""
|
|
|
|
def ex_get_server_image(self, server_id):
|
|
"""
|
|
Gets server image
|
|
|
|
:param server_id: Id of the server
|
|
:type: ``str``
|
|
|
|
:return: Server image
|
|
:rtype: ``dict``
|
|
"""
|
|
|
|
response = self.connection.request(
|
|
action='servers/%s/image' % server_id,
|
|
method='GET'
|
|
)
|
|
return response.object
|
|
|
|
def ex_reinstall_server_image(self, server_id, image_id, password=None):
|
|
"""
|
|
Installs a new image on the server
|
|
|
|
:param server_id: Id of the server
|
|
:type: ``str``
|
|
|
|
:param image_id: Id of the image (Server Appliance)
|
|
:type: ``str``
|
|
|
|
:param password: New password for the server
|
|
|
|
:return: Instance of class ``Node``
|
|
:rtype: :class: `Node`
|
|
"""
|
|
|
|
body = {
|
|
'id': image_id,
|
|
}
|
|
|
|
if password is not None:
|
|
body['password'] = password
|
|
|
|
response = self.connection.request(
|
|
action='servers/%s/image' % server_id,
|
|
data=body,
|
|
method='PUT'
|
|
)
|
|
return self._to_node(response.object)
|
|
|
|
"""
|
|
Server IP operations
|
|
"""
|
|
|
|
def ex_list_server_ips(self, server_id):
|
|
"""
|
|
Gets all server IP objects
|
|
|
|
:param server_id: Id of the server
|
|
:type: ``str``
|
|
|
|
:return: List of server IP objects
|
|
:rtype: ``list`` of ``dict``
|
|
"""
|
|
response = self.connection.request(
|
|
action='servers/%s/ips' % server_id,
|
|
method='GET'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_get_server_ip(self, server_id, ip_id):
|
|
"""
|
|
Get a single server IP object
|
|
|
|
:param server_id: Id of the server
|
|
:type: ``str``
|
|
|
|
:param ip_id: ID of the IP address
|
|
:type: ``str``
|
|
|
|
:return: IP address object
|
|
:rtype: ``dict``
|
|
"""
|
|
response = self.connection.request(
|
|
action='servers/%s/ips/%s' % (server_id, ip_id),
|
|
method='GET'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_assign_server_ip(self, server_id, ip_type):
|
|
"""
|
|
Assigns a new IP address to the server
|
|
|
|
:param server_id: Id of the server
|
|
:type: ``str``
|
|
|
|
:param ip_type: Type of the IP address [IPV4,IPV6]
|
|
:type: ``str``
|
|
|
|
:return: ``Node`` instance
|
|
:rtype: ``Node``
|
|
"""
|
|
|
|
body = {
|
|
'type': ip_type
|
|
}
|
|
|
|
response = self.connection.request(
|
|
action='servers/%s/ips' % server_id,
|
|
data=body,
|
|
method='POST'
|
|
)
|
|
|
|
return self._to_node(response.object)
|
|
|
|
def ex_remove_server_ip(self, server_id, ip_id, keep_ip=None):
|
|
"""
|
|
Removes an IP address from the server
|
|
|
|
:param server_id: Id of the server
|
|
:type: ``str``
|
|
|
|
:param ip_id: ID of the IP address
|
|
:type: ``str``
|
|
|
|
:param keep_ip: Indicates whether IP address will be removed from
|
|
the Cloud Panel
|
|
:type: ``boolean``
|
|
|
|
:return: ``Node`` instance
|
|
:rtype: ``Node``
|
|
"""
|
|
|
|
body = {}
|
|
if keep_ip is not None:
|
|
body['keep_ip'] = keep_ip
|
|
|
|
response = self.connection.request(
|
|
action='servers/%s/ips/%s' % (server_id, ip_id),
|
|
data=body,
|
|
method='DELETE'
|
|
)
|
|
|
|
return self._to_node(response.object)
|
|
|
|
def ex_get_server_firewall_policies(self, server_id, ip_id):
|
|
"""
|
|
Gets a firewall policy of attached to the server's IP
|
|
|
|
:param server_id: Id of the server
|
|
:type: ``str``
|
|
|
|
:param ip_id: ID of the IP address
|
|
:type: ``str``
|
|
|
|
:return: IP address object
|
|
:rtype: ``dict``
|
|
"""
|
|
|
|
response = self.connection.request(
|
|
action='/servers/%s/ips/%s/firewall_policy' % (server_id, ip_id),
|
|
method='GET'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_add_server_firewall_policy(self, server_id, ip_id, firewall_id):
|
|
"""
|
|
Adds a firewall policy to the server's IP address
|
|
|
|
:param server_id: Id of the server
|
|
:type: ``str``
|
|
|
|
:param ip_id: ID of the IP address
|
|
:type: ``str``
|
|
|
|
:param firewall_id: ID of the firewall policy
|
|
:type: ``str``
|
|
|
|
:return: ``Node`` instance
|
|
:rtype: ``Node``
|
|
"""
|
|
body = {
|
|
'id': firewall_id
|
|
}
|
|
response = self.connection.request(
|
|
action='/servers/%s/ips/%s/firewall_policy' % (server_id, ip_id),
|
|
data=body,
|
|
method='POST'
|
|
)
|
|
|
|
return self._to_node(response.object)
|
|
|
|
"""
|
|
Firewall Policy operations
|
|
"""
|
|
|
|
def ex_create_firewall_policy(self, name, rules, description=None):
|
|
"""
|
|
Creates a firewall Policy.
|
|
|
|
:param name:
|
|
:param description:
|
|
:param rules:
|
|
|
|
:rtype: `dict`
|
|
:return: `dict` firewall policy
|
|
|
|
"""
|
|
body = {
|
|
'name': name
|
|
}
|
|
|
|
if description is not None:
|
|
body['description'] = description
|
|
|
|
if len(rules) == 0:
|
|
raise ValueError(
|
|
'At least one firewall rule is required.'
|
|
)
|
|
else:
|
|
body['rules'] = rules
|
|
|
|
response = self.connection.request(
|
|
action='firewall_policies',
|
|
data=body,
|
|
method='POST',
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_list_firewall_policies(self):
|
|
""""
|
|
List firewall policies
|
|
|
|
:return: 'dict'
|
|
"""
|
|
|
|
response = self.connection.request(
|
|
action='firewall_policies',
|
|
method='GET'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_get_firewall_policy(self, fw_id):
|
|
"""
|
|
Gets firewall policy
|
|
|
|
:param fw_id: ID of the firewall policy
|
|
:return: 'dict'
|
|
"""
|
|
|
|
response = self.connection.request(
|
|
action='firewall_policy/%s' % fw_id,
|
|
method='GET'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_delete_firewall_policy(self, fw_id):
|
|
"""
|
|
Deletes firewall policy
|
|
|
|
:param fw_id: ID of the Firewall
|
|
:return: 'dict'
|
|
"""
|
|
response = self.connection.request(
|
|
action='firewall_policy/%s' % fw_id,
|
|
method='DELETE'
|
|
)
|
|
|
|
return response.object
|
|
|
|
"""
|
|
Shared storage operations
|
|
"""
|
|
|
|
def ex_list_shared_storages(self):
|
|
"""
|
|
List of shared storages
|
|
:return: 'dict'
|
|
"""
|
|
response = self.connection.request(
|
|
action='shared_storages',
|
|
method='GET'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_get_shared_storage(self, storage_id):
|
|
"""
|
|
Gets a shared storage
|
|
:return: 'dict'
|
|
"""
|
|
response = self.connection.request(
|
|
action='shared_storages/%s' % (storage_id),
|
|
method='GET'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_create_shared_storage(self, name, size, datacenter_id=None,
|
|
description=None):
|
|
"""
|
|
Creates a shared storage
|
|
:param name: Name of the storage
|
|
:param size: Size of the storage
|
|
:param datacenter_id: datacenter where storage should be created
|
|
:param description: description ot the storage
|
|
:return: 'dict'
|
|
"""
|
|
|
|
body = {
|
|
'name': name,
|
|
'size': size,
|
|
'datacenter_id': datacenter_id
|
|
}
|
|
|
|
if description is not None:
|
|
body['description'] = description
|
|
|
|
response = self.connection.request(
|
|
action='shared_storages',
|
|
data=body,
|
|
method='POST'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_delete_shared_storage(self, storage_id):
|
|
"""
|
|
Removes a shared storage
|
|
|
|
:param storage_id: Id of the shared storage
|
|
:type: ``str``
|
|
|
|
:return: Instnace of shared storage
|
|
:rtype: ``list`` of ``dict``
|
|
"""
|
|
response = self.connection.request(
|
|
action='shared_storages/%s' % storage_id,
|
|
method='DELETE'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_attach_server_to_shared_storage(self, storage_id,
|
|
server_id, rights):
|
|
"""
|
|
Attaches a single server to a shared storage
|
|
|
|
:param storage_id: Id of the shared storage
|
|
:param server_id: Id of the server to be attached to the shared storage
|
|
:param rights:
|
|
:return:
|
|
:rtype: 'dict'
|
|
"""
|
|
body = {
|
|
'severs': [
|
|
{
|
|
'id': server_id,
|
|
'rights': rights
|
|
}
|
|
]
|
|
}
|
|
|
|
response = self.connection.request(
|
|
action='shared_storages/%s/servers' % storage_id,
|
|
data=body,
|
|
method='POST'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_get_shared_storage_server(self, storage_id, server_id):
|
|
"""
|
|
Gets a shared storage's server
|
|
:param storage_id:
|
|
:param server_id:
|
|
:return:
|
|
"""
|
|
response = self.connection.request(
|
|
action='shared_storages/%s/servers/%s' % (storage_id, server_id),
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_detach_server_from_shared_storage(self, storage_id,
|
|
server_id):
|
|
"""
|
|
Detaches a server from shared storage
|
|
|
|
:param storage_id: Id of the shared storage
|
|
:type: ``str``
|
|
|
|
:param server_id: Id of the server
|
|
:type: ``str``
|
|
|
|
:return: Instance of shared storage
|
|
:rtype: ``dict``
|
|
"""
|
|
response = self.connection.request(
|
|
action='shared_storages/%s/servers/%s' % (storage_id, server_id),
|
|
method='DELETE'
|
|
)
|
|
|
|
return response.object
|
|
|
|
"""
|
|
Load Balancers operations
|
|
"""
|
|
|
|
def ex_create_load_balancer(self, name, method, rules,
|
|
persistence=None,
|
|
persistence_time=None,
|
|
health_check_test=None,
|
|
health_check_interval=None,
|
|
health_check_path=None,
|
|
health_check_parser=None,
|
|
datacenter_id=None,
|
|
description=None):
|
|
"""
|
|
|
|
:param name: Name of the load balancer
|
|
|
|
:param method: Load balancer method
|
|
|
|
:param rules: Load balancer rules
|
|
:type rules: ``list`` of ``dict``
|
|
|
|
:param persistence: Indictes if persistance is set
|
|
:type persistence: ``boolean``
|
|
|
|
:param persistence_time: Persistance time
|
|
:type persistence_time: ``int``
|
|
|
|
:param health_check_test: Type of test
|
|
:type health_check_test:``str``
|
|
|
|
:param health_check_interval: Interval of the check
|
|
|
|
:param health_check_path: Path
|
|
:type health_check_path: ``str``
|
|
|
|
:param health_check_parser: Parser
|
|
:type health_check_parser:``str``
|
|
|
|
:param datacenter_id: Data center id
|
|
:type datacenter_id:``str``
|
|
|
|
:param description: Description of load balancer
|
|
:type description:``str``
|
|
|
|
:return: ``dict``
|
|
"""
|
|
|
|
body = {
|
|
'name': name,
|
|
'method': method,
|
|
}
|
|
|
|
body['rules'] = []
|
|
body['rules'] = rules
|
|
|
|
if persistence is not None:
|
|
body['persistence'] = persistence
|
|
if persistence_time is not None:
|
|
body['persistence_time'] = persistence_time
|
|
if health_check_test is not None:
|
|
body['health_check_test'] = health_check_test
|
|
if health_check_interval is not None:
|
|
body['health_check_interval'] = health_check_interval
|
|
if health_check_path is not None:
|
|
body['health_check_path'] = health_check_path
|
|
if health_check_parser is not None:
|
|
body['health_check_parser'] = health_check_parser
|
|
if datacenter_id is not None:
|
|
body['datacenter_id'] = datacenter_id
|
|
if description is not None:
|
|
body['description'] = description
|
|
|
|
response = self.connection.request(
|
|
action='load_balancers',
|
|
data=body,
|
|
method='POST'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_update_load_balancer(self, lb_id, name=None, description=None,
|
|
health_check_test=None,
|
|
health_check_interval=None,
|
|
persistence=None,
|
|
persistence_time=None,
|
|
method=None):
|
|
body = {}
|
|
|
|
if name is not None:
|
|
body['name'] = name
|
|
if description is not None:
|
|
body['description'] = description
|
|
if health_check_test is not None:
|
|
body['health_check_test'] = health_check_test
|
|
if health_check_interval is not None:
|
|
body['health_check_interval'] = health_check_interval
|
|
if persistence is not None:
|
|
body['persistence'] = persistence
|
|
if persistence_time is not None:
|
|
body['persistence_time'] = persistence_time
|
|
if method is not None:
|
|
body['method'] = method
|
|
|
|
response = self.connection.request(
|
|
action='load_balancers/%s' % lb_id,
|
|
data=body,
|
|
method='PUT'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_add_servers_to_load_balancer(self, lb_id, server_ips=[]):
|
|
"""
|
|
Adds server's IP address to load balancer
|
|
|
|
:param lb_id: Load balancer ID
|
|
:type: ``str``
|
|
|
|
:param server_ips: Array of server IP IDs
|
|
:type: ``list`` of ``str``
|
|
|
|
:return: Instance of load balancer
|
|
:rtype: ``dict``
|
|
"""
|
|
body = {
|
|
'server_ips': server_ips,
|
|
}
|
|
|
|
response = self.connection.request(
|
|
action='load_balancers/%s/server_ips' % lb_id,
|
|
data=body,
|
|
method='POST'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_remove_server_from_load_balancer(self, lb_id, server_ip):
|
|
"""
|
|
Removes server's IP from load balancer
|
|
|
|
:param lb_id: Load balancer ID
|
|
:type: ``str``
|
|
|
|
:param server_ip: ID of the server IP
|
|
:type: ``str``
|
|
|
|
:return: Instance of load balancer
|
|
:rtype: ``dict``
|
|
"""
|
|
|
|
response = self.connection.request(
|
|
action='/load_balancers/%s/server_ips/%s' % (lb_id, server_ip),
|
|
method='DELETE'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_add_load_balancer_rule(self, lb_id, protocol, port_balancer,
|
|
port_server, source=None):
|
|
"""
|
|
Adds a rule to load balancer
|
|
|
|
:param lb_id: Load balancer ID
|
|
:rtype: ``str``
|
|
|
|
:param protocol: Load balancer protocol
|
|
:rtype: ``str``
|
|
|
|
:param port_balancer: Port to be balananced
|
|
:rtype: ``int``
|
|
|
|
:param port_server: Server port
|
|
:rtype: ``int``
|
|
|
|
:param source: Source IP address
|
|
:rtype: ``str``
|
|
|
|
:return: Instance of load balancer
|
|
:rtype: ``dict``
|
|
"""
|
|
|
|
body = {
|
|
'rules': [
|
|
{
|
|
'protocol': protocol,
|
|
'port_balancer': port_balancer,
|
|
'port_server': port_server
|
|
}
|
|
]
|
|
}
|
|
|
|
if source is not None:
|
|
body['rules'][0]['source'] = source
|
|
|
|
response = self.connection.request(
|
|
action='/load_balancers/%s/rules' % lb_id,
|
|
data=body,
|
|
method='POST'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_remove_load_balancer_rule(self, lb_id, rule_id):
|
|
"""
|
|
Removes load balancer rule
|
|
|
|
:param lb_id: Load balancer ID
|
|
:rtype: ``str``
|
|
|
|
:param rule_id: Rule ID
|
|
:rtype: ``str``
|
|
|
|
:return: Instance of load balancer
|
|
:rtype: ``dict``
|
|
"""
|
|
response = self.connection.request(
|
|
action='/load_balancers/%s/rules/%s' % (lb_id, rule_id),
|
|
method='DELETE'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_list_load_balancers(self):
|
|
"""
|
|
Lists all load balancers
|
|
|
|
:return: List of load balancers
|
|
:rtype: ``list`` of ``dict``
|
|
"""
|
|
response = self.connection.request(
|
|
action='load_balancers',
|
|
method='GET'
|
|
)
|
|
return response.object
|
|
|
|
def ex_get_load_balancer(self, lb_id):
|
|
"""
|
|
Gets a single load balancer
|
|
|
|
:param lb_id: ID of the load balancer
|
|
:type lb_id: ``str``
|
|
|
|
:return: Instance of load balancer
|
|
:rtype: ``dict``
|
|
"""
|
|
response = self.connection.request(
|
|
action='load_balancers/%s' % lb_id,
|
|
method='GET'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_list_load_balancer_server_ips(self, lb_id):
|
|
"""
|
|
List balanced server IP addresses
|
|
|
|
:param lb_id: ID of the load balancer
|
|
:type lb_id: ``str``
|
|
|
|
:return: Array of IP address IDs
|
|
:rtype: ``dict``
|
|
"""
|
|
response = self.connection.request(
|
|
action='load_balancers/%s/server_ips' % lb_id,
|
|
method='GET'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_get_load_balancer_server_ip(self, lb_id, server_ip):
|
|
"""
|
|
Gets load balanced server id
|
|
|
|
:param lb_id: ID of the load balancer
|
|
:type lb_id: ``str``
|
|
|
|
:param server_ip: ID of the server IP
|
|
:type server_ip: ``str``
|
|
|
|
:return: Server IP
|
|
:rtype: ``dict``
|
|
"""
|
|
response = self.connection.request(
|
|
action='load_balancers/%s/server_ips/%s' % (lb_id, server_ip),
|
|
method='GET'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_list_load_balancer_rules(self, lb_id):
|
|
"""
|
|
Lists loadbalancer rules
|
|
|
|
:param lb_id: ID of the load balancer
|
|
:type lb_id: ``str``
|
|
|
|
:return: Lists of rules
|
|
:rtype: ``list`` of ``dict``
|
|
"""
|
|
response = self.connection.request(
|
|
action='load_balancers/%s/rules' % lb_id,
|
|
method='GET'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_get_load_balancer_rule(self, lb_id, rule_id):
|
|
"""
|
|
Get a load balancer rule
|
|
|
|
:param lb_id: ID of the load balancer
|
|
:type lb_id: ``str``
|
|
|
|
:param rule_id: Rule ID
|
|
:type rule_id: ``str``
|
|
|
|
:return: A load balancer rule
|
|
:rtype: ``dict``
|
|
"""
|
|
response = self.connection.request(
|
|
action='load_balancers/%s/rules/%s' % (lb_id, rule_id),
|
|
method='GET'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_delete_load_balancer(self, lb_id):
|
|
"""
|
|
Deletes a load balancer rule
|
|
|
|
:param lb_id: ID of the load balancer
|
|
:type lb_id: ``str``
|
|
|
|
:param rule_id: Rule ID
|
|
:type rule_id: ``str``
|
|
|
|
:return: Instance of load balancer
|
|
:rtype: ``dict``
|
|
"""
|
|
response = self.connection.request(
|
|
action='load_balancers/%s' % lb_id,
|
|
method='DELETE'
|
|
)
|
|
|
|
return response.object
|
|
|
|
"""
|
|
Public IP operations
|
|
"""
|
|
|
|
def ex_list_public_ips(self):
|
|
"""
|
|
Lists all public IP addresses
|
|
|
|
:return: Array of public addresses
|
|
:rtype: ``list`` of ``dict``
|
|
"""
|
|
response = self.connection.request(
|
|
action='public_ips',
|
|
method='GET'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_create_public_ip(self, type, reverse_dns=None, datacenter_id=None):
|
|
"""
|
|
Creates a public IP
|
|
|
|
:param type: Type of IP (IPV4 or IPV6)
|
|
:type type: ``str``
|
|
|
|
:param reverse_dns: Reverse DNS
|
|
:type reverse_dns: ``str``
|
|
|
|
:param datacenter_id: Datacenter ID where IP address will be crated
|
|
:type datacenter_id: ``str``
|
|
|
|
:return: Instance of Public IP
|
|
:rtype: ``dict``
|
|
"""
|
|
body = {
|
|
'type': type
|
|
}
|
|
|
|
if reverse_dns is not None:
|
|
body['reverse_dns'] = reverse_dns
|
|
if datacenter_id is not None:
|
|
body['datacenter_id'] = datacenter_id
|
|
|
|
response = self.connection.request(
|
|
action='public_ips',
|
|
data=body,
|
|
method='POST'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_get_public_ip(self, ip_id):
|
|
"""
|
|
Gets a Public IP
|
|
|
|
:param ip_id: ID of the IP
|
|
:type ip_id: ``str``
|
|
|
|
:return: Instance of Public IP
|
|
:rtype: ``dict``
|
|
"""
|
|
response = self.connection.request(
|
|
action='public_ips/%s' % ip_id,
|
|
method='GET'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_delete_public_ip(self, ip_id):
|
|
"""
|
|
Deletes a public IP
|
|
|
|
:param ip_id: ID of public IP
|
|
:type ip_id: ``str``
|
|
|
|
:return: Instance of IP Address
|
|
:rtype: ``dict``
|
|
"""
|
|
response = self.connection.request(
|
|
action='public_ips/%s' % ip_id,
|
|
method='DELETE'
|
|
)
|
|
|
|
return response
|
|
|
|
def ex_update_public_ip(self, ip_id, reverse_dns):
|
|
"""
|
|
Updates a Public IP
|
|
|
|
:param ip_id: ID of public IP
|
|
:type ip_id: ``str``
|
|
|
|
:param reverse_dns: Reverse DNS
|
|
:type reverse_dns: ``str``
|
|
|
|
:return: Instance of Public IP
|
|
:rtype: ``dict``
|
|
"""
|
|
|
|
body = {
|
|
'reverse_dns': reverse_dns
|
|
}
|
|
response = self.connection.request(
|
|
action='public_ips/%s' % ip_id,
|
|
data=body,
|
|
method='DELETE'
|
|
)
|
|
|
|
return response.object
|
|
|
|
"""
|
|
Private Network Operations
|
|
"""
|
|
|
|
def ex_list_private_networks(self):
|
|
"""
|
|
Lists all private networks
|
|
|
|
:return: List of private networks
|
|
:rtype: ``dict``
|
|
"""
|
|
response = self.connection.request(
|
|
action='private_networks',
|
|
method='GET'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_create_private_network(self, name, description=None,
|
|
datacenter_id=None,
|
|
network_address=None,
|
|
subnet_mask=None):
|
|
"""
|
|
Creates a private network
|
|
|
|
:param name: Name of the private network
|
|
:type name: ``str``
|
|
|
|
:param description: Description of the private network
|
|
:type description: ``str``
|
|
|
|
:param datacenter_id: ID of the data center for the private network
|
|
:type datacenter_id: ``str``
|
|
|
|
:param network_address: Network address of the private network
|
|
:type network_address: ``str``
|
|
|
|
:param subnet_mask: Subnet mask of the private network
|
|
:type subnet_mask: ``str``
|
|
|
|
:return: Newly created private network
|
|
:rtype: ``dict``
|
|
"""
|
|
|
|
body = {
|
|
'name': name
|
|
}
|
|
|
|
if description is not None:
|
|
body['description'] = description
|
|
if datacenter_id is not None:
|
|
body['datacenter_id'] = datacenter_id
|
|
if network_address is not None:
|
|
body['network_address'] = network_address
|
|
if subnet_mask is not None:
|
|
body['subnet_maks'] = subnet_mask
|
|
|
|
response = self.connection.request(
|
|
action='private_networks',
|
|
data=body,
|
|
method='POST'
|
|
)
|
|
return response.object
|
|
|
|
def ex_delete_private_network(self, network_id):
|
|
"""
|
|
Deletes a private network
|
|
|
|
:param network_id: Id of the private network
|
|
:type network_id: ``str``
|
|
|
|
:return: Instance of the private network being deleted
|
|
:rtype: ``dict``
|
|
"""
|
|
response = self.connection.request(
|
|
action='private_networks' % network_id,
|
|
method='DELETE'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_update_private_network(self, network_id,
|
|
name=None, description=None,
|
|
datacenter_id=None,
|
|
network_address=None,
|
|
subnet_mask=None):
|
|
"""
|
|
Updates a private network
|
|
|
|
:param name: Name of the private network
|
|
:type name: ``str``
|
|
|
|
:param description: Description of the private network
|
|
:type description: ``str``
|
|
|
|
:param datacenter_id: ID of the data center for the private network
|
|
:type datacenter_id: ``str``
|
|
|
|
:param network_address: Network address of the private network
|
|
:type network_address: ``str``
|
|
|
|
:param subnet_mask: Subnet mask of the private network
|
|
:type subnet_mask: ``str``
|
|
|
|
:return: Instance of private network
|
|
:rtype: ``dict``
|
|
"""
|
|
body = {}
|
|
|
|
if name is not None:
|
|
body['name'] = name
|
|
if description is not None:
|
|
body['description'] = description
|
|
if datacenter_id is not None:
|
|
body['datacenter_id'] = datacenter_id
|
|
if network_address is not None:
|
|
body['network_address'] = network_address
|
|
if subnet_mask is not None:
|
|
body['subnet_maks'] = subnet_mask
|
|
|
|
response = self.connection.request(
|
|
action='private_networks/%s',
|
|
data=body,
|
|
method='PUT'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_list_private_network_servers(self, network_id):
|
|
"""
|
|
Lists all private network servers
|
|
|
|
:param network_id: Private network ID
|
|
:type network_id: ``str``
|
|
|
|
:return: List of private network servers
|
|
:rtype: ``dict``
|
|
"""
|
|
response = self.connection.request(
|
|
action='/private_networks/%s/servers' % network_id,
|
|
method='GET'
|
|
)
|
|
return response.object
|
|
|
|
def ex_add_private_network_server(self, network_id, server_ids):
|
|
"""
|
|
Add servers to private network
|
|
|
|
:param network_id: Private Network ID
|
|
:type network_id: ``str``
|
|
|
|
:param server_ids: List of server IDs
|
|
:type server_ids: ``list`` of ``str``
|
|
|
|
:return: List of attached servers
|
|
:rtype: ``dict``
|
|
|
|
"""
|
|
body = {
|
|
'servers': server_ids
|
|
|
|
}
|
|
|
|
response = self.connection.request(
|
|
action='/private_networks/%s/servers' % network_id,
|
|
data=body,
|
|
method='POST'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_remove_server_from_private_network(self, network_id, server_id):
|
|
"""
|
|
Removes a server from the private network
|
|
|
|
:param network_id: Private Network ID
|
|
:type network_id: ``str``
|
|
|
|
:param server_id: Id of the server
|
|
:type server_id: ``str``
|
|
|
|
:return: Instance of the private network
|
|
:rtype: ``dict``
|
|
"""
|
|
|
|
response = self.connection.request(
|
|
action='/private_networks/%s/servers/%s' % (network_id, server_id),
|
|
method='POST'
|
|
)
|
|
return response.object
|
|
|
|
"""
|
|
Monitoring policy operations
|
|
"""
|
|
|
|
def ex_list_monitoring_policies(self):
|
|
"""
|
|
Lists all monitoring policies
|
|
|
|
:return: List of monitoring policies
|
|
:rtype: ``dict``
|
|
"""
|
|
response = self.connection.request(
|
|
action='monitoring_policies',
|
|
method='GET'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_create_monitoring_policy(self, name, thresholds,
|
|
ports,
|
|
processes,
|
|
description=None,
|
|
email=None,
|
|
agent=None,
|
|
):
|
|
"""
|
|
Creates a monitoring policy
|
|
|
|
:param name: Name for the monitoring policy
|
|
:type name: ``str``
|
|
|
|
:param thresholds: Thresholds for the monitoring policy
|
|
:type thresholds: ``dict``
|
|
|
|
:param ports: Monitoring policies for ports
|
|
:type ports: ``list`` of ``dict``
|
|
|
|
:param processes: Processes to be monitored
|
|
:type processes: ``list`` of ``dict``
|
|
|
|
:param description: Description for the monitoring policy
|
|
:type description: ``str``
|
|
|
|
:param email: Email for notifications
|
|
:type email: ``str``
|
|
|
|
:param agent: Indicates if agent application will be installed
|
|
:type agent: ``boolean``
|
|
|
|
:return: Newly created instance of monitofing policy
|
|
:rtype: ``dict``
|
|
"""
|
|
body = {
|
|
'name': name,
|
|
'thresholds': thresholds,
|
|
'ports': ports,
|
|
'processes': processes
|
|
}
|
|
|
|
if description is not None:
|
|
body['description'] = description
|
|
if email is not None:
|
|
body['email'] = email
|
|
if agent is not None:
|
|
body['agent'] = agent
|
|
|
|
response = self.connection.request(
|
|
action='monitoring_policies',
|
|
data=body,
|
|
method='POST'
|
|
)
|
|
return response.object
|
|
|
|
def ex_delete_monitoring_policy(self, policy_id):
|
|
"""
|
|
Deletes a monitoring policy
|
|
|
|
:param policy_id: Id of the monitoring policy
|
|
:type policy_id: ``str``
|
|
|
|
:return: Instance of the monitoring policy being deleted
|
|
:rtype: ``dict``
|
|
"""
|
|
response = self.connection.request(
|
|
action='monitoring_policies' % policy_id,
|
|
method='DELETE'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_update_monitoring_policy(self, policy_id,
|
|
email,
|
|
thresholds,
|
|
name=None, description=None):
|
|
"""
|
|
Updates monitoring policy
|
|
|
|
:param policy_id: Id of the monitoring policy
|
|
:type policy_id: ``str``
|
|
|
|
:param email: Email to send notifications to
|
|
:type email: ``str``
|
|
|
|
:param thresholds: Thresholds for the monitoring policy
|
|
:type thresholds: ``dict``
|
|
|
|
:param name: Name of the monitoring policy
|
|
:type name: ``str``
|
|
|
|
:param description: Description of the monitoring policy
|
|
:type description: ``str``
|
|
|
|
:return: Instance of the monitoring policy being deleted
|
|
:rtype: ``dict``
|
|
"""
|
|
|
|
body = {}
|
|
|
|
if name is not None:
|
|
body['name'] = name
|
|
if description is not None:
|
|
body['description'] = description
|
|
if thresholds is not None:
|
|
body['thresholds'] = thresholds
|
|
if email is not None:
|
|
body['email'] = email
|
|
|
|
response = self.connection.request(
|
|
action='monitoring_policies/%s' % policy_id,
|
|
data=body,
|
|
method='PUT'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_get_monitoring_policy(self, policy_id):
|
|
"""
|
|
Fetches a monitoring policy
|
|
|
|
:param policy_id: Id of the monitoring policy
|
|
:type policy_id: ``str``
|
|
|
|
:return: Instance of a monitoring policy
|
|
:rtype: ``dict``
|
|
"""
|
|
response = self.connection.request(
|
|
action='monitoring_policies/%s' % policy_id,
|
|
method='GET'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_get_monitoring_policy_ports(self, policy_id):
|
|
"""
|
|
Fetches monitoring policy ports
|
|
|
|
:param policy_id: Id of the monitoring policy
|
|
:type policy_id:
|
|
|
|
:return: Instance of a monitoring policy
|
|
:rtype: ``dict``
|
|
"""
|
|
|
|
response = self.connection.request(
|
|
action='monitoring_policies/%s/ports' % policy_id,
|
|
method='GET'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_get_monitoring_policy_port(self, policy_id, port_id):
|
|
"""
|
|
Fetches monitoring policy port
|
|
|
|
:param policy_id: Id of the monitoring policy
|
|
:type policy_id: ``str``
|
|
|
|
:param port_id: Id of the port
|
|
:type port_id: ``str``
|
|
|
|
:return: Instance of a monitoring policy
|
|
:rtype: ``dict``
|
|
"""
|
|
|
|
response = self.connection.request(
|
|
action='monitoring_policies/%s/ports/%s' % (policy_id, port_id),
|
|
method='GET'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_remove_monitoring_policy_port(self, policy_id, port_id):
|
|
"""
|
|
Removes monitoring policy port
|
|
|
|
:param policy_id: Id of the monitoring policy
|
|
:type policy_id: ``str``
|
|
|
|
:param port_id: Id of the port
|
|
:type port_id: ``str``
|
|
|
|
:return: Instance of a monitoring policy
|
|
:rtype: ``dict``
|
|
"""
|
|
|
|
response = self.connection.request(
|
|
action='monitoring_policies/%s/ports/%s' % (policy_id, port_id),
|
|
method='DELETE'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_add_monitoring_policy_ports(self, policy_id, ports):
|
|
"""
|
|
Add monitoring policy ports
|
|
|
|
:param policy_id: Id of the monitoring policy
|
|
:type policy_id: ``str``
|
|
|
|
:param ports: List of ports
|
|
:type ports: ``dict``
|
|
[
|
|
{
|
|
'protocol':'TCP',
|
|
'port':'80',
|
|
'alert_if':'RESPONDING',
|
|
'email_notification':true
|
|
}
|
|
]
|
|
|
|
:return: Instance of a monitoring policy
|
|
:rtype: ``dict``
|
|
"""
|
|
|
|
body = {'ports': ports}
|
|
|
|
response = self.connection.request(
|
|
action='monitoring_policies/%s/ports' % policy_id,
|
|
data=body,
|
|
method='POST'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_get_monitoring_policy_processes(self, policy_id):
|
|
"""
|
|
Fetches monitoring policy processes
|
|
|
|
:param policy_id: Id of the monitoring policy
|
|
:type policy_id: ``str``
|
|
|
|
:return: Instance of a monitoring policy
|
|
:rtype: ``dict``
|
|
"""
|
|
|
|
response = self.connection.request(
|
|
action='monitoring_policies/%s/processes' % policy_id,
|
|
method='GET'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_get_monitoring_policy_process(self, policy_id, process_id):
|
|
"""
|
|
Fetches monitoring policy process
|
|
|
|
:param policy_id: Id of the monitoring policy
|
|
:type policy_id: ``str``
|
|
|
|
:param process_id: Id of the process
|
|
:type process_id: ``str``
|
|
|
|
:return: Instance of a monitoring policy
|
|
:rtype: ``dict``
|
|
"""
|
|
|
|
response = self.connection.request(
|
|
action='monitoring_policies/%s/processes/%s'
|
|
% (policy_id, process_id),
|
|
method='GET'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_remove_monitoring_policy_process(self, policy_id, process_id):
|
|
"""
|
|
Removes monitoring policy process
|
|
|
|
:param policy_id: Id of the monitoring policy
|
|
:type policy_id: ``str``
|
|
|
|
:param process_id: Id of the process
|
|
:type process_id: ``str``
|
|
|
|
:return: Instance of a monitoring policy
|
|
:rtype: ``dict``
|
|
"""
|
|
|
|
response = self.connection.request(
|
|
action='monitoring_policies/%s/processes/%s'
|
|
% (policy_id, process_id),
|
|
method='DELETE'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_add_monitoring_policy_processes(self, policy_id, processes):
|
|
"""
|
|
Add monitoring policy processes
|
|
|
|
:param policy_id: Id of the monitoring policy
|
|
:type policy_id: ``str``
|
|
|
|
:param processes: List of processes
|
|
:type processes: ``list`` of ``dict``
|
|
[
|
|
{
|
|
'process': 'taskmmgr',
|
|
'alert_if': 'RUNNING',
|
|
'email_notification': true
|
|
}
|
|
]
|
|
|
|
:return: Instance of a monitoring policy
|
|
:rtype: ``dict``
|
|
"""
|
|
|
|
body = {'processes': processes}
|
|
|
|
response = self.connection.request(
|
|
action='monitoring_policies/%s/processes' % policy_id,
|
|
data=body,
|
|
method='POST'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_list_monitoring_policy_servers(self, policy_id):
|
|
"""
|
|
List all servers that are being monitoried by the policy
|
|
|
|
:param policy_id: Id of the monitoring policy
|
|
:type policy_id: ``str``
|
|
|
|
:return: List of servers being monitored
|
|
:rtype: ``list`` of ``dict``
|
|
"""
|
|
|
|
response = self.connection.request(
|
|
action='monitoring_policies/%s/servers' % policy_id,
|
|
method='GET'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_add_servers_to_monitoring_policy(self, policy_id, servers):
|
|
"""
|
|
Adds servers to monitoring policy
|
|
|
|
:param policy_id: Id of the monitoring policy
|
|
:type policy_id: ``str``
|
|
|
|
:param servers: List of server ID
|
|
:type servers: ``list`` of ``str``
|
|
|
|
:return: Instance of a monitoring policy
|
|
:rtype: ``dict``
|
|
"""
|
|
body = {
|
|
'servers': servers
|
|
}
|
|
response = self.connection.request(
|
|
action='monitoring_policies/%s/servers' % policy_id,
|
|
data=body,
|
|
method='POST'
|
|
)
|
|
|
|
return response.object
|
|
|
|
def ex_remove_server_from_monitoring_policy(self, policy_id, server_id):
|
|
"""
|
|
Removes a server from monitoring policy
|
|
|
|
:param policy_id: Id of the monitoring policy
|
|
:type policy_id: ``str``
|
|
|
|
:param server_id: Id of the server
|
|
:type server_id: ``str``
|
|
|
|
:return: Instance of a monitoring policy
|
|
:rtype: ``dict``
|
|
"""
|
|
response = self.connection.request(
|
|
action='monitoring_policies/%s/servers/%s'
|
|
% (policy_id, server_id),
|
|
method='DELETE'
|
|
)
|
|
|
|
return response.object
|
|
|
|
"""
|
|
Private Functions
|
|
"""
|
|
|
|
def _to_images(self, object, image_type=None):
|
|
if image_type is not None:
|
|
images = [image for image in object if image['type'] == image_type]
|
|
else:
|
|
images = [image for image in object]
|
|
|
|
return [self._to_image(image) for image in images]
|
|
|
|
def _to_image(self, data):
|
|
extra = {
|
|
'os_family': data['os_family'],
|
|
'os': data['os'],
|
|
'os_version': data['os_version'],
|
|
'os_architecture': data['os_architecture'],
|
|
'os_image_type': data['os_image_type'],
|
|
'min_hdd_size': data['min_hdd_size'],
|
|
'available_datacenters': data['available_datacenters'],
|
|
'licenses': data['licenses'],
|
|
'version': data['version'],
|
|
'categories': data['categories']
|
|
}
|
|
return NodeImage(id=data['id'], name=data['name'], driver=self,
|
|
extra=extra)
|
|
|
|
def _to_node_size(self, data):
|
|
return NodeSize(
|
|
id=data['id'],
|
|
name=data['name'],
|
|
ram=data['hardware']['ram'],
|
|
disk=data['hardware']['hdds'][0]['size'],
|
|
bandwidth=None,
|
|
price=None,
|
|
driver=self.connection.driver,
|
|
extra={
|
|
'vcores': data['hardware']['vcore'],
|
|
'cores_per_processor': data['hardware']['cores_per_processor']}
|
|
|
|
)
|
|
|
|
def _to_location(self, location):
|
|
return NodeLocation(
|
|
id=location['id'],
|
|
name=location['country_code'],
|
|
country=location['location'],
|
|
driver=self.connection.driver
|
|
)
|
|
|
|
def _to_nodes(self, servers):
|
|
return [self._to_node(
|
|
server) for server in servers]
|
|
|
|
def _to_node(self, server):
|
|
extra = {}
|
|
extra['datacenter'] = server['datacenter']
|
|
|
|
if 'description' in server:
|
|
extra['description'] = server['description']
|
|
if 'status' in server:
|
|
extra['status'] = server['status']
|
|
if 'image' in server:
|
|
extra['image'] = server['image']
|
|
if 'hardware' in server:
|
|
extra['hardware'] = server['hardware']
|
|
if 'dvd' in server:
|
|
extra['dvd'] = server['dvd']
|
|
if 'snapshot' in server:
|
|
extra['snapshot'] = server['snapshot']
|
|
if 'ips' in server:
|
|
extra['ips'] = server['ips']
|
|
if 'alerts' in server:
|
|
extra['alerts'] = server['alerts']
|
|
if 'monitoring_policy' in server:
|
|
extra['monitoring_policy'] = server['monitoring_policy']
|
|
if 'private_networks' in server:
|
|
extra['private_networks'] = server['private_networks']
|
|
|
|
ips = []
|
|
|
|
if server['ips'] is not None:
|
|
for ip in server['ips']:
|
|
ips.append(ip['ip'])
|
|
state = self.NODE_STATE_MAP.get(
|
|
server['status']['state'])
|
|
|
|
return Node(
|
|
id=server['id'],
|
|
state=state,
|
|
name=server['name'],
|
|
driver=self.connection.driver,
|
|
public_ips=ips,
|
|
private_ips=None,
|
|
extra=extra
|
|
)
|
|
|
|
def _wait_for_state(self, server_id, state, retries=50):
|
|
for i in (0, retries):
|
|
server = self.ex_get_server(server_id)
|
|
|
|
if server.extra['status']['state'] == state:
|
|
return
|
|
sleep(5)
|
|
|
|
if i == retries:
|
|
raise Exception('Retries count reached')
|
|
|
|
def _list_fixed_instances(self):
|
|
response = self.connection.request(
|
|
action='/servers/fixed_instance_sizes',
|
|
method='GET'
|
|
)
|
|
|
|
return response.object
|