Statistics
| Branch: | Tag: | Revision:

root / kamaki / clients / cyclades.py @ 3dabe5d2

History | View | Annotate | Download (8 kB)

1
# Copyright 2011 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
from kamaki.clients.compute import ComputeClient, ClientError
35
from kamaki.clients.utils import path4url
36
import json
37

    
38

    
39
class CycladesClient(ComputeClient):
40
    """GRNet Cyclades API client"""
41

    
42
    def networks_get(self, network_id='', command='', **kwargs):
43
        """GET base_url/networks[/network_id][/command] request
44
        @param network_id or ''
45
        @param command can be 'detail', or ''
46
        """
47
        path = path4url('networks', network_id, command)
48
        success = kwargs.pop('success', (200, 203))
49
        return self.get(path, success=success, **kwargs)
50

    
51
    def networks_delete(self, network_id='', command='', **kwargs):
52
        """DEL ETE base_url/networks[/network_id][/command] request
53
        @param network_id or ''
54
        @param command can be 'detail', or ''
55
        """
56
        path = path4url('networks', network_id, command)
57
        success = kwargs.pop('success', 204)
58
        return self.delete(path, success=success, **kwargs)
59

    
60
    def networks_post(self,
61
        network_id='',
62
        command='',
63
        json_data=None,
64
        **kwargs):
65
        """POST base_url/servers[/server_id]/[command] request
66
        @param server_id or ''
67
        @param command: can be 'action' or ''
68
        @param json_data: a json valid dict that will be send as data
69
        """
70
        data = json_data
71
        if json_data is not None:
72
            data = json.dumps(json_data)
73
            self.set_header('Content-Type', 'application/json')
74
            self.set_header('Content-Length', len(data))
75

    
76
        path = path4url('networks', network_id, command)
77
        success = kwargs.pop('success', 202)
78
        return self.post(path, data=data, success=success, **kwargs)
79

    
80
    def networks_put(self,
81
        network_id='',
82
        command='',
83
        json_data=None,
84
        **kwargs):
85
        """PUT base_url/servers[/server_id]/[command] request
86
        @param server_id or ''
87
        @param command: can be 'action' or ''
88
        @param json_data: a json valid dict that will be send as data
89
        """
90
        data = json_data
91
        if json_data is not None:
92
            data = json.dumps(json_data)
93
            self.set_header('Content-Type', 'application/json')
94
            self.set_header('Content-Length', len(data))
95

    
96
        path = path4url('networks', network_id, command)
97
        success = kwargs.pop('success', 204)
98
        return self.put(path, data=data, success=success, **kwargs)
99

    
100
    def start_server(self, server_id):
101
        """Submit a startup request for a server specified by id"""
102
        req = {'start': {}}
103
        r = self.servers_post(server_id, 'action', json_data=req, success=202)
104
        r.release()
105

    
106
    def shutdown_server(self, server_id):
107
        """Submit a shutdown request for a server specified by id"""
108
        req = {'shutdown': {}}
109
        r = self.servers_post(server_id, 'action', json_data=req, success=202)
110
        r.release()
111

    
112
    def get_server_console(self, server_id):
113
        """Get a VNC connection to the console of a server specified by id"""
114
        req = {'console': {'type': 'vnc'}}
115
        r = self.servers_post(server_id, 'action', json_data=req, success=200)
116
        return r.json['console']
117

    
118
    def get_firewall_profile(self, server_id):
119
        r = self.get_server_details(server_id)
120
        try:
121
            return r['attachments']['values'][0]['firewallProfile']
122
        except KeyError:
123
            raise ClientError('No Firewall Profile', 520,
124
                details='Server %s is missing a firewall profile' % server_id)
125

    
126
    def set_firewall_profile(self, server_id, profile):
127
        """Set the firewall profile for the public interface of a server
128
           The server is specified by id, the profile argument
129
           is one of (ENABLED, DISABLED, PROTECTED).
130
        """
131
        req = {'firewallProfile': {'profile': profile}}
132
        r = self.servers_post(server_id, 'action', json_data=req, success=202)
133
        r.release()
134

    
135
    def list_server_nics(self, server_id):
136
        r = self.servers_get(server_id, 'ips')
137
        return r.json['addresses']['values']
138

    
139
    def get_server_stats(self, server_id):
140
        r = self.servers_get(server_id, 'stats')
141
        return r.json['stats']
142

    
143
    def list_networks(self, detail=False):
144
        detail = 'detail' if detail else ''
145
        r = self.networks_get(command=detail)
146
        return r.json['networks']['values']
147

    
148
    #NEW
149
    def list_network_nics(self, network_id):
150
        r = self.networks_get(network_id=network_id)
151
        return r.json['network']['attachments']['values']
152

    
153
    def create_network(self,
154
        name,
155
        cidr=False,
156
        gateway=False,
157
        type=False,
158
        dhcp=False):
159
        """@params cidr, geteway, type and dhcp should be strings
160
        """
161
        net = dict(name=name)
162
        if cidr:
163
            net['cidr'] = cidr
164
        if gateway:
165
            net['gateway'] = gateway
166
        if type:
167
            net['type'] = type
168
        if dhcp:
169
            net['dhcp'] = dhcp
170
        req = dict(network=net)
171
        r = self.networks_post(json_data=req, success=202)
172
        return r.json['network']
173

    
174
    def get_network_details(self, network_id):
175
        r = self.networks_get(network_id=network_id)
176
        return r.json['network']
177

    
178
    def update_network_name(self, network_id, new_name):
179
        req = {'network': {'name': new_name}}
180
        r = self.networks_put(network_id=network_id, json_data=req)
181
        r.release()
182

    
183
    def delete_network(self, network_id):
184
        try:
185
            r = self.networks_delete(network_id)
186
        except ClientError as err:
187
            if err.status == 421:
188
                err.details =\
189
                'Network may be still connected to at least one server'
190
            raise err
191
        r.release()
192

    
193
    def connect_server(self, server_id, network_id):
194
        req = {'add': {'serverRef': server_id}}
195
        r = self.networks_post(network_id, 'action', json_data=req)
196
        r.release()
197

    
198
    def disconnect_server(self, server_id, nic_id):
199
        server_nets = self.list_server_nics(server_id)
200
        nets = [(net['id'], net['network_id']) for net in server_nets\
201
            if nic_id == net['id']]
202
        if len(nets) == 0:
203
            return
204
        for (nic_id, network_id) in nets:
205
            req = {'remove': {'attachment': unicode(nic_id)}}
206
            r = self.networks_post(network_id, 'action', json_data=req)
207
            r.release()
208

    
209
    #NEW
210
    def disconnect_network_nics(self, netid):
211
        r = self.list_network_nics(netid)
212
        for nic in r:
213
            req = dict(remove=dict(attachment=nic))
214
            r = self.networks_post(netid, 'action', json_data=req)