def connect_floatingip(nova_client, fixed_ip, **kwargs): server_id = ctx.source.instance.runtime_properties[OPENSTACK_ID_PROPERTY] floating_ip_id = ctx.target.instance.runtime_properties[ OPENSTACK_ID_PROPERTY] if is_external_relationship(ctx): ctx.logger.info('Validating external floatingip and server ' 'are associated') if nova_client.floating_ips.get(floating_ip_id).instance_id ==\ server_id: return raise NonRecoverableError( 'Expected external resources server {0} and floating-ip {1} to be ' 'connected'.format(server_id, floating_ip_id)) floating_ip_address = ctx.target.instance.runtime_properties[ IP_ADDRESS_PROPERTY] server = nova_client.servers.get(server_id) server.add_floating_ip(floating_ip_address, fixed_ip or None) server = nova_client.servers.get(server_id) all_server_ips = reduce(operator.add, server.networks.values()) if floating_ip_address not in all_server_ips: return ctx.operation.retry( message='Failed to assign floating ip {0} to machine {1}.' .format(floating_ip_address, server_id))
def connect_security_group(nova_client, **kwargs): server_id = ctx.source.instance.runtime_properties[OPENSTACK_ID_PROPERTY] security_group_id = ctx.target.instance.runtime_properties[ OPENSTACK_ID_PROPERTY] security_group_name = ctx.target.instance.runtime_properties[ OPENSTACK_NAME_PROPERTY] if is_external_relationship(ctx): ctx.logger.info('Validating external security group and server ' 'are associated') server = nova_client.servers.get(server_id) if [sg for sg in server.list_security_group() if sg.id == security_group_id]: return raise NonRecoverableError( 'Expected external resources server {0} and security-group {1} to ' 'be connected'.format(server_id, security_group_id)) server = nova_client.servers.get(server_id) # to support nova security groups as well, we connect the security group # by name (as connecting by id doesn't seem to work well for nova SGs) server.add_security_group(security_group_name) _validate_security_group_and_server_connection_status(nova_client, server_id, security_group_id, security_group_name, is_connected=True)
def detach(neutron_client, **kwargs): if is_external_relationship(ctx): ctx.logger.info('Not detaching port from server since ' 'external port and server are being used') return port_id = ctx.target.instance.runtime_properties[OPENSTACK_ID_PROPERTY] server_id = ctx.source.instance.runtime_properties[OPENSTACK_ID_PROPERTY] server_floating_ip = _get_server_floating_ip(neutron_client, server_id) if server_floating_ip: return ctx.operation.retry( message='Waiting for the floating ip {0} to ' 'detach from server {1}..' .format(server_floating_ip['floating_ip_address'], server_id), retry_after=10) change = { 'port': { 'device_id': '', 'device_owner': '' } } ctx.logger.info('Detaching port {0}...'.format(port_id)) neutron_client.update_port(port_id, change) ctx.logger.info('Successfully detached port {0}'.format(port_id))
def disconnect_security_group(nova_client, **kwargs): if is_external_relationship(ctx): ctx.logger.info('Not disconnecting security group and server since ' 'external security group and server are being used') return server_id = ctx.source.instance.runtime_properties[OPENSTACK_ID_PROPERTY] security_group_id = ctx.target.instance.runtime_properties[ OPENSTACK_ID_PROPERTY] security_group_name = ctx.target.instance.runtime_properties[ OPENSTACK_NAME_PROPERTY] server = nova_client.servers.get(server_id) # to support nova security groups as well, we disconnect the security group # by name (as disconnecting by id doesn't seem to work well for nova SGs) try: server.remove_security_group(security_group_name) except nova_exceptions.NotFound: ctx.logger.warn("Security group '{0}' (id: {1}) is not attached " "to server instance {2}; skipping" .format(security_group_name, security_group_id, server_id)) else: _validate_security_group_and_server_connection_status( nova_client, server_id, security_group_id, security_group_name, is_connected=False)
def detach(nova_client, neutron_client, **kwargs): if is_external_relationship(ctx): ctx.logger.info('Not detaching port from server since ' 'external port and server are being used') return port_id = get_openstack_id(ctx.target) server_id = get_openstack_id(ctx.source) server_floating_ip = get_server_floating_ip(neutron_client, server_id) if server_floating_ip: ctx.logger.info('We have floating ip {0} attached to server'.format( server_floating_ip['floating_ip_address'])) server = nova_client.servers.get(server_id) server.remove_floating_ip(server_floating_ip['floating_ip_address']) return ctx.operation.retry( message='Waiting for the floating ip {0} to ' 'detach from server {1}..'.format( server_floating_ip['floating_ip_address'], server_id), retry_after=10) change = {PORT_OPENSTACK_TYPE: {'device_id': '', 'device_owner': ''}} ctx.logger.info('Detaching port {0}...'.format(port_id)) neutron_client.update_port(port_id, change) ctx.logger.info('Successfully detached port {0}'.format(port_id))
def connect_security_group(nova_client, **kwargs): server_id = ctx.source.instance.runtime_properties[OPENSTACK_ID_PROPERTY] security_group_id = ctx.target.instance.runtime_properties[ OPENSTACK_ID_PROPERTY] security_group_name = ctx.target.instance.runtime_properties[ OPENSTACK_NAME_PROPERTY] if is_external_relationship(ctx): ctx.logger.info('Validating external security group and server ' 'are associated') server = nova_client.servers.get(server_id) if [ sg for sg in server.list_security_group() if sg.id == security_group_id ]: return raise NonRecoverableError( 'Expected external resources server {0} and security-group {1} to ' 'be connected'.format(server_id, security_group_id)) server = nova_client.servers.get(server_id) # to support nova security groups as well, we connect the security group # by name (as connecting by id doesn't seem to work well for nova SGs) server.add_security_group(security_group_name) _validate_security_group_and_server_connection_status(nova_client, server_id, security_group_id, security_group_name, is_connected=True)
def attach_volume(nova_client, cinder_client, **kwargs): server_id = ctx.source.instance.runtime_properties[OPENSTACK_ID_PROPERTY] volume_id = ctx.target.instance.runtime_properties[OPENSTACK_ID_PROPERTY] if is_external_relationship(ctx): ctx.logger.info('Validating external volume and server ' 'are connected') attachment = volume.get_attachment(cinder_client=cinder_client, volume_id=volume_id, server_id=server_id) if attachment: return else: raise NonRecoverableError( 'Expected external resources server {0} and volume {1} to be ' 'connected'.format(server_id, volume_id)) # Note: The 'device_name' property should actually be a property of the # relationship between a server and a volume; It'll move to that # relationship type once relationship properties are better supported. device = ctx.target.node.properties[volume.DEVICE_NAME_PROPERTY] nova_client.volumes.create_server_volume(server_id, volume_id, device) volume.wait_until_status(cinder_client=cinder_client, volume_id=volume_id, status=volume.VOLUME_STATUS_IN_USE)
def connect_port(neutron_client, **kwargs): if is_external_relationship(ctx): return port_id = ctx.source.instance.runtime_properties[OPENSTACK_ID_PROPERTY] floating_ip_id = ctx.target.instance.runtime_properties[ OPENSTACK_ID_PROPERTY] fip = {'port_id': port_id} neutron_client.update_floatingip(floating_ip_id, {'floatingip': fip})
def disconnect_floatingip(nova_client, **kwargs): if is_external_relationship(ctx): ctx.logger.info('Not disassociating floatingip and server since ' 'external floatingip and server are being used') return server_id = ctx.source.instance.runtime_properties[OPENSTACK_ID_PROPERTY] server = nova_client.servers.get(server_id) server.remove_floating_ip(ctx.target.instance.runtime_properties[ IP_ADDRESS_PROPERTY])
def disconnect_security_group(nova_client, **kwargs): if is_external_relationship(ctx): ctx.logger.info('Not disconnecting security group and server since ' 'external security group and server are being used') return server_id = ctx.source.instance.runtime_properties[OPENSTACK_ID_PROPERTY] server = nova_client.servers.get(server_id) server.remove_security_group(ctx.target.instance.runtime_properties[ OPENSTACK_ID_PROPERTY])
def detach_volume(nova_client, cinder_client, **kwargs): if is_external_relationship(ctx): ctx.logger.info('Not detaching volume from server since ' 'external volume and server are being used') return server_id = ctx.target.instance.runtime_properties[OPENSTACK_ID_PROPERTY] volume_id = ctx.source.instance.runtime_properties[OPENSTACK_ID_PROPERTY] _detach_volume(nova_client, cinder_client, server_id, volume_id)
def disconnect_port(neutron_client, **kwargs): if is_external_relationship(ctx): ctx.logger.info('Not disassociating floatingip and port since ' 'external floatingip and port are being used') return floating_ip_id = ctx.target.instance.runtime_properties[ OPENSTACK_ID_PROPERTY] fip = {'port_id': None} neutron_client.update_floatingip(floating_ip_id, {'floatingip': fip})
def disconnect_port(neutron_client, **kwargs): if is_external_relationship(ctx): ctx.logger.info('Not disassociating floatingip and port since ' 'external floatingip and port are being used') return floating_ip_id = get_openstack_id(ctx.target) fip = {'port_id': None} neutron_client.update_floatingip(floating_ip_id, {FLOATINGIP_OPENSTACK_TYPE: fip})
def attach_volume(nova_client, cinder_client, **kwargs): server_id = ctx.target.instance.runtime_properties[OPENSTACK_ID_PROPERTY] volume_id = ctx.source.instance.runtime_properties[OPENSTACK_ID_PROPERTY] if is_external_relationship(ctx): ctx.logger.info('Validating external volume and server ' 'are connected') attachment = volume.get_attachment(cinder_client=cinder_client, volume_id=volume_id, server_id=server_id) if attachment: return else: raise NonRecoverableError( 'Expected external resources server {0} and volume {1} to be ' 'connected'.format(server_id, volume_id)) # Note: The 'device_name' property should actually be a property of the # relationship between a server and a volume; It'll move to that # relationship type once relationship properties are better supported. device = ctx.source.node.properties[volume.DEVICE_NAME_PROPERTY] nova_client.volumes.create_server_volume( server_id, volume_id, device if device != 'auto' else None) try: vol, wait_succeeded = volume.wait_until_status( cinder_client=cinder_client, volume_id=volume_id, status=volume.VOLUME_STATUS_IN_USE ) if not wait_succeeded: raise RecoverableError( 'Waiting for volume status {0} failed - detaching volume and ' 'retrying..'.format(volume.VOLUME_STATUS_IN_USE)) if device == 'auto': # The device name was assigned automatically so we # query the actual device name attachment = volume.get_attachment( cinder_client=cinder_client, volume_id=volume_id, server_id=server_id ) device_name = attachment['device'] ctx.logger.info('Detected device name for attachment of volume ' '{0} to server {1}: {2}' .format(volume_id, server_id, device_name)) ctx.source.instance.runtime_properties[ volume.DEVICE_NAME_PROPERTY] = device_name except Exception, e: if not isinstance(e, NonRecoverableError): __prepare_attach_volume_to_be_repeated( nova_client, cinder_client, server_id, volume_id) raise
def disconnect_subnet(neutron_client, **kwargs): if is_external_relationship(ctx): ctx.logger.info('Not connecting subnet and router since external ' 'subnet and router are being used') return neutron_client.remove_interface_router( ctx.target.instance.runtime_properties[OPENSTACK_ID_PROPERTY], { 'subnet_id': ctx.source.instance.runtime_properties[OPENSTACK_ID_PROPERTY] })
def detach_volume(nova_client, cinder_client, status_attempts, status_timeout, **kwargs): if is_external_relationship(ctx): ctx.logger.info('Not detaching volume from server since ' 'external volume and server are being used') return server_id = get_openstack_id(ctx.target) volume_id = get_openstack_id(ctx.source) _detach_volume(nova_client, cinder_client, server_id, volume_id, status_attempts, status_timeout)
def disconnect_subnet(neutron_client, **kwargs): if is_external_relationship(ctx): ctx.logger.info('Not connecting subnet and router since external ' 'subnet and router are being used') return neutron_client.remove_interface_router( ctx.target.instance.runtime_properties[OPENSTACK_ID_PROPERTY], { 'subnet_id': ctx.source.instance.runtime_properties[ OPENSTACK_ID_PROPERTY] } )
def disconnect_subnet(neutron_client, update_args=None, **kwargs): if update_args is not None and isinstance(update_args, dict): update_router(neutron_client, args=update_args, ctx=ctx) if is_external_relationship(ctx): ctx.logger.info('Not connecting subnet and router since external ' 'subnet and router are being used') return neutron_client.remove_interface_router( get_openstack_id(ctx.target), {'subnet_id': get_openstack_id(ctx.source)})
def attach(nova_client, neutron_client, **kwargs): if is_external_relationship(ctx): ctx.logger.info('Not attaching port from server since ' 'external port and server are being used') return server_id = get_openstack_id(ctx.source) port_id = get_openstack_id(ctx.target) port = neutron_client.show_port(port_id) server = nova_client.servers.get(server_id) network = neutron_client.show_network(port['port']['network_id']) network_name = network['network']['name'] floating_ip_address = None for target in ctx.target.instance.relationships: if target.type == PORT_ADDRESS_REL_TYPE: target_instance = target.target.instance floatingip_id = \ target_instance.runtime_properties[OPENSTACK_ID_PROPERTY] floating_ip = neutron_client.show_floatingip(floatingip_id) floating_ip_address = \ floating_ip['floatingip']['floating_ip_address'] server_addresses = \ [addr['addr'] for addr in server.addresses[network_name]] if floating_ip_address and floating_ip_address not in server_addresses: ctx.logger.info('We will attach floating ip {0} to server {1}'.format( floating_ip_address, server_id)) server.add_floating_ip(floating_ip_address) return ctx.operation.retry( message='Waiting for the floating ip {0} to ' 'attach to server {1}..'.format(floating_ip_address, server_id), retry_after=10) change = { PORT_OPENSTACK_TYPE: { 'device_id': server_id, } } device_id = port['port'].get('device_id') if not device_id or device_id != server_id: ctx.logger.info('Attaching port {0}...'.format(port_id)) neutron_client.update_port(port_id, change) ctx.logger.info('Successfully attached port {0}'.format(port_id)) else: ctx.logger.info('Skipping port {0} attachment, ' 'because it is already attached ' 'to device (server) id {1}.'.format( port_id, device_id))
def disconnect_floatingip(nova_client, neutron_client, **kwargs): if is_external_relationship(ctx): ctx.logger.info('Not disassociating floatingip and server since ' 'external floatingip and server are being used') return server_id = ctx.source.instance.runtime_properties[OPENSTACK_ID_PROPERTY] ctx.logger.info("Remove floating ip {0}".format( ctx.target.instance.runtime_properties[IP_ADDRESS_PROPERTY])) server_floating_ip = get_server_floating_ip(neutron_client, server_id) if server_floating_ip: server = nova_client.servers.get(server_id) server.remove_floating_ip(server_floating_ip['floating_ip_address']) ctx.logger.info("Floating ip {0} detached from server" .format(server_floating_ip['floating_ip_address']))
def disconnect_subnet(neutron_client, **kwargs): if is_external_relationship(ctx): ctx.logger.info('Not connecting subnet and router since external ' 'subnet and router are being used') return node_routes = ctx.source.instance.runtime_properties.get( ROUTES_OPENSTACK_TYPE) # Only delete routes only if it has "routes" as runtime properties if node_routes: _delete_routes(neutron_client) neutron_client.remove_interface_router( get_openstack_id(ctx.target), {'subnet_id': get_openstack_id(ctx.source)})
def disconnect_floatingip(nova_client, neutron_client, **kwargs): if is_external_relationship(ctx): ctx.logger.info('Not disassociating floatingip and server since ' 'external floatingip and server are being used') return server_id = get_openstack_id(ctx.source) ctx.logger.info("Remove floating ip {0}".format( ctx.target.instance.runtime_properties[IP_ADDRESS_PROPERTY])) server_floating_ip = get_server_floating_ip(neutron_client, server_id) if server_floating_ip: server = nova_client.servers.get(server_id) server.remove_floating_ip(server_floating_ip['floating_ip_address']) ctx.logger.info("Floating ip {0} detached from server" .format(server_floating_ip['floating_ip_address']))
def connect_subnet(neutron_client, **kwargs): router_id = ctx.target.instance.runtime_properties[OPENSTACK_ID_PROPERTY] subnet_id = ctx.source.instance.runtime_properties[OPENSTACK_ID_PROPERTY] if is_external_relationship(ctx): ctx.logger.info('Validating external subnet and router ' 'are associated') for port in neutron_client.list_ports(device_id=router_id)['ports']: for fixed_ip in port.get('fixed_ips', []): if fixed_ip.get('subnet_id') == subnet_id: return raise NonRecoverableError( 'Expected external resources router {0} and subnet {1} to be ' 'connected'.format(router_id, subnet_id)) neutron_client.add_interface_router(router_id, {'subnet_id': subnet_id})
def detach_volume(nova_client, cinder_client, **kwargs): if is_external_relationship(ctx): ctx.logger.info('Not detaching volume from server since ' 'external volume and server are being used') return server_id = ctx.target.instance.runtime_properties[OPENSTACK_ID_PROPERTY] volume_id = ctx.source.instance.runtime_properties[OPENSTACK_ID_PROPERTY] attachment = volume.get_attachment(cinder_client=cinder_client, volume_id=volume_id, server_id=server_id) if attachment: nova_client.volumes.delete_server_volume(server_id, attachment['id']) volume.wait_until_status(cinder_client=cinder_client, volume_id=volume_id, status=volume.VOLUME_STATUS_AVAILABLE)
def connect_security_group(nova_client, **kwargs): server_id = ctx.source.instance.runtime_properties[OPENSTACK_ID_PROPERTY] security_group_id = ctx.target.instance.runtime_properties[ OPENSTACK_ID_PROPERTY] if is_external_relationship(ctx): ctx.logger.info('Validating external security group and server ' 'are associated') server = nova_client.servers.get(server_id) if [sg for sg in server.list_security_group() if sg.id == security_group_id]: return raise NonRecoverableError( 'Expected external resources server {0} and security-group {1} to ' 'be connected'.format(server_id, security_group_id)) server = nova_client.servers.get(server_id) server.add_security_group(security_group_id)
def connect_floatingip(nova_client, fixed_ip, **kwargs): server_id = ctx.source.instance.runtime_properties[OPENSTACK_ID_PROPERTY] floating_ip_id = ctx.target.instance.runtime_properties[ OPENSTACK_ID_PROPERTY] if is_external_relationship(ctx): ctx.logger.info('Validating external floatingip and server ' 'are associated') if nova_client.floating_ips.get(floating_ip_id).instance_id ==\ server_id: return raise NonRecoverableError( 'Expected external resources server {0} and floating-ip {1} to be ' 'connected'.format(server_id, floating_ip_id)) floating_ip_address = ctx.target.instance.runtime_properties[ IP_ADDRESS_PROPERTY] server = nova_client.servers.get(server_id) server.add_floating_ip(floating_ip_address, fixed_ip or None)
def connect_floatingip(nova_client, **kwargs): server_id = ctx.source.instance.runtime_properties[OPENSTACK_ID_PROPERTY] floating_ip_id = ctx.target.instance.runtime_properties[ OPENSTACK_ID_PROPERTY] floating_ip_address = ctx.target.instance.runtime_properties[ IP_ADDRESS_PROPERTY] if is_external_relationship(ctx): ctx.logger.info('Validating external floatingip and server ' 'are associated') nc = _neutron_client() port_id = nc.show_floatingip(floating_ip_id)['floatingip']['port_id'] if port_id and nc.show_port(port_id)['port']['device_id'] == server_id: return raise NonRecoverableError( 'Expected external resources server {0} and floating-ip {1} to be ' 'connected'.format(server_id, floating_ip_id)) server = nova_client.servers.get(server_id) server.add_floating_ip(floating_ip_address)
def detach(neutron_client, **kwargs): if is_external_relationship(ctx): ctx.logger.info('Not detaching port from server since ' 'external port and server are being used') return port_id = ctx.target.instance.runtime_properties[OPENSTACK_ID_PROPERTY] server_id = ctx.source.instance.runtime_properties[OPENSTACK_ID_PROPERTY] server_floating_ip = _get_server_floating_ip(neutron_client, server_id) if server_floating_ip: return ctx.operation.retry( message='Waiting for the floating ip {0} to ' 'detach from server {1}..'.format( server_floating_ip['floating_ip_address'], server_id), retry_after=10) change = {'port': {'device_id': '', 'device_owner': ''}} ctx.logger.info('Detaching port {0}...'.format(port_id)) neutron_client.update_port(port_id, change) ctx.logger.info('Successfully detached port {0}'.format(port_id))
def disconnect_security_group(nova_client, **kwargs): if is_external_relationship(ctx): ctx.logger.info('Not disconnecting security group and server since ' 'external security group and server are being used') return server_id = ctx.source.instance.runtime_properties[OPENSTACK_ID_PROPERTY] security_group_id = ctx.target.instance.runtime_properties[ OPENSTACK_ID_PROPERTY] security_group_name = ctx.target.instance.runtime_properties[ OPENSTACK_NAME_PROPERTY] server = nova_client.servers.get(server_id) # to support nova security groups as well, we disconnect the security group # by name (as disconnecting by id doesn't seem to work well for nova SGs) server.remove_security_group(security_group_name) _validate_security_group_and_server_connection_status(nova_client, server_id, security_group_id, security_group_name, is_connected=False)
def connect_security_group(neutron_client, **kwargs): port_id = ctx.source.instance.runtime_properties[OPENSTACK_ID_PROPERTY] security_group_id = ctx.target.instance.runtime_properties[ OPENSTACK_ID_PROPERTY] if is_external_relationship(ctx): ctx.logger.info('Validating external port and security-group are ' 'connected') if any(sg for sg in neutron_client.show_port(port_id)['port'].get( 'security_groups', []) if sg == security_group_id): return raise NonRecoverableError( 'Expected external resources port {0} and security-group {1} to ' 'be connected'.format(port_id, security_group_id)) # WARNING: non-atomic operation port = neutron_client.cosmo_get('port', id=port_id) ctx.logger.info( "connect_security_group(): source_id={0} target={1}".format( port_id, ctx.target.instance.runtime_properties)) sgs = port['security_groups'] + [security_group_id] neutron_client.update_port(port_id, {'port': {'security_groups': sgs}})
def disconnect_security_group(nova_client, **kwargs): if is_external_relationship(ctx): ctx.logger.info('Not disconnecting security group and server since ' 'external security group and server are being used') return server_id = get_openstack_id(ctx.source) security_group_id = get_openstack_id(ctx.target) security_group_name = ctx.target.instance.runtime_properties[ OPENSTACK_NAME_PROPERTY] server = nova_client.servers.get(server_id) # to support nova security groups as well, we disconnect the security group # by name (as disconnecting by id doesn't seem to work well for nova SGs) try: server.remove_security_group(security_group_name) except nova_exceptions.NotFound: ctx.logger.warn("Security group '{0}' (id: {1}) is not attached " "to server instance {2}; skipping" .format(security_group_name, security_group_id, server_id)) else: _validate_security_group_and_server_connection_status( nova_client, server_id, security_group_id, security_group_name, is_connected=False)