root / kamaki / clients / cyclades.py @ c270fe96
History | View | Annotate | Download (7.3 kB)
1 | a1c50326 | Giorgos Verigakis | # Copyright 2011 GRNET S.A. All rights reserved.
|
---|---|---|---|
2 | a1c50326 | Giorgos Verigakis | #
|
3 | a1c50326 | Giorgos Verigakis | # Redistribution and use in source and binary forms, with or
|
4 | a1c50326 | Giorgos Verigakis | # without modification, are permitted provided that the following
|
5 | a1c50326 | Giorgos Verigakis | # conditions are met:
|
6 | a1c50326 | Giorgos Verigakis | #
|
7 | a1c50326 | Giorgos Verigakis | # 1. Redistributions of source code must retain the above
|
8 | a1c50326 | Giorgos Verigakis | # copyright notice, this list of conditions and the following
|
9 | a1c50326 | Giorgos Verigakis | # disclaimer.
|
10 | a1c50326 | Giorgos Verigakis | #
|
11 | a1c50326 | Giorgos Verigakis | # 2. Redistributions in binary form must reproduce the above
|
12 | a1c50326 | Giorgos Verigakis | # copyright notice, this list of conditions and the following
|
13 | a1c50326 | Giorgos Verigakis | # disclaimer in the documentation and/or other materials
|
14 | a1c50326 | Giorgos Verigakis | # provided with the distribution.
|
15 | a1c50326 | Giorgos Verigakis | #
|
16 | a1c50326 | Giorgos Verigakis | # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
|
17 | a1c50326 | Giorgos Verigakis | # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18 | a1c50326 | Giorgos Verigakis | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
19 | a1c50326 | Giorgos Verigakis | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
|
20 | a1c50326 | Giorgos Verigakis | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
21 | a1c50326 | Giorgos Verigakis | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
22 | a1c50326 | Giorgos Verigakis | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
23 | a1c50326 | Giorgos Verigakis | # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
24 | a1c50326 | Giorgos Verigakis | # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
25 | a1c50326 | Giorgos Verigakis | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
26 | a1c50326 | Giorgos Verigakis | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
27 | a1c50326 | Giorgos Verigakis | # POSSIBILITY OF SUCH DAMAGE.
|
28 | a1c50326 | Giorgos Verigakis | #
|
29 | a1c50326 | Giorgos Verigakis | # The views and conclusions contained in the software and
|
30 | a1c50326 | Giorgos Verigakis | # documentation are those of the authors and should not be
|
31 | a1c50326 | Giorgos Verigakis | # interpreted as representing official policies, either expressed
|
32 | a1c50326 | Giorgos Verigakis | # or implied, of GRNET S.A.
|
33 | a1c50326 | Giorgos Verigakis | |
34 | c270fe96 | Stavros Sachtouris | from kamaki.clients.compute import ComputeClient, ClientError |
35 | c270fe96 | Stavros Sachtouris | from kamaki.clients.utils import path4url |
36 | 6f1ec797 | Stavros Sachtouris | import json |
37 | a1c50326 | Giorgos Verigakis | |
38 | d2cea1e2 | Giorgos Verigakis | class CycladesClient(ComputeClient): |
39 | d2cea1e2 | Giorgos Verigakis | """GRNet Cyclades API client"""
|
40 | 2f749e6e | Stavros Sachtouris | |
41 | 6f1ec797 | Stavros Sachtouris | def networks_get(self, network_id = '', command='', **kwargs): |
42 | 6f1ec797 | Stavros Sachtouris | """GET base_url/networks[/network_id][/command] request
|
43 | 6f1ec797 | Stavros Sachtouris | @param network_id or ''
|
44 | 6f1ec797 | Stavros Sachtouris | @param command can be 'detail', or ''
|
45 | 6f1ec797 | Stavros Sachtouris | """
|
46 | 6f1ec797 | Stavros Sachtouris | path=path4url('networks', network_id, command)
|
47 | 6f1ec797 | Stavros Sachtouris | success = kwargs.pop('success', (200, 203)) |
48 | 6f1ec797 | Stavros Sachtouris | return self.get(path, success=success, **kwargs) |
49 | 6f1ec797 | Stavros Sachtouris | |
50 | 6f1ec797 | Stavros Sachtouris | def networks_delete(self, network_id = '', command='', **kwargs): |
51 | 6f1ec797 | Stavros Sachtouris | """DEL ETE base_url/networks[/network_id][/command] request
|
52 | 6f1ec797 | Stavros Sachtouris | @param network_id or ''
|
53 | 6f1ec797 | Stavros Sachtouris | @param command can be 'detail', or ''
|
54 | 6f1ec797 | Stavros Sachtouris | """
|
55 | 6f1ec797 | Stavros Sachtouris | path=path4url('networks', network_id, command)
|
56 | 6f1ec797 | Stavros Sachtouris | success = kwargs.pop('success', 204) |
57 | 6f1ec797 | Stavros Sachtouris | return self.delete(path, success=success, **kwargs) |
58 | 6f1ec797 | Stavros Sachtouris | |
59 | 6f1ec797 | Stavros Sachtouris | def networks_post(self, network_id = '', command='', json_data=None, **kwargs): |
60 | 6f1ec797 | Stavros Sachtouris | """POST base_url/servers[/server_id]/[command] request
|
61 | 6f1ec797 | Stavros Sachtouris | @param server_id or ''
|
62 | 6f1ec797 | Stavros Sachtouris | @param command: can be 'action' or ''
|
63 | 6f1ec797 | Stavros Sachtouris | @param json_data: a json valid dict that will be send as data
|
64 | 6f1ec797 | Stavros Sachtouris | """
|
65 | 6f1ec797 | Stavros Sachtouris | data= json_data |
66 | 6f1ec797 | Stavros Sachtouris | if json_data is not None: |
67 | 6f1ec797 | Stavros Sachtouris | data = json.dumps(json_data) |
68 | 6f1ec797 | Stavros Sachtouris | self.set_header('Content-Type', 'application/json') |
69 | 6f1ec797 | Stavros Sachtouris | self.set_header('Content-Length', len(data)) |
70 | 6f1ec797 | Stavros Sachtouris | |
71 | 6f1ec797 | Stavros Sachtouris | path = path4url('networks', network_id, command)
|
72 | 6f1ec797 | Stavros Sachtouris | success = kwargs.pop('success', 202) |
73 | 6f1ec797 | Stavros Sachtouris | return self.post(path, data=data, success=success, **kwargs) |
74 | 6f1ec797 | Stavros Sachtouris | |
75 | 6f1ec797 | Stavros Sachtouris | def networks_put(self, network_id = '', command='', json_data=None, **kwargs): |
76 | 6f1ec797 | Stavros Sachtouris | """PUT base_url/servers[/server_id]/[command] request
|
77 | 6f1ec797 | Stavros Sachtouris | @param server_id or ''
|
78 | 6f1ec797 | Stavros Sachtouris | @param command: can be 'action' or ''
|
79 | 6f1ec797 | Stavros Sachtouris | @param json_data: a json valid dict that will be send as data
|
80 | 6f1ec797 | Stavros Sachtouris | """
|
81 | 6f1ec797 | Stavros Sachtouris | data= json_data |
82 | 6f1ec797 | Stavros Sachtouris | if json_data is not None: |
83 | 6f1ec797 | Stavros Sachtouris | data = json.dumps(json_data) |
84 | 6f1ec797 | Stavros Sachtouris | self.set_header('Content-Type', 'application/json') |
85 | 6f1ec797 | Stavros Sachtouris | self.set_header('Content-Length', len(data)) |
86 | 6f1ec797 | Stavros Sachtouris | |
87 | 6f1ec797 | Stavros Sachtouris | path = path4url('networks', network_id, command)
|
88 | 6f1ec797 | Stavros Sachtouris | success = kwargs.pop('success', 204) |
89 | 6f1ec797 | Stavros Sachtouris | return self.put(path, data=data, success=success, **kwargs) |
90 | 6f1ec797 | Stavros Sachtouris | |
91 | a1c50326 | Giorgos Verigakis | def start_server(self, server_id): |
92 | a1c50326 | Giorgos Verigakis | """Submit a startup request for a server specified by id"""
|
93 | 6a0b1658 | Giorgos Verigakis | req = {'start': {}}
|
94 | 6ce9fc72 | Stavros Sachtouris | r = self.servers_post(server_id, 'action', json_data=req, success=202) |
95 | 6ce9fc72 | Stavros Sachtouris | r.release() |
96 | 6f1ec797 | Stavros Sachtouris | |
97 | a1c50326 | Giorgos Verigakis | def shutdown_server(self, server_id): |
98 | a1c50326 | Giorgos Verigakis | """Submit a shutdown request for a server specified by id"""
|
99 | 6a0b1658 | Giorgos Verigakis | req = {'shutdown': {}}
|
100 | 6ce9fc72 | Stavros Sachtouris | r = self.servers_post(server_id, 'action', json_data=req, success=202) |
101 | 6ce9fc72 | Stavros Sachtouris | r.release() |
102 | 4f01cc99 | Stavros Sachtouris | |
103 | a1c50326 | Giorgos Verigakis | def get_server_console(self, server_id): |
104 | a1c50326 | Giorgos Verigakis | """Get a VNC connection to the console of a server specified by id"""
|
105 | 6a0b1658 | Giorgos Verigakis | req = {'console': {'type': 'vnc'}} |
106 | 6f1ec797 | Stavros Sachtouris | r = self.servers_post(server_id, 'action', json_data=req, success=200) |
107 | 6a0b1658 | Giorgos Verigakis | return r.json['console'] |
108 | 2d67ecbb | Stavros Sachtouris | |
109 | 2d67ecbb | Stavros Sachtouris | def get_firewall_profile(self, server_id): |
110 | 2d67ecbb | Stavros Sachtouris | r = self.get_server_details(server_id)
|
111 | 2d67ecbb | Stavros Sachtouris | try:
|
112 | f34bfe13 | Stavros Sachtouris | return r['attachments']['values'][0]['firewallProfile'] |
113 | 2d67ecbb | Stavros Sachtouris | except KeyError: |
114 | 2d67ecbb | Stavros Sachtouris | raise ClientError('No Firewall Profile', 520, |
115 | 2d67ecbb | Stavros Sachtouris | details='Server %s is missing a firewall profile'%server_id)
|
116 | 2d67ecbb | Stavros Sachtouris | |
117 | a1c50326 | Giorgos Verigakis | def set_firewall_profile(self, server_id, profile): |
118 | a1c50326 | Giorgos Verigakis | """Set the firewall profile for the public interface of a server
|
119 | e52840fa | Stavros Sachtouris | The server is specified by id, the profile argument
|
120 | e52840fa | Stavros Sachtouris | is one of (ENABLED, DISABLED, PROTECTED).
|
121 | a1c50326 | Giorgos Verigakis | """
|
122 | 6a0b1658 | Giorgos Verigakis | req = {'firewallProfile': {'profile': profile}} |
123 | 6ce9fc72 | Stavros Sachtouris | r = self.servers_post(server_id, 'action', json_data=req, success=202) |
124 | 6ce9fc72 | Stavros Sachtouris | r.release() |
125 | 4f01cc99 | Stavros Sachtouris | |
126 | c7083665 | Stavros Sachtouris | def list_server_nics(self, server_id): |
127 | 6f1ec797 | Stavros Sachtouris | r = self.servers_get(server_id, 'ips') |
128 | c7083665 | Stavros Sachtouris | return r.json['addresses']['values'] |
129 | 1a85b14f | Stavros Sachtouris | |
130 | a1c50326 | Giorgos Verigakis | def get_server_stats(self, server_id): |
131 | 6f1ec797 | Stavros Sachtouris | r = self.servers_get(server_id, 'stats') |
132 | 6a0b1658 | Giorgos Verigakis | return r.json['stats'] |
133 | 4f01cc99 | Stavros Sachtouris | |
134 | a1c50326 | Giorgos Verigakis | def list_networks(self, detail=False): |
135 | 6f1ec797 | Stavros Sachtouris | detail = 'detail' if detail else '' |
136 | 6f1ec797 | Stavros Sachtouris | r = self.networks_get(command=detail)
|
137 | 6a0b1658 | Giorgos Verigakis | return r.json['networks']['values'] |
138 | a1c50326 | Giorgos Verigakis | |
139 | e52840fa | Stavros Sachtouris | def create_network(self, name, cidr=False, gateway=False, type=False, dhcp=False): |
140 | e52840fa | Stavros Sachtouris | """@params cidr, geteway, type and dhcp should be strings
|
141 | e52840fa | Stavros Sachtouris | """
|
142 | e52840fa | Stavros Sachtouris | net = dict(name=name)
|
143 | e52840fa | Stavros Sachtouris | if cidr:
|
144 | e52840fa | Stavros Sachtouris | net['cidr']=cidr
|
145 | e52840fa | Stavros Sachtouris | if gateway:
|
146 | e52840fa | Stavros Sachtouris | net['gateway']=gateway
|
147 | e52840fa | Stavros Sachtouris | if type: |
148 | e52840fa | Stavros Sachtouris | net['type']=type |
149 | e52840fa | Stavros Sachtouris | if dhcp:
|
150 | e52840fa | Stavros Sachtouris | net['dhcp']=dhcp
|
151 | e52840fa | Stavros Sachtouris | req = dict(network=net)
|
152 | 6f1ec797 | Stavros Sachtouris | r = self.networks_post(json_data=req, success=202) |
153 | 6a0b1658 | Giorgos Verigakis | return r.json['network'] |
154 | a1c50326 | Giorgos Verigakis | |
155 | a1c50326 | Giorgos Verigakis | def get_network_details(self, network_id): |
156 | 6f1ec797 | Stavros Sachtouris | r = self.networks_get(network_id=network_id)
|
157 | 6a0b1658 | Giorgos Verigakis | return r.json['network'] |
158 | a1c50326 | Giorgos Verigakis | |
159 | a1c50326 | Giorgos Verigakis | def update_network_name(self, network_id, new_name): |
160 | 6a0b1658 | Giorgos Verigakis | req = {'network': {'name': new_name}} |
161 | 6ce9fc72 | Stavros Sachtouris | r = self.networks_put(network_id=network_id, json_data=req)
|
162 | 6ce9fc72 | Stavros Sachtouris | r.release() |
163 | a1c50326 | Giorgos Verigakis | |
164 | a1c50326 | Giorgos Verigakis | def delete_network(self, network_id): |
165 | 6ce9fc72 | Stavros Sachtouris | r = self.networks_delete(network_id)
|
166 | 6ce9fc72 | Stavros Sachtouris | r.release() |
167 | a1c50326 | Giorgos Verigakis | |
168 | a1c50326 | Giorgos Verigakis | def connect_server(self, server_id, network_id): |
169 | 6a0b1658 | Giorgos Verigakis | req = {'add': {'serverRef': server_id}} |
170 | 6ce9fc72 | Stavros Sachtouris | r = self.networks_post(network_id, 'action', json_data=req) |
171 | 6ce9fc72 | Stavros Sachtouris | r.release() |
172 | a1c50326 | Giorgos Verigakis | |
173 | c7083665 | Stavros Sachtouris | def disconnect_server(self, server_id, nic_id): |
174 | c7083665 | Stavros Sachtouris | server_nets = self.list_server_nics(server_id)
|
175 | c7083665 | Stavros Sachtouris | nets = [(net['id'],net['network_id']) for net in server_nets if nic_id == net['id']] |
176 | 6f1ec797 | Stavros Sachtouris | if len(nets) == 0: |
177 | 6666f3b3 | Stavros Sachtouris | return
|
178 | c7083665 | Stavros Sachtouris | for (nic_id, network_id) in nets: |
179 | 6f1ec797 | Stavros Sachtouris | req={'remove':{'attachment':unicode(nic_id)}} |
180 | 6ce9fc72 | Stavros Sachtouris | r = self.networks_post(network_id, 'action', json_data=req) |
181 | 6ce9fc72 | Stavros Sachtouris | r.release() |