summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--boot/dcae2_vm_init.sh68
-rw-r--r--boot/dns_install.sh7
-rw-r--r--boot/named.conf.options3
-rw-r--r--heat/ONAP/onap_openstack.env6
-rw-r--r--heat/ONAP/onap_openstack.yaml64
5 files changed, 103 insertions, 45 deletions
diff --git a/boot/dcae2_vm_init.sh b/boot/dcae2_vm_init.sh
index d15d3c12..a79b9c19 100644
--- a/boot/dcae2_vm_init.sh
+++ b/boot/dcae2_vm_init.sh
@@ -162,7 +162,6 @@ register_multicloud_pod25dns_with_aai()
local DNSAAS_SERVICE_URL
local DNSAAS_USERNAME='demo'
local DNSAAS_PASSWORD='onapdemo'
- local DNSAAS_TENANT_ID
CLOUD_REGION="$(cat /opt/config/dnsaas_region.txt)"
CLOUD_ENV="$(cat /opt/config/cloud_env.txt)"
@@ -249,12 +248,12 @@ register_multicloud_pod25_with_aai()
CLOUD_IDENTITY_URL="http://${MCIP}/api/multicloud-titanium_cloud/v0/${CLOUD_OWNER}_${CLOUD_REGION}/identity/v2.0"
KEYSTONE_URL="$(cat /opt/config/openstack_keystone_url.txt)"
if [[ "$KEYSTONE_URL" == */v3 ]]; then
- echo $KEYSTONE_URL
+ echo "$KEYSTONE_URL"
elif [[ "$KEYSTONE_URL" == */v2.0 ]]; then
- echo $KEYSTONE_URL
+ echo "$KEYSTONE_URL"
else
KEYSTONE_URL="${KEYSTONE_URL}/v3"
- echo $KEYSTONE_URL
+ echo "$KEYSTONE_URL"
fi
USERNAME="$(cat /opt/config/openstack_user.txt)"
PASSWORD="$(cat /opt/config/openstack_password.txt)"
@@ -351,7 +350,6 @@ register_dns_zone()
local CLOUD_REGION
local CLOUD_VERSION='titanium_cloud'
local CLOUD_ENV
- local DCAE_ZONE
local DNSAAS_TENANT_NAME
local MCHOST
local MCURL
@@ -371,14 +369,16 @@ register_dns_zone()
MCHOST=$(cat /opt/config/openo_ip_addr.txt)
MCURL="http://$MCHOST:9005/api/multicloud-titanium_cloud/v0/swagger.json"
- MCDATA='-d "{\"auth\":{\"tenantName\": \"${DNSAAS_TENANT_NAME}\"}}"'
+ MCDATA='-d "{\"auth\":{\"tenantName\": \"'${DNSAAS_TENANT_NAME}'\"}}"'
MULTICLOUD_PLUGIN_ENDPOINT=http://${MCHOST}/api/multicloud-titanium_cloud/v0/${CLOUD_OWNER}_${CLOUD_REGION}
### zone operations
# because all VM's use 10.0.100.1 as their first DNS server, the designate DNS server as seocnd, we need to use a
# domain outside of the first DNS server's domain
+ local DCAE_DOMAIN
local ZONENAME
- ZONENAME="${DCAE_ZONE}.dcaeg2.simpledemo.onap.org."
+ DCAE_DOMAIN="$(cat /opt/config/dcae_domain.txt)"
+ ZONENAME="${DCAE_ZONE}.${DCAE_DOMAIN}."
echo "===> Register DNS zone $ZONENAME under $DNSAAS_TENANT_NAME"
@@ -396,26 +396,33 @@ register_dns_zone()
exit 1
fi
- ### list zones
- echo "=====> Get current zone listing"
- curl -sv -H "Content-Type: application/json" -H "X-Auth-Token: $TOKEN" -X GET "${MULTICLOUD_PLUGIN_ENDPOINT}/dns-delegate/v2/zones"
+ local PROJECTID
+ PROJECTID=$(curl -v -s -H "Content-Type: application/json" -H "X-Auth-Token: $TOKEN" -X GET "${MULTICLOUD_PLUGIN_ENDPOINT}/dns-delegate/v2/zones?name=${ZONENAME}" |sed 's/^.*"project_id":"\([a-zA-Z0-9-]*\)",.*$/\1/')
+ if [ ! -z "$PROJECTID" ]; then
+ ### query the zone with zone id
+ echo "!!!!!!> zone $ZONENAME already registered by project $PROJECTID"
+ else
+ ### create a zone
+ echo "=====> No zone of same name $ZONENAME found, creating new zone "
+ curl -sv -H "Content-Type: application/json" -H "X-Auth-Token: $TOKEN" -X POST -d "{ \"name\": \"$ZONENAME\", \"email\": \"lji@research.att.com\"}" "${MULTICLOUD_PLUGIN_ENDPOINT}/dns-delegate/v2/zones"
+ fi
- ### create a zone
- echo "=====> Creating zone $ZONENAME"
- curl -sv -H "Content-Type: application/json" -H "X-Auth-Token: $TOKEN" -X POST -d "{ \"name\": \"$ZONENAME\", \"email\": \"lji@research.att.com\"}" "${MULTICLOUD_PLUGIN_ENDPOINT}/dns-delegate/v2/zones"
+ ### list zones
+ echo "=====> Zone listing"
+ curl -sv -H "Content-Type: application/json" -H "X-Auth-Token: $TOKEN" -X GET "${MULTICLOUD_PLUGIN_ENDPOINT}/dns-delegate/v2/zones" | python -m json.tool
### query the zone with zone name
- echo "=====> Querying zone $ZONENAME"
- curl -s -H "Content-Type: application/json" -H "X-Auth-Token: $TOKEN" -X GET "${MULTICLOUD_PLUGIN_ENDPOINT}/dns-delegate/v2/zones?name=${ZONENAME}"
+ #echo "=====> Querying zone $ZONENAME"
+ #curl -s -H "Content-Type: application/json" -H "X-Auth-Token: $TOKEN" -X GET "${MULTICLOUD_PLUGIN_ENDPOINT}/dns-delegate/v2/zones?name=${ZONENAME}"
### export ZONE id
- local ZONEID
- ZONEID=$(curl -v -s -H "Content-Type: application/json" -H "X-Auth-Token: $TOKEN" -X GET "${MULTICLOUD_PLUGIN_ENDPOINT}/dns-delegate/v2/zones?name=${ZONENAME}" |sed 's/^.*"id":"\([a-zA-Z0-9-]*\)",.*$/\1/')
+ #local ZONEID
+ #ZONEID=$(curl -v -s -H "Content-Type: application/json" -H "X-Auth-Token: $TOKEN" -X GET "${MULTICLOUD_PLUGIN_ENDPOINT}/dns-delegate/v2/zones?name=${ZONENAME}" |sed 's/^.*"id":"\([a-zA-Z0-9-]*\)",.*$/\1/')
echo "=====> After creation, zone $ZONENAME ID is $ZONEID"
### query the zone with zone id
- echo "=====> Querying zone $ZONENAME by ID $ZONEID"
- curl -sv -H "Content-Type: application/json" -H "X-Auth-Token: $TOKEN" -X GET "${MULTICLOUD_PLUGIN_ENDPOINT}/dns-delegate/v2/zones/${ZONEID}"
+ #echo "=====> Querying zone $ZONENAME by ID $ZONEID"
+ #curl -sv -H "Content-Type: application/json" -H "X-Auth-Token: $TOKEN" -X GET "${MULTICLOUD_PLUGIN_ENDPOINT}/dns-delegate/v2/zones/${ZONEID}"
}
@@ -443,15 +450,18 @@ delete_dns_zone()
MCHOST=$(cat /opt/config/openo_ip_addr.txt)
MCURL="http://$MCHOST:9005/api/multicloud-titanium_cloud/v0/swagger.json"
- MCDATA='"{\"auth\":{\"tenantName\": \"${DNSAAS_TENANT_NAME}\"}}"'
+ local DCAE_DOMAIN
+ local ZONENAME
+ DCAE_DOMAIN="$(cat /opt/config/dcae_domain.txt)"
+ ZONENAME="${DCAE_ZONE}.${DCAE_DOMAIN}."
+
+ MCDATA='"{\"auth\":{\"tenantName\": \"'${DNSAAS_TENANT_NAME}'\"}}"'
MULTICLOUD_PLUGIN_ENDPOINT=http://${MCHOST}/api/multicloud-titanium_cloud/v0/${CLOUD_OWNER}_${CLOUD_REGION}
### Get Token
local TOKEN
TOKEN=$(curl -v -s -H "Content-Type: application/json" -X POST -d "{\"auth\":{\"tenantName\": \"${DNSAAS_TENANT_NAME}\"}}" "${MULTICLOUD_PLUGIN_ENDPOINT}/identity/v3/auth/tokens" 2>&1 | grep X-Subject-Token | sed "s/^.*: //")
- local ZONENAME
- ZONENAME="$1.dcaeg2.simpledemo.onap.org."
local ZONEID
ZONEID=$(curl -v -s -H "Content-Type: application/json" -H "X-Auth-Token: $TOKEN" -X GET "${MULTICLOUD_PLUGIN_ENDPOINT}/dns-delegate/v2/zones?name=${ZONENAME}" |sed 's/^.*"id":"\([a-zA-Z0-9-]*\)",.*$/\1/')
@@ -482,15 +492,17 @@ list_dns_zone()
MCHOST=$(cat /opt/config/openo_ip_addr.txt)
MCURL="http://$MCHOST:9005/api/multicloud-titanium_cloud/v0/swagger.json"
- MCDATA='"{\"auth\":{\"tenantName\": \"${DNSAAS_TENANT_NAME}\"}}"'
+ MCDATA='"{\"auth\":{\"tenantName\": \"'${DNSAAS_TENANT_NAME}'\"}}"'
MULTICLOUD_PLUGIN_ENDPOINT=http://${MCHOST}/api/multicloud-titanium_cloud/v0/${CLOUD_OWNER}_${CLOUD_REGION}
### Get Token
local TOKEN
TOKEN=$(curl -v -s -H "Content-Type: application/json" -X POST -d "{\"auth\":{\"tenantName\": \"${DNSAAS_TENANT_NAME}\"}}" "${MULTICLOUD_PLUGIN_ENDPOINT}/identity/v3/auth/tokens" 2>&1 | grep X-Subject-Token | sed "s/^.*: //")
+ local DCAE_DOMAIN
local ZONENAME
- ZONENAME="$1.dcaeg2.simpledemo.onap.org."
+ DCAE_DOMAIN="$(cat /opt/config/dcae_domain.txt)"
+ ZONENAME="${DCAE_ZONE}.${DCAE_DOMAIN}."
local ZONEID
ZONEID=$(curl -v -s -H "Content-Type: application/json" -H "X-Auth-Token: $TOKEN" -X GET "${MULTICLOUD_PLUGIN_ENDPOINT}/dns-delegate/v2/zones?name=${ZONENAME}" |sed 's/^.*"id":"\([a-zA-Z0-9-]*\)",.*$/\1/')
@@ -510,7 +522,7 @@ ZONE=$(cat /opt/config/rand_str.txt)
MYFLOATIP=$(cat /opt/config/dcae_float_ip.txt)
MYLOCALIP=$(cat /opt/config/dcae_ip_addr.txt)
-
+# start docker image pulling while we are waiting for A&AI to come online
docker login -u "$NEXUS_USER" -p "$NEXUS_PASSWORD" "$NEXUS_DOCKER_REPO"
docker pull "$NEXUS_DOCKER_REPO/onap/org.onap.dcaegen2.deployments.bootstrap:$DOCKER_VERSION" && docker pull nginx &
@@ -548,9 +560,9 @@ rm -f /opt/config/runtime.ip.consul
rm -f /opt/config/runtime.ip.cm
-docker login -u "$NEXUS_USER" -p "$NEXUS_PASSWORD" "$NEXUS_DOCKER_REPO"
-docker pull "$NEXUS_DOCKER_REPO/onap/org.onap.dcaegen2.deployments.bootstrap:$DOCKER_VERSION"
-docker run -d --name boot -v /opt/app/config:/opt/app/installer/config -e "LOCATION=$ZONE" "$NEXUS_DOCKER_REPO/onap/org.onap.dcaegen2.deployments.bootstrap:$DOCKER_VERSION"
+#docker login -u "$NEXUS_USER" -p "$NEXUS_PASSWORD" "$NEXUS_DOCKER_REPO"
+#docker pull "$NEXUS_DOCKER_REPO/onap/org.onap.dcaegen2.deployments.bootstrap:$DOCKER_VERSION"
+#docker run -d --name boot -v /opt/app/config:/opt/app/installer/config -e "LOCATION=$ZONE" "$NEXUS_DOCKER_REPO/onap/org.onap.dcaegen2.deployments.bootstrap:$DOCKER_VERSION"
# waiting for bootstrap to complete then starting nginx for proxying healthcheck calls
diff --git a/boot/dns_install.sh b/boot/dns_install.sh
index 2985bb7d..5d3a9a3f 100644
--- a/boot/dns_install.sh
+++ b/boot/dns_install.sh
@@ -5,6 +5,7 @@ NEXUS_REPO=$(cat /opt/config/nexus_repo.txt)
ARTIFACTS_VERSION=$(cat /opt/config/artifacts_version.txt)
CLOUD_ENV=$(cat /opt/config/cloud_env.txt)
+
if [[ $CLOUD_ENV != "rackspace" ]]
then
# Add host name to /etc/host to avoid warnings in openstack images
@@ -64,9 +65,12 @@ curl -k $NEXUS_REPO/org.onap.demo/boot/$ARTIFACTS_VERSION/$ZONE_ONAP -o /etc/bin
curl -k $NEXUS_REPO/org.onap.demo/boot/$ARTIFACTS_VERSION/$OPTIONS_FILE -o /etc/bind/named.conf.options
curl -k $NEXUS_REPO/org.onap.demo/boot/$ARTIFACTS_VERSION/named.conf.local -o /etc/bind/named.conf.local
+
+
# Set the private IP address of each ONAP VM in the Bind configuration in OpenStack deployments
if [[ $CLOUD_ENV != "rackspace" ]]
then
+ sed -i "s/dns_forwarder/"$(cat /opt/config/dns_forwarder.txt)"/g" /etc/bind/named.conf.options
sed -i "s/dns_ip_addr/"$(cat /opt/config/dns_ip_addr.txt)"/g" /etc/bind/named.conf.options
sed -i "s/external_dns/"$(cat /opt/config/external_dns.txt)"/g" /etc/bind/named.conf.options
sed -i "s/aai1_ip_addr/"$(cat /opt/config/aai1_ip_addr.txt)"/g" /etc/bind/zones/db.simpledemo.openecomp.org
@@ -107,4 +111,5 @@ fi
# Configure Bind
modprobe ip_gre
sed -i "s/OPTIONS=.*/OPTIONS=\"-4 -u bind\"/g" /etc/default/bind9
-service bind9 restart \ No newline at end of file
+service bind9 restart
+
diff --git a/boot/named.conf.options b/boot/named.conf.options
index a09931cb..23feebc5 100644
--- a/boot/named.conf.options
+++ b/boot/named.conf.options
@@ -10,8 +10,7 @@ options {
allow-transfer { none; }; # disable zone transfers by default
forwarders {
- 8.8.8.8;
- 8.8.4.4;
+ dns_forwarder;
};
// If there is a firewall between you and nameservers you want
diff --git a/heat/ONAP/onap_openstack.env b/heat/ONAP/onap_openstack.env
index ba8ffd34..88c6518c 100644
--- a/heat/ONAP/onap_openstack.env
+++ b/heat/ONAP/onap_openstack.env
@@ -69,6 +69,7 @@ parameters:
dns_list: PUT THE ADDRESS OF THE EXTERNAL DNS HERE (e.g. a comma-separated list of IP addresses in your /etc/resolv.conf in UNIX-based Operating Systems)
external_dns: PUT THE FIRST ADDRESS OF THE EXTERNAL DNS LIST HERE
+ dns_forwarder: PUT THE IP OF DNS FORWARDER FOR ONAP DEPLOYMENT'S OWN DNS SERVER
oam_network_cidr: 10.0.0.0/16
### Private IP addresses ###
@@ -123,13 +124,12 @@ parameters:
dnsaas_config_enabled: PUT WHETHER TO USE PROXYED DESIGNATE
dnsaas_region: PUT THE DESIGNATE PROVIDING OPENSTACK'S REGION HERE
dnsaas_keystone_url: PUT THE DESIGNATE PROVIDING OPENSTACK'S KEYSTONE URL HERE
- dnsaas_tenant_name: PUT THE TENANT NAME IN THE DESIGNATE PROVIDING OPENSTACK HERE
+ dnsaas_tenant_name: PUT THE TENANT NAME IN THE DESIGNATE PROVIDING OPENSTACK HERE (FOR R1 USE THE SAME AS openstack_tenant_name)
dnsaas_username: PUT THE DESIGNATE PROVIDING OPENSTACK'S USERNAME HERE
dnsaas_password: PUT THE DESIGNATE PROVIDING OPENSTACK'S PASSWORD HERE
dcae_keystone_url: PUT THE MULTIVIM PROVIDED KEYSTONE API URL HERE
dcae_centos_7_image: PUT THE CENTOS7 VM IMAGE NAME HERE FOR DCAE LAUNCHED CENTOS7 VM
- dcae_security_group: PUT THE SECURITY GROUP NAME HERE FOR DCAE LAUNCHED VMS
- dcae_key_name: PUT THE ON BOARDED KEY-PAIR NAME HERE FOR DCAE LAUNCHED VMS
+ dcae_domain: PUT THE NAME OF DOMAIN THAT DCAE VMS REGISTER UNDER
dcae_public_key: PUT THE PUBLIC KEY OF A KEYPAIR HERE TO BE USED BETWEEN DCAE LAUNCHED VMS
dcae_private_key: PUT THE SECRET KEY OF A KEYPAIR HERE TO BE USED BETWEEN DCAE LAUNCHED VMS
diff --git a/heat/ONAP/onap_openstack.yaml b/heat/ONAP/onap_openstack.yaml
index 8449b079..2c4ef766 100644
--- a/heat/ONAP/onap_openstack.yaml
+++ b/heat/ONAP/onap_openstack.yaml
@@ -162,6 +162,10 @@ parameters:
type: string
description: First element of the dns_list for ONAP network
+ dns_forwarder:
+ type: string
+ description: the forwarder address for setting up ONAP's private DNS server
+
oam_network_cidr:
type: string
description: CIDR of the OAM ONAP network
@@ -252,10 +256,6 @@ parameters:
type: string
description: the keystone URL for DCAE to use (via MultiCloud)
- dcae_key_name:
- type: string
- description: the name of the keypair on-boarded with Cloud
-
dcae_private_key:
type: string
description: the private key of the key-apir used between the DCAE bootstrap container and DCAE VMs
@@ -268,10 +268,9 @@ parameters:
type: string
description: the id/name of the CentOS 7 VM imange
- dcae_security_group:
+ dcae_domain:
type: string
- description: the security group to be used by DCAE VMs
-
+ description: the top level domain to register DCAE VMs (the zone will be random-str.dcae_domain)
# dcae_base_environment:
# type: string
@@ -419,7 +418,6 @@ resources:
properties:
length: 4
-
# Public key used to access ONAP components
vm_key:
type: OS::Nova::KeyPair
@@ -433,6 +431,36 @@ resources:
public_key: { get_param: pub_key }
save_private_key: false
+
+ # ONAP security group
+ onap_sg:
+ type: OS::Neutron::SecurityGroup
+ properties:
+ name:
+ str_replace:
+ template: base_rand
+ params:
+ base: onap_sg
+ rand: { get_resource: random-str }
+ description: security group used by ONAP
+ rules:
+ # All egress traffic
+ - direction: egress
+ ethertype: IPv4
+ - direction: egress
+ ethertype: IPv6
+ # ingress traffic
+ # ICMP
+ - protocol: icmp
+ - protocol: udp
+ port_range_min: 1
+ port_range_max: 65535
+ - protocol: tcp
+ port_range_min: 1
+ port_range_max: 65535
+
+
+
# ONAP management private network
oam_onap:
type: OS::Neutron::Net
@@ -519,6 +547,7 @@ resources:
__openo_ip_addr__: { get_param: openo_ip_addr }
__cloud_env__: { get_param: cloud_env }
__external_dns__: { get_param: external_dns }
+ __dns_forwarder__: { get_param: dns_forwarder }
template: |
#!/bin/bash
@@ -545,6 +574,7 @@ resources:
echo "__clamp_ip_addr__" > /opt/config/clamp_ip_addr.txt
echo "__openo_ip_addr__" > /opt/config/openo_ip_addr.txt
echo "__external_dns__" > /opt/config/external_dns.txt
+ echo "__dns_forwarder__" > /opt/config/dns_forwarder.txt
# Download and run install script
curl -k __nexus_repo__/org.onap.demo/boot/__artifacts_version__/dns_install.sh -o /opt/dns_install.sh
@@ -1710,6 +1740,8 @@ resources:
key_name: { get_resource: vm_key }
networks:
- port: { get_resource: dcae_c_private_port }
+ #security_groups:
+ # - { get_resource: onap_sg }
user_data_format: RAW
user_data:
str_replace:
@@ -1730,6 +1762,8 @@ resources:
__dcae_float_ip__: { get_attr: [dcae_c_floating_ip, floating_ip_address] }
__dns_ip_addr__: { get_param: dns_ip_addr }
__external_dns__: { get_param: external_dns }
+ __dns_forwarder__: { get_param: dns_forwarder }
+ __dcae_domain__: { get_param: dcae_domain }
# conf for VMs DCAE is to bringup
__openstack_keystone_url__: { get_param: keystone_url }
__dcae_keystone_url__: { get_param: dcae_keystone_url }
@@ -1738,18 +1772,23 @@ resources:
__dcaeos_region__: { get_param: openstack_region }
__dcaeos_tenant_id__: { get_param: openstack_tenant_id }
__dcaeos_tenant_name__: { get_param: openstack_tenant_name }
+ __dcaeos_security_group__:
+ str_replace:
+ template: 'onap_sg_rand'
+ params:
+ rand: { get_resource: random-str }
+ #__dcaeos_security_group__: { get_attr: [onap_sg, name] }
__dcaeos_username__: { get_param: openstack_username }
__dcaeos_password__: { get_param: openstack_api_key }
- __dcaeos_key_name__: { get_attr: [vm_key, name] }
- __dcaeos_key_name__: { get_param: dcae_key_name }
+ __dcaeos_key_name__: { get_resource: vm_key }
__dcaeos_public_key__: { get_param: dcae_public_key }
__dcaeos_private_key__: { get_param: dcae_private_key }
__dcaeos_private_network_name__: { get_attr: [oam_onap, name] }
__dcaeos_public_network_name__: { get_param: public_net_name }
__dcaeos_ubuntu_1604_image__: { get_param: ubuntu_1604_image }
__dcaeos_centos_7_image__: { get_param: dcae_centos_7_image }
- __dcaeos_security_group__ : { get_param: dcae_security_group }
__dcaeos_flavor_id__: { get_param: flavor_medium }
+ __dcaeos_flavor_id_cdap__: { get_param: flavor_xlarge }
__dcaeos_dnsaas_config_enabled__: { get_param: dnsaas_config_enabled }
__dcaeos_dnsaas_region__: { get_param: dnsaas_region }
__dcaeos_dnsaas_keystone_url__: { get_param: dnsaas_keystone_url }
@@ -1795,6 +1834,8 @@ resources:
echo "__dcae_float_ip__" > /opt/config/dcae_float_ip.txt
echo "__dns_ip_addr__" > /opt/config/dns_ip_addr.txt
echo "__external_dns__" > /opt/config/external_dns.txt
+ echo "__dns_forwarder__" > /opt/config/dns_forwarder.txt
+ echo "__dcae_domain__" > /opt/config/dcae_domain.txt
# conf for the OpenStack env where DCAE is deployed
echo "__openstack_keystone_url__" > /opt/config/openstack_keystone_url.txt
echo "__dcaeos_cloud_env__" > /opt/config/cloud_env.txt
@@ -1814,6 +1855,7 @@ resources:
echo "__dcaeos_centos_7_image__" > /opt/config/centos_7_image.txt
echo "__dcaeos_security_group__" > /opt/config/security_group.txt
echo "__dcaeos_flavor_id__" > /opt/config/flavor_id.txt
+ echo "__dcaeos_flavor_id_cdap__" > /opt/config/flavor_id_cdap.txt
echo "__dcaeos_dnsaas_config_enabled__" > /opt/config/dnsaas_config_enabled.txt
echo "__dcaeos_dnsaas_region__" > /opt/config/dnsaas_region.txt
echo "__dcaeos_dnsaas_keystone_url__" > /opt/config/dnsaas_keystone_url.txt