diff --git a/README.md b/README.md index 183b6b0..4cbe569 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,24 @@ import json master = cherry.Master(auth_token="api_token") -plans = master.get_plans("28519") +plans = master.get_plans(team_id="28519") + +for plan in plans: + p = json.dumps(plan) + parse_p = json.loads(p) + print("Plan id: %s -> Plan name: %s -> Av: %s" % (parse_p['id'], + parse_p['name'], + parse_p['available_regions'])) +``` + +#### Get only bare metal plans +``` +import cherry +import json + +master = cherry.Master(auth_token="api_token") + +plans = master.get_plans(team_id="28519", **{'type[]':'baremetal'}) for plan in plans: p = json.dumps(plan) @@ -51,7 +68,7 @@ import json master = cherry.Master(auth_token="api_token") -images = master.get_images("161") +images = master.get_images(plan_id="161") for image in images: i = json.dumps(image) @@ -68,7 +85,7 @@ import json master = cherry.Master(auth_token="api_token") -projects = master.get_projects("28519") +projects = master.get_projects(team_id="28519") for project in projects: p = json.dumps(project) @@ -98,7 +115,7 @@ import json master = cherry.Master(auth_token="api_token") -servers = master.get_servers("79813") +servers = master.get_servers(project_id="79813") for server in servers: sr = json.dumps(server) @@ -107,14 +124,26 @@ for server in servers: print("Server ID: %s -> IP: %s" % (parse_sr['id'], parse_sr['ip_addresses'])) ``` -### Get specific server info +#### Get server info +``` +import cherry +import json + +master = cherry.Master(auth_token="api_token") + +server = master.get_server(server_id="165903") + +print(server) +``` + +#### Get specific server info ``` import cherry import json master = cherry.Master(auth_token="api_token") -server = master.get_server("165903") +server = master.get_server(server_id="165903", fields="power,state,termination_date") print(server) ``` @@ -133,7 +162,7 @@ server = master.create_server(project_id="79813", name="super-duper", hostname="bla.com", image="Ubuntu 16.04 64bit", - region="EU-East-1", + region="EU-Nord-1", ip_addresses=ips, ssh_keys=ssh_keys, plan_id="161") @@ -141,13 +170,119 @@ server = master.create_server(project_id="79813", print("Server: %s" % server) ``` +#### Order first available server from spot market +``` +import cherry +import json + +master = cherry.Master(auth_token="api_token") +plans = master.get_plans(team_id="28519", fields="id,name,available_regions,region") + +for plan in plans: + for region in plan['available_regions']: + if region['spot_qty'] > 0: + server = master.create_server(project_id="79813", + region=region['name'], + plan_id=plan['id'], + spot_market="1") + print("%s server (ID %s) deployment has just been started from spot market" % (plan['name'], server['id'])) + exit() +print("No available servers in spot market") +``` + #### Terminate server ``` import cherry import json master = cherry.Master(auth_token="api_token") +server = master.terminate_server(server_id="165760") -server = master.terminate_server("165760") print("Delete server: %s" % server) +``` + +#### Order IP subnet +``` +import cherry +import json + +master = cherry.Master(auth_token="api_token") +subnet = master.create_ip_subnet(project_id="46776", + quantity="8", + region="EU-Nord-1") +print("Subnet: %s" % subnet) +``` + +#### Assign subnet IP addresses to a server +``` +import cherry +import json + +master = cherry.Master(auth_token="api_token") +subnet = master.get_ip_subnet(project_id=46776, subnet_id="377432", fields="subnet,id") +server_id = "377441" + +for subnet_ip in subnet["addresses"]: + master.update_ip_address(project_id=46776, ip_address_id=subnet_ip["id"], assigned_to=server_id) + + print("Subnet IP %s assigned to a server %s" % (subnet_ip, server_id)) +``` + +#### Remove subnet IP addresses from a server +``` +import cherry +import json + +master = cherry.Master(auth_token="api_token") +subnet = master.get_ip_subnet(project_id=46776, subnet_id="377432", fields="subnet,id,assigned_to") + +for subnet_ip in subnet["addresses"]: + if subnet_ip["assigned_to"]: + master.update_ip_address(project_id=46776, ip_address_id=subnet_ip["id"], assigned_to="") + print("Subnet IP %s removed from a server %s" % (subnet_ip["id"], subnet_ip["assigned_to"]["id"])) +``` + +#### Order storage volume +``` +import cherry +import json + +master = cherry.Master(auth_token="api_token") +size_in_gb = 100 +storage = master.create_storage_volume(project_id=46776, region="EU-Nord-1", size=size_in_gb) + +print("Storage: %s" % storage) +``` + +#### Attach storage volume to a server +``` +import cherry +import json + +master = cherry.Master(auth_token="api_token") +storage = master.attach_storage_volume(project_id=46776, storage_id=377447, server_id="377441") + +print("Storage attached to: %s" % storage["attached_to"]["href"]) +``` + +#### Detach storage volume from a server +``` +import cherry +import json + +master = cherry.Master(auth_token="api_token") +storage = master.detach_storage_volume(project_id=46776, storage_id=377447) + +print("Storage detached") +``` +#### Increase storage volume size +``` +import cherry +import json + +master = cherry.Master(auth_token="api_token") +size_in_gb = 200 +storage = master.update_storage_volume(project_id=46776, storage_id=377457, size=size_in_gb) + +print("Storage size upgraded") ``` \ No newline at end of file diff --git a/cherry/Master.py b/cherry/Master.py index c1ca253..6a770c2 100644 --- a/cherry/Master.py +++ b/cherry/Master.py @@ -17,221 +17,296 @@ def call_api(self, method, type='GET', args=None): ''' Cia nustatom pagal nutylejima tipus ''' return super(Master, self).call_api(method, type, args) - def get_teams(self, args={}): - - """ Get teams ID for further requests """ - - cmd = self.call_api('v1/teams', args=args) - return cmd - - def get_plans(self, team_id): + def get_teams(self, **kwargs): + """ Get teams ID for further requests + Link: https://api.cherryservers.com/doc/#operation/get-teams + """ - """ Get available plans for specified team """ + args = self.update_args(kwargs, {}) + return self.call_api('v1/teams', args=args) - plans = self.call_api('v1/teams/%s/plans' % team_id) - return plans + def get_plans(self, team_id, **kwargs): + """ Get available plans for specified team + Link: https://api.cherryservers.com/doc/#operation/get-team-plans + """ - def get_images(self, plan_id): + args = self.update_args(kwargs, {}) + return self.call_api('v1/teams/%s/plans' % team_id, args=args) - """ List supported distributions for specified plan """ + def get_images(self, plan_id, **kwargs): + """ List supported distributions for specified plan + Link: https://api.cherryservers.com/doc/#operation/get-plan-images + """ - images = self.call_api('v1/plans/%s/images' % plan_id) - return images + args = self.update_args(kwargs, {}) + return self.call_api('v1/plans/%s/images' % plan_id, args=args) - def get_projects(self, team_id): - - """ Get projects for team """ - - projects = self.call_api('v1/teams/%s/projects' % team_id) - return projects + def get_projects(self, team_id, **kwargs): + """ Get projects for team + Link: https://api.cherryservers.com/doc/#operation/get-team-projects + """ - def get_servers(self, project_id): + args = self.update_args(kwargs, {}) + return self.call_api('v1/teams/%s/projects' % team_id, args=args) - """ Get servers for project """ + def get_servers(self, project_id, **kwargs): + """ Get servers for project + Link: https://api.cherryservers.com/doc/#operation/get-project-servers + """ - servers = self.call_api('v1/projects/%s/servers' % project_id) - return servers + args = self.update_args(kwargs, {}) + return self.call_api('v1/projects/%s/servers' % project_id, args=args) - def get_server(self, server_id): - - """ Get single server info """ - - server = self.call_api('v1/servers/%s' % server_id) - return server + def get_server(self, server_id, **kwargs): + """ Get single server info + Link: https://api.cherryservers.com/doc/#operation/get-server + """ - def create_server(self, - project_id, - hostname, - image, - region, - ip_addresses, - ssh_keys, - plan_id): + args = self.update_args(kwargs, {}) + return self.call_api('v1/servers/%s' % server_id, args=args) - """ Create server in specified project """ + def create_server(self, project_id, region, plan_id, **kwargs): + """ Create server in specified project + Link: https://api.cherryservers.com/doc/#operation/deploy-server + """ - args = { - "project_id" : project_id, - "hostname" : hostname, - "image" : image, - "region" : region, - "ip_addresses" : ip_addresses, - "ssh_keys" : ssh_keys, - "plan_id" : plan_id - } + args = self.update_args(kwargs, { + "project_id": project_id, + "region": region, + "plan_id": plan_id + }) - server = self.call_api('v1/projects/%s/servers' + return self.call_api('v1/projects/%s/servers' % project_id, type='POST', args=args) - return server def terminate_server(self, server_id): + """ Terminated server by ID + Link: https://api.cherryservers.com/doc/#operation/terminate-server + """ - """ Terminated server by ID """ - - server = self.call_api('v1/servers/%s' % server_id, type='DELETE') - return server + return self.call_api('v1/servers/%s' % server_id, type='DELETE') def reboot_server(self, server_id): - - """ Reboot server by ID """ + """ Reboot server by ID + Link: https://api.cherryservers.com/doc/#operation/perform-server-action + """ args = { - "type" : "reboot" + "type": "reboot" } - server = self.call_api('v1/servers/%s/actions' + return self.call_api('v1/servers/%s/actions' % server_id, type='POST', args=args) - return server def poweron_server(self, server_id): - - """ Power on server by ID """ + """ Power on server by ID + Link: https://api.cherryservers.com/doc/#operation/perform-server-action + """ args = { - "type" : "power_on" + "type": "power_on" } - server = self.call_api('v1/servers/%s/actions' + return self.call_api('v1/servers/%s/actions' % server_id, type='POST', args=args) - return server def poweroff_server(self, server_id): - - """ Power off server by ID """ + """ Power off server by ID + Link: https://api.cherryservers.com/doc/#operation/perform-server-action + """ args = { - "type" : "power_off" + "type": "power_off" } - server = self.call_api('v1/servers/%s/actions' + return self.call_api('v1/servers/%s/actions' % server_id, type='POST', args=args) - return server - - def get_ssh_keys(self): - """ List SSH keys """ + def get_ssh_keys(self, **kwargs): + """ List SSH keys + Link: https://api.stage.cherryservers.com/doc/#operation/get-ssh-keys + """ - ssh_keys = self.call_api('v1/ssh-keys') - return ssh_keys + args = self.update_args(kwargs, {}) + return self.call_api('v1/ssh-keys', args=args) def create_ssh_key(self, label, ssh_key): - - """ Adds new ssh key """ + """ Adds new ssh key + Link: https://api.cherryservers.com/doc/#operation/create-ssh-key + """ args = { - "label" : label, - "key" : ssh_key + "label": label, + "key": ssh_key } - key = self.call_api('v1/ssh-keys', type='POST', args=args) - return key + return self.call_api('v1/ssh-keys', type='POST', args=args) - def update_ssh_keys(self, ssh_key_id, label, ssh_key): + def update_ssh_keys(self, ssh_key_id, **kwargs): + """ Updates ssh key + Link: https://api.cherryservers.com/doc/#operation/update-ssh-key + """ - """ Updates ssh key """ + args = self.update_args(kwargs, {}) - args = { - "label" : label, - "key" : ssh_key - } - - key = self.call_api('v1/ssh-keys/%s' + return self.call_api('v1/ssh-keys/%s' % ssh_key_id, type='PUT', args=args) - return key def delete_ssh_key(self, ssh_key_id): + """ Removes ssh key + Link: https://api.cherryservers.com/doc/#operation/delete-ssh-key + """ - """ Removes ssh key """ + return self.call_api('v1/ssh-keys/%s' % ssh_key_id, type='DELETE') - key = self.call_api('v1/ssh-keys/%s' % ssh_key_id, type='DELETE') - return key + def get_ip_addresses(self, project_id, **kwargs): + """ Get all project`s ips available + Link: https://api.cherryservers.com/doc/#operation/get-ip-addresses + """ - def get_ip_addresses(self, project_id): + args = self.update_args(kwargs, {}) + return self.call_api('v1/projects/%s/ips' % project_id, args=args) - """ Get all project`s ips available """ + def get_ip_address(self, project_id, ip_address_id, **kwargs): + """ Get specific IP + Link: https://api.cherryservers.com/doc/#operation/get-ip-address + """ - ips = self.call_api('v1/projects/%s/ips' % project_id) - return ips + args = self.update_args(kwargs, {}) + return self.call_api('v1/projects/%s/ips/%s' + % (project_id, ip_address_id), args=args) - def get_ip_address(self, project_id, ip_address_id): + def create_ip_address(self, project_id, region, **kwargs): + """ Orders additional ip address + Link: https://api.stage.cherryservers.com/doc/#operation/request-ip-address + """ - """ Get specific IP """ + args = self.update_args(kwargs, { + "region": region + }) - ip = self.call_api('v1/projects/%s/ips/%s' - % (project_id, ip_address_id)) - return ip + return self.call_api('v1/projects/%s/ips' + % project_id, type='POST', args=args) - def create_ip_address(self, - project_id, - ip_type, - region, - ptr_record, - a_record, - routed_to, - assigned_to): + def update_ip_address(self, project_id, ip_address_id, **kwargs): + """ Update IP address info + Link: https://api.stage.cherryservers.com/doc/#operation/update-ip-address + """ - """ Orders additional ip address """ + args = self.update_args(kwargs, {}) + return self.call_api('v1/projects/%s/ips/%s' + % (project_id, ip_address_id), type='PUT', args=args) - args = { - "type" : ip_type, - "region" : region, - "ptr_record" : ptr_record, - "a_record" : a_record, - "routed_to" : routed_to, - "assigned_to" : assigned_to - } + def remove_ip_address(self, project_id, ip_address_id): + """ Removes IP address + Link: https://api.stage.cherryservers.com/doc/#operation/delete-ip-address + """ + + return self.call_api('v1/projects/%s/ips/%s' + % (project_id, ip_address_id), type='DELETE') + + def get_ip_subnets(self, project_id, **kwargs): + """ Get all project`s subnets + Link: https://api.cherryservers.com/doc/#operation/get-project-subnets + """ - ip = self.call_api('v1/projects/%s/ips' + args = self.update_args(kwargs, {}) + return self.call_api('v1/projects/%s/subnets' % project_id, args=args) + + def get_ip_subnet(self, project_id, subnet_id, **kwargs): + """ Get specific IP subnet + Link: https://api.cherryservers.com/doc/#operation/get-subnet + """ + + args = self.update_args(kwargs, {}) + return self.call_api('v1/projects/%s/subnets/%s' + % (project_id, subnet_id), args=args) + + def create_ip_subnet(self, project_id, region, quantity, **kwargs): + """ Orders additional IP subnet + Link: https://api.cherryservers.com/doc/#operation/request-subnet + """ + + args = self.update_args(kwargs, { + "region": region, + "quantity": quantity + }) + + return self.call_api('v1/projects/%s/subnets' % project_id, type='POST', args=args) - return ip - def update_ip_address(self, - project_id, - ip_address_id, - ptr_record, - a_record, - routed_to, - assigned_to): + def remove_ip_subnet(self, project_id, subnet_id): + """ Removes IP subnet + Link: https://api.cherryservers.com/doc/#operation/delete-subnet + """ - """ Update IP address info """ + return self.call_api('v1/projects/%s/subnets/%s' + % (project_id, subnet_id), type='DELETE') - args = { - "ptr_record" : ptr_record, - "a_record" : a_record, - "routed_to" : routed_to, - "assigned_to" : assigned_to - } + def get_storage_volumes(self, project_id, **kwargs): + """ Get all project`s storage volumes + Link: https://api.cherryservers.com/doc/#operation/get-project-storages + """ - ip = self.call_api('v1/projects/%s/ips/%s' - % (project_id, ip_address_id), type='PUT', args=args) - return ip + args = self.update_args(kwargs, {}) + return self.call_api('v1/projects/%s/storages' % project_id, args=args) - def remove_ip_address(self, project_id, ip_address_id): + def get_storage_volume(self, project_id, storage_id, **kwargs): + """ Get specific storage volume + Link: https://api.cherryservers.com/doc/#operation/get-storage + """ + args = self.update_args(kwargs, {}) + return self.call_api('v1/projects/%s/storages/%s' + % (project_id, storage_id), args=args) + + def create_storage_volume(self, project_id, region, size, **kwargs): + """ Orders storage volume + Link: https://api.cherryservers.com/doc/#operation/request-storage """ - Removes IP address + + args = self.update_args(kwargs, { + "region": region, + "size": size + }) + + return self.call_api('v1/projects/%s/storages' + % project_id, type='POST', args=args) + + def update_storage_volume(self, project_id, storage_id, **kwargs): + """ Update storage volume + Link: https://api.cherryservers.com/doc/#operation/resize-storage """ - ip = self.call_api('v1/projects/%s/ips/%s' - % (project_id, ip_address_id), type='DELETE') - return ip \ No newline at end of file + args = self.update_args(kwargs, {}) + return self.call_api('v1/projects/%s/storages/%s' + % (project_id, storage_id), type='PUT', args=args) + + def attach_storage_volume(self, project_id, storage_id, server_id, **kwargs): + """ Attach storage volume to an existing server + Link: https://api.cherryservers.com/doc/#operation/attach-storage + """ + + args = self.update_args(kwargs, { + "attach_to": server_id + }) + + return self.call_api('v1/projects/%s/storages/%s/attachments' + % (project_id, storage_id), type='POST', args=args) + + def detach_storage_volume(self, project_id, storage_id, **kwargs): + """ Detach storage volume from a server + Link: https://api.cherryservers.com/doc/#operation/deatach-storage + """ + + args = self.update_args(kwargs, {}) + return self.call_api('v1/projects/%s/storages/%s/attachments' + % (project_id, storage_id), type='DELETE', args=args) + + def remove_storage_volume(self, project_id, storage_id): + """ Removes storage volume from project + Link: https://api.cherryservers.com/doc/#operation/delete-storage + """ + + return self.call_api('v1/projects/%s/storages/%s' + % (project_id, storage_id), type='DELETE') diff --git a/cherry/api.py b/cherry/api.py index eda8969..30a1567 100644 --- a/cherry/api.py +++ b/cherry/api.py @@ -25,6 +25,7 @@ def call_api(self, method, type='GET', args=None): } if type == 'GET': + api_url += self._parse_params(args) resp = requests.get(api_url, headers=headers) elif type == 'POST': resp = requests.post(api_url, headers=headers, data=json.dumps(args)) @@ -47,7 +48,18 @@ def call_api(self, method, type='GET', args=None): if resp.status_code != 404 and resp.status_code != 400: resp.raise_for_status() except requests.HTTPError as e: - raise Exception("Error detected: %s Details: %s More details: %s" + raise Exception("Error detected: %s Details: %s More details: %s" % (e, data, json.dumps(args))) return data + + def update_args(self, args, updates): + args = args.copy() if isinstance(args, dict) else json.dumps(args) + args.update(updates) + return args + + def _parse_params(self, params): + vals = list() + for k, v in params.items(): + vals.append(str("%s=%s" % (k, v))) + return "?" + "&".join(vals) \ No newline at end of file diff --git a/setup.py b/setup.py index b1df2d4..26bbca8 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ long_description = readme.read() setup(name='cherry-python', - version='0.1.4', + version='0.2', description='Cherry Servers API client', long_description=long_description, long_description_content_type='text/markdown',