#!/usr/bin/env python3 import os import sys import argparse import requests from urllib.parse import urljoin class NetBoxManager: def __init__(self, url, token): self.base_url = url.rstrip('/') self.api_url = urljoin(self.base_url + '/', 'api/') self.headers = { 'Authorization': f'Token {token}', 'Content-Type': 'application/json', 'Accept': 'application/json' } self.session = requests.Session() self.session.headers.update(self.headers) def get(self, endpoint, params=None): """Make GET request to NetBox API""" url = urljoin(self.api_url, endpoint.lstrip('/')) response = self.session.get(url, params=params) response.raise_for_status() return response.json() def post(self, endpoint, data): """Make POST request to NetBox API""" url = urljoin(self.api_url, endpoint.lstrip('/')) response = self.session.post(url, json=data) if response.status_code not in [200, 201]: print(f"Error creating {endpoint}: {response.status_code}") print(f"Response: {response.text}") response.raise_for_status() return response.json() def create_site(self, name, slug=None, status='active', comments='', physical_address=''): """Create a new site""" if not slug: slug = name.lower().replace(' ', '-').replace('_', '-') site_data = { 'name': name, 'slug': slug, 'status': status, 'comments': comments } if physical_address: site_data['physical_address'] = physical_address return self.post('dcim/sites/', site_data) def create_site(site_name, site_comments='', physical_address='', slug=None): """ Create a site in NetBox Args: site_name: Name of the site site_comments: Comments for the site physical_address: Physical address of the site slug: Custom slug for the site (defaults to lowercase hyphenated name) """ # Get API token from environment variable or use the one from CLAUDE.md api_token = os.environ.get('NETBOX_KEY', 'e50298f7fd20f7fd6f1931f635511b34f6e8cfde') # Initialize NetBox client nb = NetBoxManager('https://netbox.vntx.net/', api_token) print(f"=== Creating {site_name} Site in NetBox ===\n") # Check if site exists site_response = nb.get('dcim/sites/', params={'name': site_name}) if site_response['count'] == 0: # Create site print(f"Creating {site_name} site...") try: site = nb.create_site( name=site_name, slug=slug, status='active', comments=site_comments, physical_address=physical_address ) site_id = site['id'] print(f"✓ Created {site_name} site (ID: {site_id})") print(f" Name: {site['name']}") print(f" Slug: {site['slug']}") print(f" Status: {site['status']['label']}") if site_comments: print(f" Comments: {site_comments}") if physical_address: print(f" Address: {physical_address}") return site_id except Exception as e: print(f"✗ Failed to create {site_name} site: {e}") return None else: site = site_response['results'][0] site_id = site['id'] print(f"✓ {site_name} site already exists (ID: {site_id})") print(f" Name: {site['name']}") print(f" Slug: {site['slug']}") print(f" Status: {site['status']['label']}") if site.get('comments'): print(f" Comments: {site['comments']}") return site_id def main(): parser = argparse.ArgumentParser(description='Create a site in NetBox') parser.add_argument('site_name', help='Name of the site') parser.add_argument('--comments', help='Comments for the site') parser.add_argument('--address', help='Physical address of the site') parser.add_argument('--slug', help='Custom slug for the site') args = parser.parse_args() site_id = create_site( site_name=args.site_name, site_comments=args.comments or '', physical_address=args.address or '', slug=args.slug ) if site_id: print(f"\nSuccess! Site created with ID: {site_id}") print(f"You can now add devices to this site using:") print(f" python3 create_site_and_router.py \"{args.site_name}\" --router-name ") return 0 else: print(f"\nFailed to create site.") return 1 if __name__ == "__main__": sys.exit(main())