diff --git a/manifests/all.pp b/manifests/all.pp index f6ac7cc..029a95c 100644 --- a/manifests/all.pp +++ b/manifests/all.pp @@ -59,60 +59,66 @@ class openstack::all ( # Network Required $public_address, - # MySQL Required - $mysql_root_password = 'sql_pass', - # Rabbit Required - $rabbit_password = 'rabbitpw', - # Keystone Required - $keystone_db_password = 'keystone_pass', - $keystone_admin_token = 'keystone_admin_token', - $admin_email = 'some_user@some_fake_email_address.foo', - $admin_password = 'ChangeMe', - # Nova Required - $nova_db_password = 'nova_pass', - $nova_user_password = 'nova_pass', - # Glance Required - $glance_db_password = 'glance_pass', - $glance_user_password = 'glance_pass', - # Horizon Required - $secret_key = 'dummy_secret_key', - # Network $public_interface = 'eth0', $private_interface = 'eth1', - $fixed_range = '10.0.0.0/24', - $network_manager = 'nova.network.manager.FlatDHCPManager', - $network_config = {}, - $auto_assign_floating_ip = false, - $floating_range = false, - $create_networks = true, - $num_networks = 1, - # MySQL + # Database + $mysql_root_password = 'sql_pass', $db_type = 'mysql', $mysql_account_security = true, $allowed_hosts = ['127.0.0.%'], - # Rabbit - $rabbit_user = 'nova', # Keystone + $admin_email = 'some_user@some_fake_email_address.foo', + $admin_password = 'ChangeMe', + $keystone_db_password = 'keystone_pass', $keystone_db_user = 'keystone', $keystone_db_dbname = 'keystone', + $keystone_admin_token = 'keystone_admin_token', $keystone_admin_tenant = 'admin', - # Nova - $nova_db_user = 'nova', - $nova_db_dbname = 'nova', - $purge_nova_config = true, - # Glance + $region = 'RegionOne', + # Glance Required + $glance_db_password = 'glance_pass', $glance_db_user = 'glance', $glance_db_dbname = 'glance', + $glance_user_password = 'glance_pass', + # Nova + $nova_db_password = 'nova_pass', + $nova_db_user = 'nova', + $nova_db_dbname = 'nova', + $nova_user_password = 'nova_pass', + $purge_nova_config = true, + # Network + $network_manager = 'nova.network.manager.FlatDHCPManager', + $fixed_range = '10.0.0.0/24', + $floating_range = false, + $create_networks = true, + $num_networks = 1, + $auto_assign_floating_ip = false, + $network_config = {}, + $quantum = true, + # Rabbit + $rabbit_password = 'rabbit_pw', + $rabbit_user = 'nova', # Horizon + $secret_key = 'dummy_secret_key', $cache_server_ip = '127.0.0.1', $cache_server_port = '11211', $swift = false, - $quantum = false, $horizon_app_links = undef, + # if the cinder management components should be installed + $cinder = true, + $cinder_user_password = 'cinder_user_pass', + $cinder_db_password = 'cinder_db_pass', + $cinder_db_user = 'cinder', + $cinder_db_dbname = 'cinder', + $volume_group = 'cinder-volumes', + $cinder_test = false, + # + $quantum_user_password = 'quantum_user_pass', + $quantum_db_password = 'quantum_db_pass', + $quantum_db_user = 'quantum', + $quantum_db_dbname = 'quantum', # Virtaulization $libvirt_type = 'kvm', - # Volume - $nova_volume = 'nova-volumes', # VNC $vnc_enabled = true, # General @@ -123,26 +129,36 @@ class openstack::all ( # Ensure things are run in order Class['openstack::db::mysql'] -> Class['openstack::keystone'] Class['openstack::db::mysql'] -> Class['openstack::glance'] - Class['openstack::db::mysql'] -> Class['openstack::nova::controller'] # set up mysql server - case $db_type { - 'mysql': { - class { 'openstack::db::mysql': - mysql_root_password => $mysql_root_password, - mysql_bind_address => '127.0.0.1', - mysql_account_security => $mysql_account_security, - keystone_db_user => $keystone_db_user, - keystone_db_password => $keystone_db_password, - keystone_db_dbname => $keystone_db_dbname, - glance_db_user => $glance_db_user, - glance_db_password => $glance_db_password, - glance_db_dbname => $glance_db_dbname, - nova_db_user => $nova_db_user, - nova_db_password => $nova_db_password, - nova_db_dbname => $nova_db_dbname, - allowed_hosts => $allowed_hosts, - } + if ($db_type == 'mysql') { + if ($enabled) { + Class['glance::db::mysql'] -> Class['glance::registry'] + $nova_db = "mysql://${nova_db_user}:${nova_db_password}@127.0.0.1/nova?charset=utf8" + } else { + $nova_db = false + } + class { 'openstack::db::mysql': + mysql_root_password => $mysql_root_password, + mysql_account_security => $mysql_account_security, + keystone_db_user => $keystone_db_user, + keystone_db_password => $keystone_db_password, + keystone_db_dbname => $keystone_db_dbname, + glance_db_user => $glance_db_user, + glance_db_password => $glance_db_password, + glance_db_dbname => $glance_db_dbname, + nova_db_user => $nova_db_user, + nova_db_password => $nova_db_password, + nova_db_dbname => $nova_db_dbname, + cinder => $cinder, + cinder_db_user => $cinder_db_user, + cinder_db_password => $cinder_db_password, + cinder_db_dbname => $cinder_db_dbname, + quantum => $quantum, + quantum_db_user => $quantum_db_user, + quantum_db_password => $quantum_db_password, + quantum_db_dbname => $quantum_db_dbname, + allowed_hosts => $allowed_hosts, } } @@ -151,18 +167,23 @@ class openstack::all ( verbose => $verbose, db_type => $db_type, db_host => '127.0.0.1', - keystone_db_password => $keystone_db_password, - keystone_db_dbname => $keystone_db_dbname, - keystone_db_user => $keystone_db_user, - keystone_admin_token => $keystone_admin_token, - keystone_admin_tenant => $keystone_admin_tenant, + db_password => $keystone_db_password, + db_name => $keystone_db_dbname, + db_user => $keystone_db_user, + admin_token => $keystone_admin_token, + admin_tenant => $keystone_admin_tenant, admin_email => $admin_email, admin_password => $admin_password, public_address => $public_address, internal_address => '127.0.0.1', admin_address => '127.0.0.1', + region => $region, glance_user_password => $glance_user_password, nova_user_password => $nova_user_password, + cinder => $cinder, + cinder_user_password => $cinder_user_password, + quantum => $quantum, + quantum_user_password => $quantum_user_password, } ######## GLANCE ########## @@ -174,6 +195,7 @@ class openstack::all ( glance_db_dbname => $glance_db_dbname, glance_db_password => $glance_db_password, glance_user_password => $glance_user_password, + enabled => $enabled, } ######## NOVA ########### @@ -188,68 +210,108 @@ class openstack::all ( } } - class { 'openstack::nova::controller': - # Network - network_manager => $network_manager, - network_config => $network_config, - private_interface => $private_interface, - public_interface => $public_interface, - floating_range => $floating_range, - fixed_range => $fixed_range, - public_address => $public_address, - admin_address => '127.0.0.1', - internal_address => '127.0.0.1', - auto_assign_floating_ip => $auto_assign_floating_ip, - create_networks => $create_networks, - num_networks => $num_networks, - multi_host => false, - # Database - db_host => '127.0.0.1', - # Nova - nova_user_password => $nova_user_password, - nova_db_password => $nova_db_password, - nova_db_user => $nova_db_user, - nova_db_dbname => $nova_db_dbname, - # Rabbit - rabbit_user => $rabbit_user, - rabbit_password => $rabbit_password, - # Glance - glance_api_servers => '127.0.0.1:9292', - # VNC - vnc_enabled => $vnc_enabled, - # General - verbose => $verbose, - enabled => $enabled, - exported_resources => false, + # Install / configure rabbitmq + class { 'nova::rabbitmq': + userid => $rabbit_user, + password => $rabbit_password, + enabled => $enabled, } - class { 'openstack::nova::compute': - # Network - public_address => $public_address, - private_interface => $private_interface, - public_interface => $public_interface, - fixed_range => $fixed_range, - network_manager => $network_manager, - network_config => $network_config, - multi_host => false, - internal_address => '127.0.0.1', - # Virtualization - libvirt_type => $libvirt_type, - # Volumes - nova_volume => $nova_volume, - manage_volumes => true, - iscsi_ip_address => '127.0.0.1', - # VNC - vnc_enabled => $vnc_enabled, - vncproxy_host => $public_address, - # Nova - nova_user_password => $nova_user_password, - # Rabbit - rabbit_password => $rabbit_password, - # General - verbose => $verbose, - exported_resources => false, + # Configure Nova + class { 'nova': + sql_connection => $nova_db, + rabbit_userid => $rabbit_user, + rabbit_password => $rabbit_password, + image_service => 'nova.image.glance.GlanceImageService', + glance_api_servers => 'localhost:9292', + verbose => $verbose, + rabbit_host => $internal_address, + } + + # Configure nova-api + class { 'nova::api': + enabled => $enabled, + admin_password => $nova_user_password, + auth_host => 'localhost', + } + + if $enabled { + $really_create_networks = $create_networks + } else { + $really_create_networks = false + } + + if $quantum == false { + # Configure nova-network + class { 'nova::network': + private_interface => $private_interface, + public_interface => $public_interface, + fixed_range => $fixed_range, + floating_range => $floating_range, + network_manager => $network_manager, + config_overrides => $network_config, + create_networks => $really_create_networks, + num_networks => $num_networks, + enabled => $enabled, + } + } else { + # Set up Quantum + } + + if $auto_assign_floating_ip { + nova_config { 'auto_assign_floating_ip': value => 'True' } + } + + class { [ + 'nova::scheduler', + 'nova::objectstore', + 'nova::cert', + 'nova::consoleauth' + ]: + enabled => $enabled, + } + + if $vnc_enabled { + class { 'nova::vncproxy': + host => $public_address, + enabled => $enabled, + } + } + + ######### Cinder Controller Services ######## + if ($cinder) { + class { "cinder::base": + verbose => $verbose, + sql_connection => "mysql://${cinder_db_user}:${cinder_db_password}@127.0.0.1/${cinder_db_dbname}?charset=utf8", + rabbit_password => $rabbit_password, + } + + class { 'cinder::api': + keystone_password => $cinder_user_password, + } + + class { 'cinder::scheduler': } + class { 'cinder::volume': } + class { 'cinder::volume::iscsi': + volume_group => $volume_group, + test => $cinder_test, + } + } else { + # Set up nova-volume + } + + # Install / configure nova-compute + class { '::nova::compute': enabled => $enabled, + vnc_enabled => $vnc_enabled, + vncserver_proxyclient_address => $internal_address, + vncproxy_host => 'localhost', + } + + # Configure libvirt for nova-compute + class { 'nova::compute::libvirt': + libvirt_type => $libvirt_type, + vncserver_listen => $internal_address, } ######## Horizon ######## diff --git a/manifests/compute.pp b/manifests/compute.pp index 455aa1d..082db9f 100644 --- a/manifests/compute.pp +++ b/manifests/compute.pp @@ -22,13 +22,20 @@ class openstack::compute ( $nova_user_password, # Required Rabbit $rabbit_password, - # Network # DB - $sql_connection = false, + $sql_connection, + # Network + $quantum = true, + $public_interface = undef, + $private_interface = undef, + $fixed_range = undef, + $network_manager = 'nova.network.manager.FlatDHCPManager', + $network_config = {}, + $multi_host = false, # Nova - $purge_nova_config = true, + $purge_nova_config = true, # Rabbit - $rabbit_host = false, + $rabbit_host = '127.0.0.1', $rabbit_user = 'nova', # Glance $glance_api_servers = false, @@ -37,11 +44,26 @@ class openstack::compute ( # VNC $vnc_enabled = true, $vncproxy_host = undef, + $vncserver_listen = false, + # cinder / volumes + $cinder = true, + $cinder_sql_connection = undef, + $manage_volumes = true, + $nova_volume = 'cinder-volumes', + $iscsi_ip_address = '127.0.0.1', # General + $migration_support = false, $verbose = 'False', $enabled = true ) { + if $vncserver_listen { + $vncserver_listen_real = $vncserver_listen + } else { + $vncserver_listen_real = $internal_address + } + + # # indicates that all nova config entries that we did # not specifify in Puppet should be purged from file @@ -54,10 +76,6 @@ class openstack::compute ( } } - $final_sql_connection = $sql_connection - $glance_connection = $glance_api_servers - $rabbit_connection = $rabbit_host - class { 'nova': sql_connection => $sql_connection, rabbit_userid => $rabbit_user, @@ -78,47 +96,70 @@ class openstack::compute ( # Configure libvirt for nova-compute class { 'nova::compute::libvirt': - libvirt_type => $libvirt_type, - vncserver_listen => $internal_address, + libvirt_type => $libvirt_type, + vncserver_listen => $vncserver_listen_real, + migration_support => $migration_support, } # if the compute node should be configured as a multi-host # compute installation - if $multi_host { - include keystone::python - #nova_config { - # 'multi_host': value => 'True'; - # 'send_arp_for_ha': value => 'True'; - #} - #if ! $public_interface { - # fail('public_interface must be defined for multi host compute nodes') - #} - #$enable_network_service = true - class { 'nova::api': - enabled => true, - admin_tenant_name => 'services', - admin_user => 'nova', - admin_password => $nova_user_password, - # TODO override enabled_apis + if $quantum == false { + if $multi_host { + include keystone::python + nova_config { + 'multi_host': value => 'True'; + 'send_arp_for_ha': value => 'True'; + } + if ! $public_interface { + fail('public_interface must be defined for multi host compute nodes') + } + $enable_network_service = true + class { 'nova::api': + enabled => true, + admin_tenant_name => 'services', + admin_user => 'nova', + admin_password => $nova_user_password, + # TODO override enabled_apis + } + } else { + $enable_network_service = false + nova_config { + 'multi_host': value => 'False'; + 'send_arp_for_ha': value => 'False'; + } + } + + class { 'nova::network': + private_interface => $private_interface, + public_interface => $public_interface, + fixed_range => $fixed_range, + floating_range => false, + network_manager => $network_manager, + config_overrides => $network_config, + create_networks => false, + enabled => $enable_network_service, + install_service => $enable_network_service, } } else { - #$enable_network_service = false - #nova_config { - # 'multi_host': value => 'False'; - # 'send_arp_for_ha': value => 'False'; - #} + # TODO install quantum } - #class { 'nova::network': - # private_interface => $private_interface, - # public_interface => $public_interface, - # fixed_range => $fixed_range, - # floating_range => false, - # network_manager => $network_manager, - # config_overrides => $network_config, - # create_networks => false, - # enabled => $enable_network_service, - # install_service => $enable_network_service, - #} + if ($cinder) { + class { 'cinder::base': + rabbit_password => $rabbit_password, + rabbit_host => $rabbit_host, + sql_connection => $cinder_sql_connection, + verbose => $verbose, + } + class { 'cinder::volume': } + class { 'cinder::volume::iscsi': + iscsi_ip_address => $internal_address, + volume_group => $nova_volume, + } + + nova_config { 'volume_api_class': value => 'nova.volume.cinder.API' } + } else { + # Set up nova-volume + } } diff --git a/manifests/controller.pp b/manifests/controller.pp index d0d54d8..be1eb45 100644 --- a/manifests/controller.pp +++ b/manifests/controller.pp @@ -31,7 +31,6 @@ # [network_config] Hash that can be used to pass implementation specifc # network settings. Optioal. Defaults to {} # [verbose] Whether to log services at verbose. -# [export_resources] Rather to export resources. # Horizon related config - assumes puppetlabs-horizon code # [secret_key] secret key to encode cookies, … # [cache_server_ip] local memcached instance ip @@ -67,35 +66,27 @@ class openstack::controller ( $public_address, $public_interface, $private_interface, - # Required Database - $mysql_root_password = 'sql_pass', - # Required Keystone - $admin_email = 'some_user@some_fake_email_address.foo', - $admin_password = 'ChangeMe', - $keystone_db_password = 'keystone_pass', - $keystone_admin_token = 'keystone_admin_token', - # Required Glance - $glance_db_password = 'glance_pass', - $glance_user_password = 'glance_pass', - # Required Nova - $nova_db_password = 'nova_pass', - $nova_user_password = 'nova_pass', - # Required Horizon - $secret_key = 'dummy_secret_key', - # not sure if this works correctly - $internal_address = $public_address, - $admin_address = $public_address, - $network_manager = 'nova.network.manager.FlatDHCPManager', - $fixed_range = '10.0.0.0/24', - $floating_range = false, - $create_networks = true, - $num_networks = 1, - $multi_host = false, - $auto_assign_floating_ip = false, - $network_config = {}, + $admin_email, + # required password + $admin_password, + $rabbit_password, + $keystone_db_password, + $keystone_admin_token, + $glance_db_password, + $glance_user_password, + $nova_db_password, + $nova_user_password, + $secret_key, + # cinder and quantum password are not required b/c they are + # optional. Not sure what to do about this. + $cinder_user_password = 'cinder_pass', + $cinder_db_password = 'cinder_pass', + $quantum_user_password = 'quantum_pass', + $quantum_db_password = 'quantum_pass', # Database $db_host = '127.0.0.1', $db_type = 'mysql', + $mysql_root_password = 'sql_pass', $mysql_account_security = true, $mysql_bind_address = '0.0.0.0', $allowed_hosts = '%', @@ -103,6 +94,7 @@ class openstack::controller ( $keystone_db_user = 'keystone', $keystone_db_dbname = 'keystone', $keystone_admin_tenant = 'admin', + $region = 'RegionOne', # Glance $glance_db_user = 'glance', $glance_db_dbname = 'glance', @@ -111,32 +103,50 @@ class openstack::controller ( $nova_db_user = 'nova', $nova_db_dbname = 'nova', $purge_nova_config = true, + # Network + $internal_address = false, + $admin_address = false, + $network_manager = 'nova.network.manager.FlatDHCPManager', + $fixed_range = '10.0.0.0/24', + $floating_range = false, + $create_networks = true, + $num_networks = 1, + $multi_host = false, + $auto_assign_floating_ip = false, + $network_config = {}, + $quantum = true, # Rabbit - $rabbit_password = 'rabbit_pw', $rabbit_user = 'nova', # Horizon $cache_server_ip = '127.0.0.1', $cache_server_port = '11211', - $swift = false, - $quantum = false, - $cinder = false, $horizon_app_links = undef, + $swift = false, + # VNC + $vnc_enabled = true, # General $verbose = 'False', - $export_resources = true, # if the cinder management components should be installed - $cinder_user_password = 'cinder_user_pass', - $cinder_db_password = 'cinder_db_pass', + $cinder = false, $cinder_db_user = 'cinder', $cinder_db_dbname = 'cinder', # - $quantum_user_password = 'quantum_user_pass', - $quantum_db_password = 'quantum_db_pass', $quantum_db_user = 'quantum', $quantum_db_dbname = 'quantum', $enabled = true ) { + if $internal_address { + $internal_address_real = $internal_address + } else { + $internal_address_real = $public_address + } + if $admin_address { + $admin_address_real = $admin_address + } else { + $admin_address_real = $public_address + } + # Ensure things are run in order Class['openstack::db::mysql'] -> Class['openstack::keystone'] Class['openstack::db::mysql'] -> Class['openstack::glance'] @@ -187,8 +197,9 @@ class openstack::controller ( admin_email => $admin_email, admin_password => $admin_password, public_address => $public_address, - internal_address => $internal_address, + internal_address => $internal_address_real, admin_address => $admin_address, + region => $region, glance_user_password => $glance_user_password, nova_user_password => $nova_user_password, cinder => $cinder, @@ -227,15 +238,18 @@ class openstack::controller ( db_host => $db_host, # Network network_manager => $network_manager, + network_config => $network_config, floating_range => $floating_range, fixed_range => $fixed_range, public_address => $public_address, admin_address => $admin_address, - internal_address => $internal_address, + internal_address => $internal_address_real, auto_assign_floating_ip => $auto_assign_floating_ip, create_networks => $create_networks, num_networks => $num_networks, multi_host => $multi_host, + public_interface => $public_interface, + private_interface => $private_interface, quantum => $quantum, # Nova nova_user_password => $nova_user_password, @@ -247,10 +261,11 @@ class openstack::controller ( rabbit_password => $rabbit_password, # Glance glance_api_servers => $glance_api_servers, + # VNC + vnc_enabled => $vnc_enabled, # General verbose => $verbose, enabled => $enabled, - exported_resources => $export_resources, } ######### Cinder Controller Services ######## diff --git a/manifests/keystone.pp b/manifests/keystone.pp index df74088..ed23031 100644 --- a/manifests/keystone.pp +++ b/manifests/keystone.pp @@ -54,6 +54,7 @@ class openstack::keystone ( $admin_tenant = 'admin', $verbose = 'False', $bind_host = '0.0.0.0', + $region = 'RegionOne', $internal_address = false, $admin_address = false, $glance_public_address = false, @@ -177,6 +178,7 @@ class openstack::keystone ( public_address => $public_address, admin_address => $admin_real, internal_address => $internal_real, + region => $region, } # Configure Glance endpoint in Keystone @@ -186,6 +188,7 @@ class openstack::keystone ( public_address => $glance_public_real, admin_address => $glance_admin_real, internal_address => $glance_internal_real, + region => $region, } } @@ -196,6 +199,7 @@ class openstack::keystone ( public_address => $nova_public_real, admin_address => $nova_admin_real, internal_address => $nova_internal_real, + region => $region, } } @@ -206,6 +210,7 @@ class openstack::keystone ( public_address => $cinder_public_real, admin_address => $cinder_admin_real, internal_address => $cinder_internal_real, + region => $region, } } if $quantum { @@ -214,6 +219,7 @@ class openstack::keystone ( public_address => $quantum_public_real, admin_address => $quantum_admin_real, internal_address => $quantum_internal_real, + region => $region, } } } diff --git a/manifests/nova/controller.pp b/manifests/nova/controller.pp index 187ef24..873bdce 100644 --- a/manifests/nova/controller.pp +++ b/manifests/nova/controller.pp @@ -30,15 +30,18 @@ class openstack::nova::controller ( $nova_user_password, $nova_db_password, # Network - $fixed_range = '10.0.0.0/24', + $network_manager = 'nova.network.manager.FlatDHCPManager', + $network_config = {}, $floating_range = false, - $internal_address = $public_address, + $fixed_range = '10.0.0.0/24', $admin_address = $public_address, + $internal_address = $public_address, $auto_assign_floating_ip = false, $create_networks = true, $num_networks = 1, $multi_host = false, - $network_manager = 'nova.network.manager.FlatDHCPManager', + $public_interface = undef, + $private_interface = undef, $quantum = true, # Nova $nova_db_user = 'nova', @@ -55,7 +58,6 @@ class openstack::nova::controller ( $keystone_host = '127.0.0.1', $verbose = 'False', $enabled = true, - $exported_resources = true ) { # Configure the db string @@ -70,25 +72,10 @@ class openstack::nova::controller ( } else { $real_glance_api_servers = $glance_api_servers } - if ($exported_resources) { - # export all of the things that will be needed by the clients - @@nova_config { 'rabbit_host': value => $internal_address } - Nova_config <| title == 'rabbit_host' |> - @@nova_config { 'sql_connection': value => $nova_db } - Nova_config <| title == 'sql_connection' |> - - @@nova_config { 'glance_api_servers': value => $real_glance_api_servers } - Nova_config <| title == 'glance_api_servers' |> - - $sql_connection = false - $glance_connection = false - $rabbit_connection = false - } else { - $sql_connection = $nova_db - $glance_connection = $real_glance_api_servers - $rabbit_connection = $internal_address - } + $sql_connection = $nova_db + $glance_connection = $real_glance_api_servers + $rabbit_connection = $internal_address # Install / configure rabbitmq class { 'nova::rabbitmq': @@ -115,17 +102,6 @@ class openstack::nova::controller ( auth_host => $keystone_host, } - # Configure nova-network - if $multi_host { - nova_config { 'multi_host': value => 'True' } - $enable_network_service = false - } else { - if $enabled { - $enable_network_service = true - } else { - $enable_network_service = false - } - } if $enabled { $really_create_networks = $create_networks @@ -134,6 +110,18 @@ class openstack::nova::controller ( } if $quantum == false { + # Configure nova-network + if $multi_host { + nova_config { 'multi_host': value => 'True' } + $enable_network_service = false + } else { + if $enabled { + $enable_network_service = true + } else { + $enable_network_service = false + } + } + class { 'nova::network': private_interface => $private_interface, public_interface => $public_interface, @@ -146,6 +134,8 @@ class openstack::nova::controller ( enabled => $enable_network_service, install_service => $enable_network_service, } + } else { + # Set up Quantum } if $auto_assign_floating_ip {