Revision b6afe2ec
b/kamaki/cli/commands/cyclades.py | ||
---|---|---|
474 | 474 |
'If neither --network or --no-network are used, the default ' |
475 | 475 |
'network policy is applied. These policies are set on the cloud, ' |
476 | 476 |
'so kamaki is oblivious to them', |
477 |
'--no-network') |
|
477 |
'--no-network'), |
|
478 |
project=ValueArgument('Assign the server to project', '--project'), |
|
478 | 479 |
) |
479 | 480 |
required = ('server_name', 'flavor_id', 'image_id') |
480 | 481 |
|
481 | 482 |
@errors.cyclades.cluster_size |
482 |
def _create_cluster(self, prefix, flavor_id, image_id, size): |
|
483 |
def _create_cluster(self, prefix, flavor_id, image_id, size, project=None):
|
|
483 | 484 |
networks = self['network_configuration'] or ( |
484 | 485 |
[] if self['no_network'] else None) |
485 | 486 |
servers = [dict( |
486 | 487 |
name='%s%s' % (prefix, i if size > 1 else ''), |
487 | 488 |
flavor_id=flavor_id, |
488 | 489 |
image_id=image_id, |
490 |
project=project, |
|
489 | 491 |
personality=self['personality'], |
490 | 492 |
networks=networks) for i in range(1, 1 + size)] |
491 | 493 |
if size == 1: |
... | ... | |
518 | 520 |
@errors.cyclades.flavor_id |
519 | 521 |
def _run(self, name, flavor_id, image_id): |
520 | 522 |
for r in self._create_cluster( |
521 |
name, flavor_id, image_id, size=self['cluster_size'] or 1): |
|
523 |
name, flavor_id, image_id, size=self['cluster_size'] or 1, |
|
524 |
project=self['project']): |
|
522 | 525 |
if not r: |
523 | 526 |
self.error('Create %s: server response was %s' % (name, r)) |
524 | 527 |
continue |
... | ... | |
657 | 660 |
|
658 | 661 |
|
659 | 662 |
@command(server_cmds) |
663 |
class server_reassign(_init_cyclades, _optional_json): |
|
664 |
"""Assign a VM to a different project |
|
665 |
""" |
|
666 |
|
|
667 |
@errors.generic.all |
|
668 |
@errors.cyclades.connection |
|
669 |
@errors.cyclades.server_id |
|
670 |
def _run(self, server_id, project): |
|
671 |
self.client.reassign_server(server_id, project) |
|
672 |
|
|
673 |
def main(self, server_id, project): |
|
674 |
super(self.__class__, self)._run() |
|
675 |
self._run(server_id=server_id, project=project) |
|
676 |
|
|
677 |
|
|
678 |
@command(server_cmds) |
|
660 | 679 |
class server_delete(_init_cyclades, _optional_output_cmd, _server_wait): |
661 | 680 |
"""Delete a virtual server""" |
662 | 681 |
|
b/kamaki/cli/commands/network.py | ||
---|---|---|
189 | 189 |
name=ValueArgument('Network name', '--name'), |
190 | 190 |
shared=FlagArgument( |
191 | 191 |
'Make network shared (special privileges required)', '--shared'), |
192 |
project=ValueArgument('Assign the network to project', '--project'), |
|
192 | 193 |
network_type=NetworkTypeArgument( |
193 | 194 |
'Valid network types: %s' % (', '.join(NetworkTypeArgument.types)), |
194 | 195 |
'--type') |
... | ... | |
199 | 200 |
@errors.cyclades.network_type |
200 | 201 |
def _run(self, network_type): |
201 | 202 |
net = self.client.create_network( |
202 |
network_type, name=self['name'], shared=self['shared']) |
|
203 |
network_type, name=self['name'], |
|
204 |
shared=self['shared'], |
|
205 |
project=self['project']) |
|
203 | 206 |
self._print(net, self.print_dict) |
204 | 207 |
|
205 | 208 |
def main(self): |
... | ... | |
208 | 211 |
|
209 | 212 |
|
210 | 213 |
@command(network_cmds) |
214 |
class network_reassign(_init_network, _optional_json): |
|
215 |
"""Assign a network to a different project |
|
216 |
""" |
|
217 |
|
|
218 |
@errors.generic.all |
|
219 |
@errors.cyclades.connection |
|
220 |
@errors.cyclades.network_id |
|
221 |
def _run(self, network_id, project): |
|
222 |
self.client.reassign_network(network_id, project) |
|
223 |
|
|
224 |
def main(self, network_id, project): |
|
225 |
super(self.__class__, self)._run() |
|
226 |
self._run(network_id=network_id, project=project) |
|
227 |
|
|
228 |
|
|
229 |
@command(network_cmds) |
|
211 | 230 |
class network_delete(_init_network, _optional_output_cmd): |
212 | 231 |
"""Delete a network""" |
213 | 232 |
|
... | ... | |
607 | 626 |
arguments = dict( |
608 | 627 |
network_id=ValueArgument( |
609 | 628 |
'The network to preserve the IP on', '--network-id'), |
610 |
ip_address=ValueArgument('Allocate an IP address', '--address') |
|
629 |
ip_address=ValueArgument('Allocate an IP address', '--address'), |
|
630 |
project=ValueArgument('Assign the IP to project', '--project'), |
|
611 | 631 |
) |
612 | 632 |
required = ('network_id', ) |
613 | 633 |
|
... | ... | |
617 | 637 |
def _run(self, network_id): |
618 | 638 |
self._print( |
619 | 639 |
self.client.create_floatingip( |
620 |
network_id, floating_ip_address=self['ip_address']), |
|
640 |
network_id, floating_ip_address=self['ip_address'], |
|
641 |
project=self['project']), |
|
621 | 642 |
self.print_dict) |
622 | 643 |
|
623 | 644 |
def main(self): |
... | ... | |
626 | 647 |
|
627 | 648 |
|
628 | 649 |
@command(ip_cmds) |
650 |
class ip_reassign(_init_network, _optional_output_cmd): |
|
651 |
"""Assign a floating IP to a different project |
|
652 |
""" |
|
653 |
@errors.generic.all |
|
654 |
@errors.cyclades.connection |
|
655 |
def _run(self, ip, project): |
|
656 |
self._optional_output(self.client.reassign_floating_ip(ip, project)) |
|
657 |
|
|
658 |
def main(self, IP, project): |
|
659 |
super(self.__class__, self)._run() |
|
660 |
self._run(ip=IP, project=project) |
|
661 |
|
|
662 |
|
|
663 |
@command(ip_cmds) |
|
629 | 664 |
class ip_delete(_init_network, _optional_output_cmd): |
630 | 665 |
"""Unreserve an IP (also delete the port, if attached)""" |
631 | 666 |
|
b/kamaki/clients/compute/__init__.py | ||
---|---|---|
114 | 114 |
metadata=None, |
115 | 115 |
personality=None, |
116 | 116 |
networks=None, |
117 |
project=None, |
|
117 | 118 |
response_headers=dict(location=None)): |
118 | 119 |
"""Submit request to create a new server |
119 | 120 |
|
... | ... | |
151 | 152 |
if networks is not None: |
152 | 153 |
req['server']['networks'] = networks |
153 | 154 |
|
155 |
if project: |
|
156 |
req['server']['project'] = project |
|
157 |
|
|
154 | 158 |
r = self.servers_post( |
155 | 159 |
json_data=req, |
156 | 160 |
security_group=security_group, |
b/kamaki/clients/cyclades/__init__.py | ||
---|---|---|
35 | 35 |
from kamaki.clients.network import NetworkClient |
36 | 36 |
from kamaki.clients.utils import path4url |
37 | 37 |
from kamaki.clients import ClientError, Waiter |
38 |
|
|
38 |
import json |
|
39 | 39 |
|
40 | 40 |
class CycladesClient(CycladesRestClient, Waiter): |
41 | 41 |
"""Synnefo Cyclades Compute API client""" |
42 | 42 |
|
43 | 43 |
def create_server( |
44 | 44 |
self, name, flavor_id, image_id, |
45 |
metadata=None, personality=None, networks=None): |
|
45 |
metadata=None, personality=None, networks=None, project=None):
|
|
46 | 46 |
"""Submit request to create a new server |
47 | 47 |
|
48 | 48 |
:param name: (str) |
... | ... | |
64 | 64 |
ATTENTION: Empty list is different to None. None means ' do not |
65 | 65 |
mention it', empty list means 'automatically get an ip' |
66 | 66 |
|
67 |
:param project: the project where to assign the server |
|
68 |
|
|
67 | 69 |
:returns: a dict with the new virtual server details |
68 | 70 |
|
69 | 71 |
:raises ClientError: wraps request errors |
... | ... | |
78 | 80 |
|
79 | 81 |
return super(CycladesClient, self).create_server( |
80 | 82 |
name, flavor_id, image_id, |
81 |
metadata=metadata, personality=personality, networks=networks) |
|
83 |
metadata=metadata, personality=personality, networks=networks, |
|
84 |
project=project) |
|
82 | 85 |
|
83 | 86 |
def set_firewall_profile(self, server_id, profile, port_id): |
84 | 87 |
"""Set the firewall profile for the public interface of a server |
... | ... | |
123 | 126 |
r = self.servers_action_post(server_id, json_data=req, success=200) |
124 | 127 |
return r.json['console'] |
125 | 128 |
|
129 |
def reassign_server(self, server_id, project): |
|
130 |
req = {'reassign': {'project': project}} |
|
131 |
r = self.servers_action_post(server_id, json_data=req, success=200) |
|
132 |
return r.headers |
|
133 |
|
|
126 | 134 |
def get_server_stats(self, server_id): |
127 | 135 |
""" |
128 | 136 |
:param server_id: integer (str or int) |
... | ... | |
180 | 188 |
r = self.get(path, success=200) |
181 | 189 |
return r.json['networks'] |
182 | 190 |
|
183 |
def create_network(self, type, name=None, shared=None): |
|
191 |
def create_network(self, type, name=None, shared=None, project=None):
|
|
184 | 192 |
req = dict(network=dict(type=type, admin_state_up=True)) |
185 | 193 |
if name: |
186 | 194 |
req['network']['name'] = name |
187 | 195 |
if shared not in (None, ): |
188 | 196 |
req['network']['shared'] = bool(shared) |
197 |
if project is not None: |
|
198 |
req['network']['project'] = project |
|
189 | 199 |
r = self.networks_post(json_data=req, success=201) |
190 | 200 |
return r.json['network'] |
191 | 201 |
|
202 |
def networks_action_post( |
|
203 |
self, network_id='', json_data=None, success=202, **kwargs): |
|
204 |
"""POST base_url/networks/<network_id>/action |
|
205 |
|
|
206 |
:returns: request response |
|
207 |
""" |
|
208 |
if json_data: |
|
209 |
json_data = json.dumps(json_data) |
|
210 |
self.set_header('Content-Type', 'application/json') |
|
211 |
self.set_header('Content-Length', len(json_data)) |
|
212 |
path = path4url('networks', network_id, 'action') |
|
213 |
return self.post(path, data=json_data, success=success, **kwargs) |
|
214 |
|
|
215 |
def reassign_network(self, network_id, project): |
|
216 |
req = {'reassign': {'project': project}} |
|
217 |
r = self.networks_action_post(network_id, json_data=req, success=200) |
|
218 |
return r.headers |
|
219 |
|
|
192 | 220 |
def list_ports(self, detail=None): |
193 | 221 |
path = path4url('ports', 'detail' if detail else '') |
194 | 222 |
r = self.get(path, success=200) |
... | ... | |
215 | 243 |
r = self.ports_post(json_data=dict(port=port), success=201) |
216 | 244 |
return r.json['port'] |
217 | 245 |
|
218 |
def create_floatingip(self, floating_network_id, floating_ip_address=''): |
|
246 |
def create_floatingip(self, floating_network_id, floating_ip_address='', |
|
247 |
project=None): |
|
248 |
args = {"project": project} |
|
219 | 249 |
return super(CycladesNetworkClient, self).create_floatingip( |
220 |
floating_network_id, floating_ip_address=floating_ip_address) |
|
250 |
floating_network_id, |
|
251 |
floating_ip_address=floating_ip_address, args=args) |
|
252 |
|
|
253 |
def floating_ip_action_post( |
|
254 |
self, fip_id, json_data=None, success=202, **kwargs): |
|
255 |
"""POST base_url/floatingips/<fip_id>/action |
|
256 |
|
|
257 |
:returns: request response |
|
258 |
""" |
|
259 |
if json_data: |
|
260 |
json_data = json.dumps(json_data) |
|
261 |
self.set_header('Content-Type', 'application/json') |
|
262 |
self.set_header('Content-Length', len(json_data)) |
|
263 |
path = path4url('floatingips', fip_id, 'action') |
|
264 |
return self.post(path, data=json_data, success=success, **kwargs) |
|
265 |
|
|
266 |
def reassign_floating_ip(self, floating_network_id, project): |
|
267 |
req = {'reassign': {'project': project}} |
|
268 |
r = self.floating_ip_action_post(floating_network_id, json_data=req) |
b/kamaki/clients/network/__init__.py | ||
---|---|---|
331 | 331 |
|
332 | 332 |
def create_floatingip( |
333 | 333 |
self, floating_network_id, |
334 |
floating_ip_address='', port_id='', fixed_ip_address=''): |
|
334 |
floating_ip_address='', port_id='', fixed_ip_address='', |
|
335 |
args=None): |
|
335 | 336 |
"""Cyclades do not use port_id and fixed_ip_address""" |
336 | 337 |
floatingip = dict(floating_network_id=floating_network_id) |
337 | 338 |
if floating_ip_address: |
... | ... | |
340 | 341 |
floatingip['port_id'] = port_id |
341 | 342 |
if fixed_ip_address: |
342 | 343 |
floatingip['fixed_ip_address'] = fixed_ip_address |
344 |
if args is not None: |
|
345 |
floatingip.update(args) |
|
343 | 346 |
r = self.floatingips_post( |
344 | 347 |
json_data=dict(floatingip=floatingip), success=200) |
345 | 348 |
return r.json['floatingip'] |
Also available in: Unified diff