| name | fabric-slice-create |
| description | Create FABRIC experiment slices with nodes, components, and networks |
| allowed-tools | ["Read","Grep","Glob","Write","Edit","Bash"] |
Instructions
When invoked, generate code to create a FABRIC experiment slice. Ask the user about:
- Slice name
- Number and type of nodes (cores, RAM, disk, image, site)
- Any special components (GPUs, NICs, NVMe, FPGAs)
- Network connectivity needs (L2, L3/FABnet, none)
- Post-boot configuration needs
Generate complete, working code including error handling and cleanup on failure.
Use the modern API patterns:
- For networks: create the network first, then use
iface.set_mode('auto') and net.add_interface(iface)
- For L3 routing: use
node.add_route(subnet=fablib.FABNETV4_SUBNET, next_hop=net.get_gateway())
- For node FABnet shortcut: use
node.add_fabnet() for simple cases
API Reference
Creating a Slice
slice = fablib.new_slice(name="my-slice") -> Slice
Adding Nodes
node = slice.add_node(
name: str,
site: str = None,
cores: int = 2,
ram: int = 8,
disk: int = 10,
image: str = None,
instance_type: str = None,
host: str = None,
user_data: dict = {},
validate: bool = False,
raise_exception: bool = True,
) -> Node
Adding Components to Nodes
component = node.add_component(
model: str = None,
name: str = None,
) -> Component
ifaces = component.get_interfaces()
iface = ifaces[0]
Interface Configuration
iface.set_mode('auto')
net.add_interface(iface)
Adding Storage
component = node.add_storage(
name: str,
auto_mount: bool = False,
) -> Component
Simplified FABnet (on Node)
node.add_fabnet(
name: str = "FABNET",
net_type: str = "IPv4",
nic_type: str = "NIC_Basic",
routes: list = None,
subnet: ipaddress.ip_network = None,
)
Submitting a Slice
slice.submit(
wait: bool = True,
wait_timeout: int = 1800,
wait_interval: int = 20,
progress: bool = True,
wait_jupyter: str = "text",
post_boot_config: bool = True,
wait_ssh: bool = True,
extra_ssh_keys: list = None,
lease_start_time: datetime = None,
)
Validation
node = slice.add_node(name="Node1", validate=True, raise_exception=False)
slice.validate()
Patterns
Basic Single Node
from fabrictestbed_extensions.fablib.fablib import FablibManager
fablib = FablibManager()
slice = fablib.new_slice(name="my-experiment")
node = slice.add_node(
name="node1",
site="TACC",
cores=4,
ram=16,
disk=50,
image="default_ubuntu_24",
)
slice.submit()
print(f"SSH command: {node.get_ssh_command()}")
Multi-Node with Components
slice = fablib.new_slice(name="gpu-experiment")
gpu_site = fablib.get_random_site(
filter_function=lambda x: x["rtx6000_available"] > 0
)
gpu_node = slice.add_node(name="gpu-node", site=gpu_site, cores=8, ram=32, disk=100)
gpu_node.add_component(model="GPU_RTX6000", name="gpu1")
nic_node = slice.add_node(name="nic-node", site=gpu_site, cores=4, ram=16, disk=50)
nic_node.add_component(model="NIC_ConnectX_6", name="nic1")
slice.submit()
Slice with L2 Network (Auto IP)
from ipaddress import IPv4Network
slice = fablib.new_slice(name="l2-network")
site = fablib.get_random_site()
subnet = IPv4Network("192.168.1.0/24")
net = slice.add_l2network(name="lan", subnet=subnet)
node1 = slice.add_node(name="node1", site=site)
iface1 = node1.add_component(model="NIC_Basic", name="nic1").get_interfaces()[0]
iface1.set_mode('auto')
net.add_interface(iface1)
node2 = slice.add_node(name="node2", site=site)
iface2 = node2.add_component(model="NIC_Basic", name="nic1").get_interfaces()[0]
iface2.set_mode('auto')
net.add_interface(iface2)
slice.submit()
node2_addr = node2.get_interface(network_name="lan").get_ip_addr()
stdout, stderr = node1.execute(f"ping -c 5 {node2_addr}")
Slice with FABnet IPv4 (Cross-Site L3)
from ipaddress import IPv4Network
slice = fablib.new_slice(name="fabnet-experiment")
[site1, site2] = fablib.get_random_sites(count=2)
net1 = slice.add_l3network(name="net1", type="IPv4")
net2 = slice.add_l3network(name="net2", type="IPv4")
node1 = slice.add_node(name="node1", site=site1)
iface1 = node1.add_component(model="NIC_Basic", name="nic1").get_interfaces()[0]
iface1.set_mode('auto')
net1.add_interface(iface1)
node1.add_route(subnet=fablib.FABNETV4_SUBNET, next_hop=net1.get_gateway())
node2 = slice.add_node(name="node2", site=site2)
iface2 = node2.add_component(model="NIC_Basic", name="nic1").get_interfaces()[0]
iface2.set_mode('auto')
net2.add_interface(iface2)
node2.add_route(subnet=fablib.FABNETV4_SUBNET, next_hop=net2.get_gateway())
slice.submit()
node2_addr = node2.get_interface(network_name="net2").get_ip_addr()
stdout, stderr = node1.execute(f"ping -c 5 {node2_addr}")
Simplified FABnet (Using node.add_fabnet)
slice = fablib.new_slice(name="simple-fabnet")
node1 = slice.add_node(name="node1", site="TACC")
node1.add_fabnet(net_type="IPv4")
node2 = slice.add_node(name="node2", site="UCSD")
node2.add_fabnet(net_type="IPv4")
slice.submit()
for node in slice.get_nodes():
iface = node.get_interface(network_name="FABNET")
print(f"{node.get_name()}: {iface.get_ip_addr()}")
Error Handling Pattern
try:
slice = fablib.new_slice(name="safe-experiment")
node = slice.add_node(name="node1", cores=4, ram=16, disk=50)
slice.submit()
except Exception as e:
print(f"Slice creation failed: {e}")
try:
slice.delete()
except:
pass
raise
Non-Blocking Submit
slice = fablib.new_slice(name="async-experiment")
node = slice.add_node(name="node1")
slice.submit(wait=False)
slice_id = slice.get_slice_id()
slice = fablib.get_slice(slice_id=slice_id)
slice.wait_ssh(progress=True)
slice.post_boot_config()
Future-Scheduled Slice
from datetime import datetime, timezone, timedelta
start = datetime.now(timezone.utc) + timedelta(days=1)
slice = fablib.new_slice(name="scheduled-experiment")
node = slice.add_node(name="node1", site="TACC")
slice.submit(lease_start_time=start)
Node with NVMe Storage
site = fablib.get_random_site(
filter_function=lambda x: x["nvme_available"] > 0
)
slice = fablib.new_slice(name="storage-experiment")
node = slice.add_node(name="storage-node", site=site, cores=4, ram=16, disk=50)
node.add_component(model="NVME_P4510", name="nvme1")
slice.submit()
storage = node.get_storage("nvme1")
storage.configure_nvme()