class subnet_create(_NetworkInit, OptionalOutput): """Create a new subnet""" arguments = dict( name=ValueArgument('Subnet name', '--name'), allocation_pools=AllocationPoolArgument( 'start_address,end_address of allocation pool (can be repeated)' ' e.g., --alloc-pool=123.45.67.1,123.45.67.8', '--alloc-pool'), gateway=ValueArgument('Gateway IP', '--gateway'), subnet_id=ValueArgument('The id for the subnet', '--id'), ipv6=FlagArgument('If set, IP version is set to 6, else 4', '--ipv6'), enable_dhcp=FlagArgument('Enable dhcp (default: off)', '--with-dhcp'), network_id=ValueArgument('Set the network ID', '--network-id'), cidr=ValueArgument('Set the CIDR', '--cidr')) required = ('network_id', 'cidr') @errors.Generic.all @errors.Cyclades.connection def _run(self): try: net = self.client.create_subnet(self['network_id'], self['cidr'], self['name'], self['allocation_pools'], self['gateway'], self['subnet_id'], self['ipv6'], self['enable_dhcp']) except ClientError as ce: if ce.status in (404, 400): self._network_exists(network_id=self['network_id']) raise self.print_(net, self.print_dict) def main(self): super(self.__class__, self)._run() self._run()
class network_create(_NetworkInit, OptionalOutput): """Create a new network (default type: MAC_FILTERED)""" arguments = dict( name=ValueArgument('Network name', '--name'), shared=FlagArgument( 'Make network shared (special privileges required)', '--shared'), project_id=ValueArgument('Assign network to project', '--project-id'), network_type=NetworkTypeArgument( 'Valid network types: %s' % (', '.join(NetworkTypeArgument.types)), '--type')) @errors.Generic.all @errors.Cyclades.connection def _run(self): try: net = self.client.create_network(self['network_type'], name=self['name'], shared=self['shared'], project_id=self['project_id']) except ClientError as ce: if self['project_id'] and ce.status in (400, 403, 404): self._project_id_exists(project_id=self['project_id']) raise self.print_(net, self.print_dict) def main(self): super(self.__class__, self)._run() self._run()
class IDFilter(object): if_arguments = dict( id=ValueArgument('filter by id', '--id'), id_pref=ValueArgument('filter by id prefix (case insensitive)', '--id-prefix'), id_suff=ValueArgument('filter by id suffix (case insensitive)', '--id-suffix'), id_like=ValueArgument( 'print only if id contains this (case insensitive)', '--id-like')) def _non_exact_id_filter(self, items): np, ns, nl = self['id_pref'], self['id_suff'], self['id_like'] return [ item for item in items if ((not np) or ('%s' % item['id']).lower().startswith(np.lower())) and ((not ns) or ('%s' % item['id']).lower().endswith(ns.lower())) and ((not nl) or nl.lower() in ('%s' % item['id']).lower()) ] def _exact_id_filter(self, items): return filter_dicts_by_dict(items, dict( id=self['id'])) if (self['id']) else items def _filter_by_id(self, items): return self._non_exact_id_filter(self._exact_id_filter(items))
class NameFilter(object): nf_arguments = dict( name=ValueArgument('filter by name', '--name'), name_pref=ValueArgument('filter by name prefix (case insensitive)', '--name-prefix'), name_suff=ValueArgument('filter by name suffix (case insensitive)', '--name-suffix'), name_like=ValueArgument( 'print only if name contains this (case insensitive)', '--name-like')) def _non_exact_name_filter(self, items): np, ns, nl = self['name_pref'], self['name_suff'], self['name_like'] return [ item for item in items if ((not np) or (item['name'] or '').lower().startswith(np.lower()) ) and ((not ns) or ( item['name'] or '').lower().endswith(ns.lower())) and ( (not nl) or nl.lower() in (item['name'] or '').lower()) ] def _exact_name_filter(self, items): return filter_dicts_by_dict(items, dict( name=self['name'] or '')) if (self['name']) else items def _filter_by_name(self, items): return self._non_exact_name_filter(self._exact_name_filter(items))
class project_list(_AstakosInit, OptionalOutput): """List all projects""" arguments = dict( details=FlagArgument('Show details', ('-l', '--details')), name=ValueArgument('Filter by name', ('--with-name', )), state=ValueArgument('Filter by state', ('--with-state', )), owner=ValueArgument('Filter by owner', ('--with-owner', )), ) @errors.Generic.all @errors.Astakos.astakosclient def _run(self): r = self.client.get_projects(self['name'], self['state'], self['owner']) if not (self['details'] or self['output_format']): r = [ dict(id=i['id'], name=i['name'], description=i['description']) for i in r ] self.print_(r) def main(self): super(self.__class__, self)._run() self._run()
class commission_issue(_AstakosInit, OptionalOutput): """Issue commissions as a json string (special privileges required)""" arguments = dict(uuid=ValueArgument('User UUID', '--uuid'), source=ValueArgument('Commission source (ex system)', '--source'), file_path=ValueArgument('File of provisions', '--provisions-file'), description=ValueArgument('Commision description', '--description'), force=FlagArgument('Force commission', '--force'), accept=FlagArgument('Do not wait for verification', '--accept')) required = ('uuid', 'source', 'file_path') @errors.Generic.all @errors.Astakos.astakosclient def _run(self): try: with open(self['file_path']) as f: provisions = loads(f.read()) except Exception as e: raise CLIError('Failed load a json dict from file %s' % self['file_path'], importance=2, details=['%s' % e]) self.print_( self.client.issue_one_commission(self['uuid'], self['source'], provisions, self['description'] or '', self['force'], self['accept'])) def main(self): super(self.__class__, self)._run() self._run()
class port_create(_port_create): """Create a new port (== connect server to network)""" arguments = dict( name=ValueArgument('A human readable name', '--name'), security_group_id=RepeatableArgument( 'Add a security group id (can be repeated)', ('-g', '--security-group')), subnet_id=ValueArgument( 'Subnet id for fixed ips (used with --ip-address)', '--subnet-id'), ip_address=ValueArgument('IP address for subnet id', '--ip-address'), network_id=ValueArgument('Set the network ID', '--network-id'), device_id=ValueArgument( 'The device is either a virtual server or a virtual router', '--device-id'), wait=FlagArgument('Wait port to be established', ('-w', '--wait')), ) required = ('network_id', 'device_id') @errors.Generic.all @errors.Cyclades.connection def _run(self): self.connect(self['network_id'], self['device_id']) def main(self): super(self.__class__, self)._run() self._run()
def _run(self, ip_or_ip_id): netid = None for ip in self.client.list_floatingips(): if ip_or_ip_id in (ip['floating_ip_address'], ip['id']): netid = ip['floating_network_id'] iparg = ValueArgument(parsed_name='--ip') iparg.value = ip['floating_ip_address'] self.arguments['ip_address'] = iparg break if netid: server_id = self['server_id'] self.error('Creating a port to attach IP %s to server %s' % ( ip_or_ip_id, server_id)) try: self.connect(netid, server_id) except ClientError as ce: self.error('Failed to connect network %s with server %s' % ( netid, server_id)) if ce.status in (400, 404): self._server_exists(server_id=server_id) self._network_exists(network_id=netid) raise else: raiseCLIError( '%s does not match any reserved IPs or IP ids' % ip_or_ip_id, details=errors.Cyclades.about_ips)
class server_detach(_CycladesInit): """Detach a volume from a VM""" arguments = dict( attachment_id=ValueArgument( 'The volume attachment (mutually exclusive to --volume-id)', '--attachment-id', ), volume_id=ValueArgument( 'Volume to detach from VM (mutually exclusive to --attachment-id)', '--volume-id') ) required = ['attachment_id', 'volume_id'] @errors.Generic.all @errors.Cyclades.connection @errors.Cyclades.server_id @errors.Cyclades.endpoint def _run(self, server_id): att_id = self['attachment_id'] if att_id: self.client.delete_volume_attachment(server_id, att_id) else: r = self.client.detach_volume(server_id, self['volume_id']) self.error('%s detachment%s deleted, volume is detached' % ( len(r), '' if len(r) == 1 else 's')) self.error('OK') def main(self, server_id): super(self.__class__, self)._run() if all([self['attachment_id'], self['volume_id']]): raise CLISyntaxError('Invalid argument compination', details=[ '%s and %s are mutually exclusive' % ( self.arguments['attachment_id'].lvalue, self.arguments['volume_id'].lvalue)]) self._run(server_id=server_id)
class network_connect(_port_create): """Connect a network with a device (server or router)""" arguments = dict( name=ValueArgument('A human readable name for the port', '--name'), security_group_id=RepeatableArgument( 'Add a security group id (can be repeated)', ('-g', '--security-group')), subnet_id=ValueArgument( 'Subnet id for fixed ips (used with --ip-address)', '--subnet-id'), ip_address=ValueArgument( 'IP address for subnet id (used with --subnet-id', '--ip-address'), wait=FlagArgument('Wait network to connect', ('-w', '--wait')), device_id=RepeatableArgument( 'Connect this device to the network (can be repeated)', '--device-id')) required = ('device_id', ) @errors.Generic.all @errors.Cyclades.connection @errors.Cyclades.network_id def _run(self, network_id, server_id): self.error('Creating a port to connect network %s with device %s' % (network_id, server_id)) try: self.connect(network_id, server_id) except ClientError as ce: if ce.status in (400, 404): self._server_exists(server_id=server_id) raise def main(self, network_id): super(self.__class__, self)._run() for sid in self['device_id']: self._run(network_id=network_id, server_id=sid)
def _run(self, ip_or_ip_id): netid = None for ip in self.client.list_floatingips(): if ip_or_ip_id in (ip['floating_ip_address'], ip['id']): netid = ip['floating_network_id'] iparg = ValueArgument(parsed_name='--ip') iparg.value = ip['floating_ip_address'] self.arguments['ip_address'] = iparg break if netid: server_id = self['server_id'] self.error('Creating a port to attach IP %s to server %s' % (ip_or_ip_id, server_id)) try: self.connect(netid, server_id) except ClientError as ce: self.error('Failed to connect network %s with server %s' % (netid, server_id)) if ce.status in (400, 404): self._server_exists(server_id=server_id) self._network_exists(network_id=netid) raise else: raiseCLIError('%s does not match any reserved IPs or IP ids' % ip_or_ip_id, details=errors.Cyclades.about_ips)
class user_info(_AstakosInit, OptionalOutput): """Get info for (current) session user""" arguments = dict(uuid=ValueArgument('Query user with uuid', '--uuid'), name=ValueArgument('Query user with username/email', '--username')) @errors.Generic.all @errors.Astakos.astakosclient def _run(self): if self['uuid'] and self['name']: raise CLISyntaxError( 'Arguments uuid and username are mutually exclusive', details=['Use either uuid OR username OR none, but NOT both']) uuid = self['uuid'] or (self._username2uuid(self['name']) if (self['name']) else None) try: if any([self['uuid'], self['name']]) and not uuid: raise KeyError() token = self.astakos.get_token(uuid) if uuid else None except KeyError: msg = ('id %s' % self['uuid']) if ( self['uuid']) else 'username %s' % self['name'] raise CLIError( 'No user with %s in the cached session list' % msg, details=[ 'To see all cached session users:', ' kamaki user list', 'To authenticate and add a new user in the session list:', ' kamaki user add NEW_TOKEN' ]) self.print_(self.astakos.user_info(token), self.print_dict) def main(self): super(self.__class__, self)._run() self._run()
class ip_create(_NetworkInit, OptionalOutput): """Reserve an IP on a network""" arguments = dict( network_id=ValueArgument('The network to preserve the IP on', '--network-id'), ip_address=ValueArgument('Allocate an IP address', '--address'), project_id=ValueArgument('Assign the IP to project', '--project-id'), ) @errors.Generic.all @errors.Cyclades.connection def _run(self): try: self.print_( self.client.create_floatingip( self['network_id'], floating_ip_address=self['ip_address'], project_id=self['project_id']), self.print_dict) except ClientError as ce: if ce.status in (400, 404): network_id, ip = self['network_id'], self['ip_address'] self._network_exists(network_id=network_id) if ip: self._ip_exists(ip, network_id, ce) if self['project_id'] and ce.status in (400, 403, 404): self._project_id_exists(project_id=self['project_id']) raise def main(self): super(self.__class__, self)._run() self._run()
class flavor_list(_CycladesInit, OptionalOutput, NameFilter, IDFilter): """List available hardware flavors""" arguments = dict( detail=FlagArgument('show detailed output', ('-l', '--details')), limit=IntArgument('limit # of listed flavors', ('-n', '--number')), more=FlagArgument( 'output results in pages (-n to set items per page, default 10)', '--more'), enum=FlagArgument('Enumerate results', '--enumerate'), ram=ValueArgument('filter by ram', ('--ram')), vcpus=ValueArgument('filter by number of VCPUs', ('--vcpus')), disk=ValueArgument('filter by disk size in GB', ('--disk')), disk_template=ValueArgument( 'filter by disk_templace', ('--disk-template')), project_id=ValueArgument('filter by project ID', '--project'), is_public=FlagArgument('list only public flavors', '--public'), ) def _apply_common_filters(self, flavors): common_filters = dict() if self['ram']: common_filters['ram'] = self['ram'] if self['vcpus']: common_filters['vcpus'] = self['vcpus'] if self['disk']: common_filters['disk'] = self['disk'] if self['disk_template']: common_filters['SNF:disk_template'] = self['disk_template'] return filter_dicts_by_dict(flavors, common_filters) @errors.Generic.all @errors.Cyclades.connection def _run(self): withcommons = self['ram'] or self['vcpus'] or ( self['disk'] or self['disk_template']) detail = self['detail'] or withcommons flavors = self.client.list_flavors( detail, is_public=self['is_public'], project_id=self['project_id']) flavors = self._filter_by_name(flavors) flavors = self._filter_by_id(flavors) if withcommons: flavors = self._apply_common_filters(flavors) if not (self['detail'] or self['output_format']): remove_from_items(flavors, 'links') if detail and not self['detail']: for flv in flavors: for key in set(flv).difference(['id', 'name']): flv.pop(key) kwargs = dict(out=StringIO(), title=()) if self['more'] else {} self.print_(flavors, with_enumeration=self['enum'], **kwargs) if self['more']: pager(kwargs['out'].getvalue()) def main(self): super(self.__class__, self)._run() self._run()
class image_modify(_ImageInit): """Add / update metadata and properties for an image Preserves values not explicitly modified """ arguments = dict( image_name=ValueArgument('Change name', '--name'), disk_format=ValueArgument('Change disk format', '--disk-format'), container_format=ValueArgument('Change container format', '--container-format'), status=ValueArgument('Change status', '--status'), publish=FlagArgument('Make the image public', '--public'), unpublish=FlagArgument('Make the image private', '--private'), property_to_set=KeyValueArgument( 'set property in key=value form (can be repeated)', ('-p', '--property-set')), property_to_del=RepeatableArgument( 'Delete property by key (can be repeated)', '--property-del'), member_ID_to_add=RepeatableArgument( 'Add member to image (can be repeated)', '--member-add'), member_ID_to_remove=RepeatableArgument( 'Remove a member (can be repeated)', '--member-del'), ) required = [ 'image_name', 'disk_format', 'container_format', 'status', 'publish', 'unpublish', 'property_to_set', 'member_ID_to_add', 'member_ID_to_remove', 'property_to_del' ] @errors.Generic.all @errors.Image.connection @errors.Image.permissions @errors.Image.id def _run(self, image_id): for mid in (self['member_ID_to_add'] or []): self.client.add_member(image_id, mid) for mid in (self['member_ID_to_remove'] or []): self.client.remove_member(image_id, mid) meta = self.client.get_meta(image_id) for k, v in self['property_to_set'].items(): meta['properties'][k.upper()] = v for k in (self['property_to_del'] or []): meta['properties'][k.upper()] = None self.client.update_image(image_id, name=self['image_name'], disk_format=self['disk_format'], container_format=self['container_format'], status=self['status'], public=self['publish'] or (False if self['unpublish'] else None), **meta['properties']) def main(self, image_id): super(self.__class__, self)._run() self._run(image_id=image_id)
class keypair_upload(_CycladesInit, OptionalOutput): """Upload or update a keypair""" arguments = dict( key_name=ValueArgument( 'The name of the key', '--key-name'), public_key=ValueArgument( 'The contents of the keypair(the public key)', '--public-key'), force=FlagArgument( '(DANGEROUS) Force keypair creation. This option' ' will delete an existing keypair in case of a name' 'conflict. Do not use it if unsure.', ('-f', '--force') ) ) required = ['public_key'] @errors.Generic.all @errors.Keypair.connection def _run(self): key_name = self['key_name'] if key_name is None: uniq = str(uuid.uuid4())[:8] key_name = 'kamaki-key_autogen_{:%m_%d_%H_%M_%S_%f}_{uniq}'.format( datetime.now(), uniq=uniq) try: keypair = self.client.create_key( key_name=key_name, public_key=self['public_key']) except ClientError as e: if e.status == 409 and self['force']: self.client.delete_keypair(key_name) keypair = self.client.create_key( key_name=key_name, public_key=self['public_key']) else: help_command = ('kamaki keypair upload -f --key-name %s ' '--public-key %s' % (key_name, self['public_key'])) self._err.write('A keypair with that name already exists. ' 'To override the conflicting key you can use ' 'the following command:\n%s\n' % (help_command)) raise e self.print_(keypair, self.print_dict) def main(self): super(self.__class__, self)._run() self._run()
class quota_list(_AstakosInit, OptionalOutput): """Show user quotas""" _to_format = set(['cyclades.disk', 'pithos.diskspace', 'cyclades.ram']) arguments = dict(resource=ValueArgument('Filter by resource', '--resource'), project_id=ValueArgument('Filter by project', '--project-id'), bytes=FlagArgument('Show data size in bytes', '--bytes')) def _print_quotas(self, quotas, *args, **kwargs): if not self['bytes']: for project_id, resources in quotas.items(): for r in self._to_format.intersection(resources): resources[r] = dict([(k, format_size(v)) for k, v in resources[r].items()]) self.print_dict(quotas, *args, **kwargs) @errors.Generic.all @errors.Astakos.astakosclient def _run(self): quotas = self.client.get_quotas() if self['project_id']: try: resources = quotas[self['project_id']] except KeyError: raise CLIError('User not assigned to project with id "%s" ' % (self['project_id']), details=[ 'See all quotas of current user:'******' kamaki quota list' ]) quotas = {self['project_id']: resources} if self['resource']: d = dict() for project_id, resources in quotas.items(): r = dict() for resource, value in resources.items(): if (resource.startswith(self['resource'])): r[resource] = value if r: d[project_id] = r if not d: raise CLIError('Resource "%s" not found' % self['resource']) quotas = d self.print_(quotas, self._print_quotas) def main(self): super(self.__class__, self)._run() self._run()
class server_reboot(_CycladesInit, _ServerWait): """Reboot a virtual server""" arguments = dict( type=ValueArgument('SOFT or HARD - default: SOFT', ('--type')), wait=FlagArgument('Wait server to start again', ('-w', '--wait')) ) @errors.Generic.all @errors.Cyclades.connection @errors.Cyclades.server_id def _run(self, server_id): hard_reboot = None if self['type']: if self['type'].lower() in ('soft', ): hard_reboot = False elif self['type'].lower() in ('hard', ): hard_reboot = True else: raise CLISyntaxError( 'Invalid reboot type %s' % self['type'], importance=2, details=[ '--type values are either SOFT (default) or HARD']) self.client.reboot_server(int(server_id), hard_reboot) if self['wait']: self.wait_while(server_id, 'REBOOT') def main(self, server_id): super(self.__class__, self)._run() self._run(server_id=server_id)
class port_list(_NetworkInit, OptionalOutput, NameFilter, IDFilter): """List all ports""" arguments = dict(detail=FlagArgument('show detailed output', ('-l', '--details')), more=FlagArgument('output results in pages', '--more'), user_id=ValueArgument( 'show only networks belonging to user with this id', '--user-id')) @errors.Generic.all @errors.Cyclades.connection def _run(self): ports = self.client.list_ports() ports = self._filter_by_user_id(ports) ports = self._filter_by_name(ports) ports = self._filter_by_id(ports) if not self['detail']: ports = [dict(id=p['id'], name=p['name']) for p in ports] kwargs = dict() if self['more']: kwargs['out'] = StringIO() kwargs['title'] = () self.print_(ports, **kwargs) if self['more']: pager(kwargs['out'].getvalue()) def main(self): super(self.__class__, self)._run() self._run()
class history_show(_HistoryInit): """Show history Featutes: - slice notation (cmd numbers --> N or :N or N: or N1:N2) - text matching (--match) """ arguments = dict(match=ValueArgument('Show lines matching this', '--match'), ) @errors.Generic.all def _run(self, cmd_slice): c = self.history.counter lines = [ '%s. %s' % (i + c, l) for i, l in enumerate(self.history[:]) ][cmd_slice] if not isinstance(cmd_slice, slice): lines = [ lines, ] if self['match']: lines = [l for l in lines if self.history._match(l, self['match'])] self.print_items([l[:-1] for l in lines]) def main(self, cmd_numbers=''): super(self.__class__, self)._run() sl_args = [int(x) if x else None for x in cmd_numbers.split(':') ] if (cmd_numbers) else [None, None] slice_cmds = slice(*sl_args) if len(sl_args) > 1 else sl_args[0] self._run(slice_cmds)
class user_add(_AstakosInit, OptionalOutput): """Authenticate a user by token and add to session user list (cache)""" arguments = dict(token=ValueArgument('Token of user to add', '--token'), ) required = ('token', ) @errors.Generic.all @errors.Astakos.astakosclient def _run(self): ask = self['token'] and self['token'] not in self.astakos._uuids try: self.print_(self.astakos.authenticate(self['token']), self.print_dict) except ClientError as ce: if ce.status in (401, ): raise CLIError('Token %s was not authenticated' % self['token'], details=['%s' % ce]) if ask and self.ask_user( 'Token is temporarily stored in memory. Append it in ' 'configuration file as an alternative token?'): tokens = self.astakos._uuids.keys() tokens.remove(self.astakos.token) self['config'].set_cloud(self.cloud, 'token', ' '.join([self.astakos.token] + tokens)) self['config'].write() def main(self): super(self.__class__, self)._run() self._run()
class ip_attach(_port_create): """Attach an IP on a virtual server""" arguments = dict(name=ValueArgument('A human readable name for the port', '--name'), security_group_id=RepeatableArgument( 'Add a security group id (can be repeated)', ('-g', '--security-group')), subnet_id=ValueArgument('Subnet id', '--subnet-id'), wait=FlagArgument('Wait IP to be attached', ('-w', '--wait')), server_id=ValueArgument('Server to attach to this IP', '--server-id')) required = ('server_id', ) @errors.Generic.all @errors.Cyclades.connection def _run(self, ip_or_ip_id): netid = None for ip in self.client.list_floatingips(): if ip_or_ip_id in (ip['floating_ip_address'], ip['id']): netid = ip['floating_network_id'] iparg = ValueArgument(parsed_name='--ip') iparg.value = ip['floating_ip_address'] self.arguments['ip_address'] = iparg break if netid: server_id = self['server_id'] self.error('Creating a port to attach IP %s to server %s' % (ip_or_ip_id, server_id)) try: self.connect(netid, server_id) except ClientError as ce: self.error('Failed to connect network %s with server %s' % (netid, server_id)) if ce.status in (400, 404): self._server_exists(server_id=server_id) self._network_exists(network_id=netid) raise else: raiseCLIError('%s does not match any reserved IPs or IP ids' % ip_or_ip_id, details=errors.Cyclades.about_ips) def main(self, ip_or_ip_id): super(self.__class__, self)._run() self._run(ip_or_ip_id=ip_or_ip_id)
class service_quotas(_AstakosInit, OptionalOutput): """Get service quotas""" arguments = dict(service_token=ValueArgument('Authenticate service', '--service-token'), uuid=ValueArgument('A user uuid to get quotas for', '--uuid')) required = ('service_token') @errors.Generic.all @errors.Astakos.astakosclient @with_temp_token def _run(self): self.print_(self.client.service_get_quotas(self['uuid'])) def main(self): super(self.__class__, self)._run() self._run(token=self['service_token'])
class _ApplicationAction(_AstakosInit): action = '' arguments = dict( app_id=ValueArgument('The application ID', '--app-id'), reason=ValueArgument('Quote a reason for this action', '--reason'), ) required = ('app_id', ) @errors.Generic.all @errors.Astakos.astakosclient @errors.Astakos.project_id def _run(self, project_id): self.client.application_action(project_id, self['app_id'], self.action, self['reason'] or '') def main(self, project_id): super(_ApplicationAction, self)._run() self._run(project_id=project_id)
def _run(self, ip_or_ip_id, server_id): netid = None for ip in self.client.list_floatingips(): if ip_or_ip_id in (ip['floating_ip_address'], ip['id']): netid = ip['floating_network_id'] iparg = ValueArgument(parsed_name='--ip') iparg.value = ip['floating_ip_address'] self.arguments['ip_address'] = iparg break if netid: self.error('Creating a port to attach IP %s to server %s' % ( ip_or_ip_id, server_id)) self.connect(netid, server_id) else: raiseCLIError( '%s does not match any reserved IPs or IP ids' % ip_or_ip_id, details=[ 'To reserve an IP:', ' [kamaki] ip create', 'To see all reserved IPs:', ' [kamaki] ip list'])
class _MembershipAction(_AstakosInit, OptionalOutput): action = '' arguments = dict(reason=ValueArgument('Reason for the action', '--reason')) @errors.Generic.all @errors.Astakos.astakosclient @errors.Astakos.membership_id def _run(self, membership_id): self.print_(self.client.membership_action( membership_id, self.action, self['reason'] or '')) def main(self, membership_id): super(_MembershipAction, self)._run() self._run(membership_id=membership_id)
class project_enroll(_AstakosInit): """Enroll a user to a project""" arguments = dict(email=ValueArgument('User e-mail', '--email')) required = ('email', ) @errors.Generic.all @errors.Astakos.astakosclient @errors.Astakos.project_id def _run(self, project_id): self.writeln(self.client.enroll_member(project_id, self['email'])) def main(self, project_id): super(project_enroll, self)._run() self._run(project_id=project_id)
class membership_list(_AstakosInit, OptionalOutput): """List all memberships""" arguments = dict( project_id=ValueArgument('Filter by project id', '--project-id')) @errors.Generic.all @errors.Astakos.astakosclient @errors.Astakos.project_id def _run(self, project_id): self.print_(self.client.get_memberships(project_id)) def main(self): super(self.__class__, self)._run() self._run(project_id=self['project_id'])
class _ProjectAction(_AstakosInit): action = '' arguments = dict(reason=ValueArgument('Quote a reason for this action', '--reason'), ) @errors.Generic.all @errors.Astakos.astakosclient @errors.Astakos.project_id def _run(self, project_id): self.client.project_action(project_id, self.action, self['reason'] or '') def main(self, project_id): super(_ProjectAction, self)._run() self._run(project_id=project_id)
class endpoint_list(_AstakosInit, OptionalOutput, NameFilter): """Get endpoints service endpoints""" arguments = dict(endpoint_type=ValueArgument('Filter by type', '--type')) @errors.Generic.all @errors.Astakos.astakosclient def _run(self): r = self.client.get_endpoints()['access']['serviceCatalog'] r = self._filter_by_name(r) if self['endpoint_type']: r = filter_dicts_by_dict(r, dict(type=self['endpoint_type'])) self.print_(r) def main(self): super(self.__class__, self)._run() self._run()
class subnet_modify(_NetworkInit, OptionalOutput): """Modify the attributes of a subnet""" arguments = dict( new_name=ValueArgument('New name of the subnet', '--name')) required = ['new_name'] @errors.Generic.all @errors.Cyclades.connection @errors.Cyclades.subnet_permissions @errors.Cyclades.subnet_id def _run(self, subnet_id): r = self.client.update_subnet(subnet_id, name=self['new_name']) self.print_(r, self.print_dict) def main(self, subnet_id): super(self.__class__, self)._run() self._run(subnet_id=subnet_id)
class server_attach(_CycladesInit, OptionalOutput): """Attach a volume on a VM""" arguments = dict( volume_id=ValueArgument('The volume to be attached', '--volume-id') ) required = ('volume_id', ) @errors.Generic.all @errors.Cyclades.connection @errors.Cyclades.server_id @errors.Cyclades.endpoint def _run(self, server_id): r = self.client.attach_volume(server_id, self['volume_id']) self.print_(r, self.print_dict) def main(self, server_id): super(self.__class__, self)._run() self._run(server_id=server_id)