Statistics
| Branch: | Tag: | Revision:

root / kamaki / clients / cyclades.py @ 29685b9b

History | View | Annotate | Download (7.4 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.cyclades_rest_api import CycladesClientApi
35
from kamaki.clients import ClientError
36
from time import sleep
37

    
38

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

    
42
    def start_server(self, server_id):
43
        """Submit a startup request for a server specified by id"""
44
        req = {'start': {}}
45
        r = self.servers_post(server_id, 'action', json_data=req, success=202)
46
        r.release()
47

    
48
    def shutdown_server(self, server_id):
49
        """Submit a shutdown request for a server specified by id"""
50
        req = {'shutdown': {}}
51
        r = self.servers_post(server_id, 'action', json_data=req, success=202)
52
        r.release()
53

    
54
    def get_server_console(self, server_id):
55
        """Get a VNC connection to the console of a server specified by id"""
56
        req = {'console': {'type': 'vnc'}}
57
        r = self.servers_post(server_id, 'action', json_data=req, success=200)
58
        return r.json['console']
59

    
60
    def get_firewall_profile(self, server_id):
61
        r = self.get_server_details(server_id)
62
        try:
63
            return r['attachments']['values'][0]['firewallProfile']
64
        except KeyError:
65
            raise ClientError('No Firewall Profile', 520,
66
                details='Server %s is missing a firewall profile' % server_id)
67

    
68
    def set_firewall_profile(self, server_id, profile):
69
        """Set the firewall profile for the public interface of a server
70
           The server is specified by id, the profile argument
71
           is one of (ENABLED, DISABLED, PROTECTED).
72
        """
73
        req = {'firewallProfile': {'profile': profile}}
74
        r = self.servers_post(server_id, 'action', json_data=req, success=202)
75
        r.release()
76

    
77
    def list_server_nics(self, server_id):
78
        r = self.servers_get(server_id, 'ips')
79
        return r.json['addresses']['values']
80

    
81
    def get_server_stats(self, server_id):
82
        r = self.servers_get(server_id, 'stats')
83
        return r.json['stats']
84

    
85
    def list_networks(self, detail=False):
86
        detail = 'detail' if detail else ''
87
        r = self.networks_get(command=detail)
88
        return r.json['networks']['values']
89

    
90
    #NEW
91
    def list_network_nics(self, network_id):
92
        r = self.networks_get(network_id=network_id)
93
        return r.json['network']['attachments']['values']
94

    
95
    def create_network(self,
96
        name,
97
        cidr=False,
98
        gateway=False,
99
        type=False,
100
        dhcp=False):
101
        """@params cidr, geteway, type and dhcp should be strings
102
        """
103
        net = dict(name=name)
104
        if cidr:
105
            net['cidr'] = cidr
106
        if gateway:
107
            net['gateway'] = gateway
108
        if type:
109
            net['type'] = type
110
        if dhcp:
111
            net['dhcp'] = dhcp
112
        req = dict(network=net)
113
        r = self.networks_post(json_data=req, success=202)
114
        return r.json['network']
115

    
116
    def get_network_details(self, network_id):
117
        r = self.networks_get(network_id=network_id)
118
        return r.json['network']
119

    
120
    def update_network_name(self, network_id, new_name):
121
        req = {'network': {'name': new_name}}
122
        r = self.networks_put(network_id=network_id, json_data=req)
123
        r.release()
124

    
125
    def delete_network(self, network_id):
126
        try:
127
            r = self.networks_delete(network_id)
128
        except ClientError as err:
129
            if err.status == 421:
130
                err.details =\
131
                'Network may be still connected to at least one server'
132
            raise err
133
        r.release()
134

    
135
    def connect_server(self, server_id, network_id):
136
        req = {'add': {'serverRef': server_id}}
137
        r = self.networks_post(network_id, 'action', json_data=req)
138
        r.release()
139

    
140
    def disconnect_server(self, server_id, nic_id):
141
        server_nets = self.list_server_nics(server_id)
142
        nets = [(net['id'], net['network_id']) for net in server_nets\
143
            if nic_id == net['id']]
144
        if len(nets) == 0:
145
            return
146
        for (nic_id, network_id) in nets:
147
            req = {'remove': {'attachment': unicode(nic_id)}}
148
            r = self.networks_post(network_id, 'action', json_data=req)
149
            r.release()
150

    
151
    #NEW
152
    def disconnect_network_nics(self, netid):
153
        r = self.list_network_nics(netid)
154
        for nic in r:
155
            req = dict(remove=dict(attachment=nic))
156
            r = self.networks_post(netid, 'action', json_data=req)
157

    
158
    def wait_server(self, server_id,
159
        current_status='BUILD',
160
        delay=0.5,
161
        max_wait=128,
162
        wait_cb=None):
163
        """Wait for server to reach a status different from current_status
164
            @return the new mode if succesfull, False if timed out
165
            @server_id
166
            @current_status
167
            @delay time interval between retries
168
            @wait_cb if set a progressbar is used to show progress
169
        """
170
        r = self.get_server_details(server_id)
171
        if r['status'] != current_status:
172
            return r['status']
173
        old_wait = total_wait = 0
174

    
175
        if current_status == 'BUILD':
176
            max_wait = 100
177
            wait_gen = wait_cb(max_wait)
178
        elif wait_cb:
179
            wait_gen = wait_cb(1 + max_wait // delay)
180
            wait_gen.next()
181

    
182
        while r['status'] == current_status and total_wait <= max_wait:
183
            if current_status == 'BUILD':
184
                total_wait = int(r['progress'])
185
                if wait_cb:
186
                    for i in range(int(old_wait), int(total_wait)):
187
                        wait_gen.next()
188
                    old_wait = total_wait
189
            else:
190
                if wait_cb:
191
                    wait_gen.next()
192
                total_wait += delay
193
            sleep(delay)
194
            r = self.get_server_details(server_id)
195

    
196
        if r['status'] != current_status:
197
            if wait_cb:
198
                try:
199
                    while True:
200
                        wait_gen.next()
201
                except:
202
                    pass
203
            return r['status']
204
        return False