def connect_floatingip(nova_client, fixed_ip, **kwargs): server_id = get_openstack_id(ctx.source) floating_ip_id = get_openstack_id(ctx.target) if is_external_relationship_not_conditionally_created(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(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_not_conditionally_created(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}}) # Double check if SG has been actually updated (a race-condition # in OpenStack): port_info = neutron_client.show_port(port_id)['port'] port_security_groups = port_info.get('security_groups', []) if security_group_id not in port_security_groups: return ctx.operation.retry( message='Security group connection (`{0}\' -> `{1}\')' ' has not been established!'.format(port_id, security_group_id), retry_after=NO_SG_PORT_CONNECTION_RETRY_INTERVAL )
def connect_security_group(nova_client, **kwargs): 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] if is_external_relationship_not_conditionally_created(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) for security_group in server.list_security_group(): # Since some security groups are already attached in # create this will ensure that they are not attached twice. if security_group_id != security_group.id and \ security_group_name != security_group.name: # 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 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_not_conditionally_created(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) for security_group in server.list_security_group(): # Since some security groups are already attached in # create this will ensure that they are not attached twice. if security_group_id != security_group.id and \ security_group_name != security_group.name: # 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 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_not_conditionally_created(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_not_conditionally_created(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, status_attempts, status_timeout, **kwargs): server_id = get_openstack_id(ctx.target) volume_id = get_openstack_id(ctx.source) if is_external_relationship_not_conditionally_created(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, num_tries=status_attempts, timeout=status_timeout ) 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, status_attempts, status_timeout) raise
def attach_volume(nova_client, cinder_client, status_attempts, status_timeout, **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_not_conditionally_created(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, num_tries=status_attempts, timeout=status_timeout ) 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, status_attempts, status_timeout) raise
def connect_port(neutron_client, **kwargs): if is_external_relationship_not_conditionally_created(ctx): return port_id = get_openstack_id(ctx.source) floating_ip_id = get_openstack_id(ctx.target) fip = {'port_id': port_id} neutron_client.update_floatingip(floating_ip_id, {FLOATINGIP_OPENSTACK_TYPE: fip})
def connect_port(neutron_client, **kwargs): if is_external_relationship_not_conditionally_created(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 connect_port(neutron_client, **kwargs): if is_external_relationship_not_conditionally_created(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 connect_subnet(neutron_client, **kwargs): router_id = get_openstack_id(ctx.target) subnet_id = get_openstack_id(ctx.source) if is_external_relationship_not_conditionally_created(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 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_not_conditionally_created(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 connect_security_group(neutron_client, **kwargs): port_id = get_openstack_id(ctx.source) security_group_id = get_openstack_id(ctx.target) if is_external_relationship_not_conditionally_created(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_OPENSTACK_TYPE, id=port_id) ctx.logger.info( "connect_security_group(): source_id={0} target={1}".format( port_id, ctx.target.instance.runtime_properties)) # We could just pass the port['security_groups'] # dict here with a new element, however we need to test # a race condition in Openstack so we need to copy the security # group list. sgs = port['security_groups'][:] if security_group_id not in port['security_groups']: sgs.append(security_group_id) neutron_client.update_port(port_id, {PORT_OPENSTACK_TYPE: { 'security_groups': sgs }}) # Double check if SG has been actually updated (a race-condition # in OpenStack): port_info = neutron_client.show_port(port_id)['port'] port_security_groups = port_info.get('security_groups', []) if security_group_id not in port_security_groups: return ctx.operation.retry( message='Security group connection (`{0}\' -> `{1}\')' ' has not been established!'.format(port_id, security_group_id), retry_after=NO_SG_PORT_CONNECTION_RETRY_INTERVAL)