Commit 82c4d59b authored by Giorgos Korfiatis's avatar Giorgos Korfiatis Committed by Stavros Sachtouris
Browse files

Adapt Cyclades-related commands for new projects

Add optional argument --project in create subcommands;
add subcommand "reassign" for "server", "network" and "ip" commands.
parent d8f0b4e0
......@@ -474,18 +474,20 @@ class server_create(_init_cyclades, _optional_json, _server_wait):
'If neither --network or --no-network are used, the default '
'network policy is applied. These policies are set on the cloud, '
'so kamaki is oblivious to them',
'--no-network')
'--no-network'),
project=ValueArgument('Assign the server to project', '--project'),
)
required = ('server_name', 'flavor_id', 'image_id')
@errors.cyclades.cluster_size
def _create_cluster(self, prefix, flavor_id, image_id, size):
def _create_cluster(self, prefix, flavor_id, image_id, size, project=None):
networks = self['network_configuration'] or (
[] if self['no_network'] else None)
servers = [dict(
name='%s%s' % (prefix, i if size > 1 else ''),
flavor_id=flavor_id,
image_id=image_id,
project=project,
personality=self['personality'],
networks=networks) for i in range(1, 1 + size)]
if size == 1:
......@@ -518,7 +520,8 @@ class server_create(_init_cyclades, _optional_json, _server_wait):
@errors.cyclades.flavor_id
def _run(self, name, flavor_id, image_id):
for r in self._create_cluster(
name, flavor_id, image_id, size=self['cluster_size'] or 1):
name, flavor_id, image_id, size=self['cluster_size'] or 1,
project=self['project']):
if not r:
self.error('Create %s: server response was %s' % (name, r))
continue
......@@ -656,6 +659,22 @@ class server_modify(_init_cyclades, _optional_output_cmd):
self._run(server_id=server_id)
@command(server_cmds)
class server_reassign(_init_cyclades, _optional_json):
"""Assign a VM to a different project
"""
@errors.generic.all
@errors.cyclades.connection
@errors.cyclades.server_id
def _run(self, server_id, project):
self.client.reassign_server(server_id, project)
def main(self, server_id, project):
super(self.__class__, self)._run()
self._run(server_id=server_id, project=project)
@command(server_cmds)
class server_delete(_init_cyclades, _optional_output_cmd, _server_wait):
"""Delete a virtual server"""
......
......@@ -189,6 +189,7 @@ class network_create(_init_network, _optional_json):
name=ValueArgument('Network name', '--name'),
shared=FlagArgument(
'Make network shared (special privileges required)', '--shared'),
project=ValueArgument('Assign the network to project', '--project'),
network_type=NetworkTypeArgument(
'Valid network types: %s' % (', '.join(NetworkTypeArgument.types)),
'--type')
......@@ -199,7 +200,9 @@ class network_create(_init_network, _optional_json):
@errors.cyclades.network_type
def _run(self, network_type):
net = self.client.create_network(
network_type, name=self['name'], shared=self['shared'])
network_type, name=self['name'],
shared=self['shared'],
project=self['project'])
self._print(net, self.print_dict)
def main(self):
......@@ -207,6 +210,22 @@ class network_create(_init_network, _optional_json):
self._run(network_type=self['network_type'])
@command(network_cmds)
class network_reassign(_init_network, _optional_json):
"""Assign a network to a different project
"""
@errors.generic.all
@errors.cyclades.connection
@errors.cyclades.network_id
def _run(self, network_id, project):
self.client.reassign_network(network_id, project)
def main(self, network_id, project):
super(self.__class__, self)._run()
self._run(network_id=network_id, project=project)
@command(network_cmds)
class network_delete(_init_network, _optional_output_cmd):
"""Delete a network"""
......@@ -607,7 +626,8 @@ class ip_create(_init_network, _optional_json):
arguments = dict(
network_id=ValueArgument(
'The network to preserve the IP on', '--network-id'),
ip_address=ValueArgument('Allocate an IP address', '--address')
ip_address=ValueArgument('Allocate an IP address', '--address'),
project_id=ValueArgument('Assign the IP to project', '--project-id'),
)
@errors.generic.all
......@@ -615,7 +635,9 @@ class ip_create(_init_network, _optional_json):
def _run(self):
self._print(
self.client.create_floatingip(
self['network_id'], floating_ip_address=self['ip_address']),
self['network_id'],
floating_ip_address=self['ip_address'],
project_id=self['project_id']),
self.print_dict)
def main(self):
......@@ -623,6 +645,20 @@ class ip_create(_init_network, _optional_json):
self._run()
@command(ip_cmds)
class ip_reassign(_init_network, _optional_output_cmd):
"""Assign a floating IP to a different project
"""
@errors.generic.all
@errors.cyclades.connection
def _run(self, ip, project):
self._optional_output(self.client.reassign_floating_ip(ip, project))
def main(self, IP, project):
super(self.__class__, self)._run()
self._run(ip=IP, project=project)
@command(ip_cmds)
class ip_delete(_init_network, _optional_output_cmd):
"""Unreserve an IP (also delete the port, if attached)"""
......
......@@ -114,6 +114,7 @@ class ComputeClient(ComputeRestClient):
metadata=None,
personality=None,
networks=None,
project=None,
response_headers=dict(location=None)):
"""Submit request to create a new server
......@@ -151,6 +152,9 @@ class ComputeClient(ComputeRestClient):
if networks is not None:
req['server']['networks'] = networks
if project:
req['server']['project'] = project
r = self.servers_post(
json_data=req,
security_group=security_group,
......
......@@ -35,14 +35,14 @@ from kamaki.clients.cyclades.rest_api import CycladesRestClient
from kamaki.clients.network import NetworkClient
from kamaki.clients.utils import path4url
from kamaki.clients import ClientError, Waiter
import json
class CycladesClient(CycladesRestClient, Waiter):
"""Synnefo Cyclades Compute API client"""
def create_server(
self, name, flavor_id, image_id,
metadata=None, personality=None, networks=None):
metadata=None, personality=None, networks=None, project=None):
"""Submit request to create a new server
:param name: (str)
......@@ -64,6 +64,8 @@ class CycladesClient(CycladesRestClient, Waiter):
ATTENTION: Empty list is different to None. None means ' do not
mention it', empty list means 'automatically get an ip'
:param project: the project where to assign the server
:returns: a dict with the new virtual server details
:raises ClientError: wraps request errors
......@@ -78,7 +80,8 @@ class CycladesClient(CycladesRestClient, Waiter):
return super(CycladesClient, self).create_server(
name, flavor_id, image_id,
metadata=metadata, personality=personality, networks=networks)
metadata=metadata, personality=personality, networks=networks,
project=project)
def set_firewall_profile(self, server_id, profile, port_id):
"""Set the firewall profile for the public interface of a server
......@@ -123,6 +126,11 @@ class CycladesClient(CycladesRestClient, Waiter):
r = self.servers_action_post(server_id, json_data=req, success=200)
return r.json['console']
def reassign_server(self, server_id, project):
req = {'reassign': {'project': project}}
r = self.servers_action_post(server_id, json_data=req, success=200)
return r.headers
def get_server_stats(self, server_id):
"""
:param server_id: integer (str or int)
......@@ -180,15 +188,35 @@ class CycladesNetworkClient(NetworkClient):
r = self.get(path, success=200)
return r.json['networks']
def create_network(self, type, name=None, shared=None):
def create_network(self, type, name=None, shared=None, project=None):
req = dict(network=dict(type=type, admin_state_up=True))
if name:
req['network']['name'] = name
if shared not in (None, ):
req['network']['shared'] = bool(shared)
if project is not None:
req['network']['project'] = project
r = self.networks_post(json_data=req, success=201)
return r.json['network']
def networks_action_post(
self, network_id='', json_data=None, success=202, **kwargs):
"""POST base_url/networks/<network_id>/action
:returns: request response
"""
if json_data:
json_data = json.dumps(json_data)
self.set_header('Content-Type', 'application/json')
self.set_header('Content-Length', len(json_data))
path = path4url('networks', network_id, 'action')
return self.post(path, data=json_data, success=success, **kwargs)
def reassign_network(self, network_id, project):
req = {'reassign': {'project': project}}
r = self.networks_action_post(network_id, json_data=req, success=200)
return r.headers
def list_ports(self, detail=None):
path = path4url('ports', 'detail' if detail else '')
r = self.get(path, success=200)
......@@ -216,18 +244,27 @@ class CycladesNetworkClient(NetworkClient):
return r.json['port']
def create_floatingip(
self, floating_network_id=None, floating_ip_address=''):
self,
floating_network_id=None, floating_ip_address='', project_id=None):
"""
:param floating_network_id: if not provided, it is assigned
automatically by the service
:param floating_ip_address: only if the IP is availabel in network
pool
:param floating_ip_address: only if the IP is availabel in network pool
:param project_id: specific project to get resource quotas from
"""
floatingip = {}
if floating_network_id:
floatingip['floating_network_id'] = floating_network_id
if floating_ip_address:
floatingip['floating_ip_address'] = floating_ip_address
if project_id:
floatingip['project'] = project_id
r = self.floatingips_post(
json_data=dict(floatingip=floatingip), success=200)
return r.json['floatingip']
def reassign_floating_ip(self, floating_network_id, project_id):
"""Change the project where this ip is charged"""
path = path4url('floatingips', floating_network_id, 'action')
json_data = dict(reassign=dict(project=project_id))
self.post(path, json=json_data, success=202)
......@@ -331,7 +331,8 @@ class NetworkClient(NetworkRestClient, Waiter):
def create_floatingip(
self, floating_network_id,
floating_ip_address='', port_id='', fixed_ip_address=''):
floating_ip_address='', port_id='', fixed_ip_address='',
args=None):
"""Cyclades do not use port_id and fixed_ip_address"""
floatingip = dict(floating_network_id=floating_network_id)
if floating_ip_address:
......@@ -340,6 +341,8 @@ class NetworkClient(NetworkRestClient, Waiter):
floatingip['port_id'] = port_id
if fixed_ip_address:
floatingip['fixed_ip_address'] = fixed_ip_address
if args is not None:
floatingip.update(args)
r = self.floatingips_post(
json_data=dict(floatingip=floatingip), success=200)
return r.json['floatingip']
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment